Import Cobalt 2.9617 2016-08-17
diff --git a/src/README.md b/src/README.md index 2d2efba..fb912c9 100644 --- a/src/README.md +++ b/src/README.md
@@ -180,17 +180,25 @@ Here's a quick and dirty guide to get to build the code on Linux. - 1. Install the provided `depot_tools` archive into your favorite directory. It - has been slightly modified from Chromium's `depot_tools`. + 1. Pull `depot_tools` into your favorite directory. It has been slightly + modified from Chromium's `depot_tools`. + + git clone https://cobalt.googlesource.com/depot_tools + 2. Add that directory to the end of your `$PATH`. - 3. Ensure you have these packages installed: `sudo apt-get install - libgles2-mesa-dev libpulse-dev libavformat-dev libavresample-dev - libasound2-dev libxrender-dev libxcomposite-dev` + 3. Ensure you have these packages installed: + + sudo apt-get install libgles2-mesa-dev libpulse-dev libavformat-dev \ + libavresample-dev libasound2-dev libxrender-dev libxcomposite-dev + 4. Ensure you have the standard C++ header files installed (e.g. `libstdc++-4.8-dev`). - 5. Remove bison-3 and install bison-2.7, or just make sure that bison-2.7 is - before bison-3 on your `$PATH`. (NOTE: We plan on moving to bison-3 in the - future.) + 5. For now, we also require ruby: + + sudo apt-get install ruby + + 6. Remove bison-3 and install bison-2.7. (NOTE: We plan on moving to bison-3 + in the future.) $ sudo apt-get remove bison $ sudo apt-get install m4 @@ -203,27 +211,28 @@ $ bison --version bison (GNU Bison) 2.7.12-4996 - 6. (From this directory) run GYP: + 7. (From this directory) run GYP: cobalt/build/gyp_cobalt -C debug linux-x64x11 - 7. If you get a "clang not found" error, add the path to Cobalt's clang to + 8. If you get a "clang not found" error, add the path to Cobalt's clang to your `$PATH` and rerun `gyp_cobalt` as above. For example: `/path/to/cobalt/src/third_party/llvm-build/Release+Asserts/bin` - 8. Run Ninja: + 9. Run Ninja: ninja -C out/linux-x64x11_debug cobalt - 9. Run Cobalt: + 10. Run Cobalt: out/linux-x64x11_debug/cobalt [--url=<url>] * If you want to use `http` instead of `https`, you must pass the `--allow_http` flag to the Cobalt command-line. * If you want to connect to an `https` host that doesn't have a - globally-validatable certificate, you must pass the + certificate validatable by our set of root CAs, you must pass the `--ignore_certificate_errors` flag to the Cobalt command-line. - * See `cobalt/browser/switches.cc` for more command-line options. + * See [`cobalt/browser/switches.cc`](cobalt/browser/switches.cc) for more + command-line options. ## Build Types
diff --git a/src/base/base.gyp b/src/base/base.gyp index 3838ff6..bd8a374 100644 --- a/src/base/base.gyp +++ b/src/base/base.gyp
@@ -1273,7 +1273,7 @@ 'variables': { 'executable_name': 'base_unittests', }, - 'includes': [ '../cobalt/build/deploy.gypi' ], + 'includes': [ '../starboard/build/deploy.gypi' ], }, ], }],
diff --git a/src/base/base_paths_starboard.cc b/src/base/base_paths_starboard.cc index 2b8a14a..fbad177 100644 --- a/src/base/base_paths_starboard.cc +++ b/src/base/base_paths_starboard.cc
@@ -91,7 +91,7 @@ return PathProviderStarboard(base::DIR_CACHE, result); } - NOTREACHED() << "key = " << key; + DLOG(ERROR) << "Could not resolve path for key = " << key; return false; }
diff --git a/src/base/circular_buffer_shell.cc b/src/base/circular_buffer_shell.cc index a41d89a..ae58e4b 100644 --- a/src/base/circular_buffer_shell.cc +++ b/src/base/circular_buffer_shell.cc
@@ -37,7 +37,8 @@ length_(0), read_position_(0) { if (reserve_type == kReserve) { - IncreaseCapacityTo(max_capacity_); + base::AutoLock l(lock_); + IncreaseCapacityTo_Locked(max_capacity_); } } @@ -65,7 +66,7 @@ if (destination == NULL) length = 0; - ReadAndAdvanceUnchecked(destination, length, bytes_read); + ReadAndAdvanceUnchecked_Locked(destination, length, bytes_read); } void CircularBufferShell::Peek(void* destination, @@ -77,12 +78,12 @@ if (destination == NULL) length = 0; - ReadUnchecked(destination, length, source_offset, bytes_peeked); + ReadUnchecked_Locked(destination, length, source_offset, bytes_peeked); } void CircularBufferShell::Skip(size_t length, size_t* bytes_skipped) { base::AutoLock l(lock_); - ReadAndAdvanceUnchecked(NULL, length, bytes_skipped); + ReadAndAdvanceUnchecked_Locked(NULL, length, bytes_skipped); } bool CircularBufferShell::Write(const void* source, @@ -93,7 +94,7 @@ if (source == NULL) length = 0; - if (!EnsureCapacityToWrite(length)) { + if (!EnsureCapacityToWrite_Locked(length)) { return false; } @@ -102,12 +103,13 @@ size_t remaining = length - produced; // In this pass, write up to the contiguous space left. - size_t to_write = std::min(remaining, capacity_ - GetWritePosition()); + size_t to_write = + std::min(remaining, capacity_ - GetWritePosition_Locked()); if (to_write == 0) break; // Copy this segment and do the accounting. - void* destination = GetWritePointer(); + void* destination = GetWritePointer_Locked(); const void* src = add_to_pointer(source, produced); memcpy(destination, src, to_write); length_ += to_write; @@ -124,12 +126,14 @@ return length_; } -void CircularBufferShell::ReadUnchecked(void* destination, - size_t destination_length, - size_t source_offset, - size_t* bytes_read) const { +void CircularBufferShell::ReadUnchecked_Locked(void* destination, + size_t destination_length, + size_t source_offset, + size_t* bytes_read) const { DCHECK(destination != NULL || bytes_read != NULL); + lock_.AssertAcquired(); + size_t dummy = 0; if (!bytes_read) { bytes_read = &dummy; @@ -168,9 +172,12 @@ *bytes_read = consumed; } -void CircularBufferShell::ReadAndAdvanceUnchecked(void* destination, - size_t destination_length, - size_t* bytes_read) { +void CircularBufferShell::ReadAndAdvanceUnchecked_Locked( + void* destination, + size_t destination_length, + size_t* bytes_read) { + lock_.AssertAcquired(); + size_t dummy = 0; if (!bytes_read) { bytes_read = &dummy; @@ -182,20 +189,26 @@ return; } - ReadUnchecked(destination, destination_length, 0, bytes_read); + ReadUnchecked_Locked(destination, destination_length, 0, bytes_read); length_ -= *bytes_read; read_position_ = (read_position_ + *bytes_read) % capacity_; } -void* CircularBufferShell::GetWritePointer() const { - return add_to_pointer(buffer_, GetWritePosition()); +void* CircularBufferShell::GetWritePointer_Locked() const { + lock_.AssertAcquired(); + + return add_to_pointer(buffer_, GetWritePosition_Locked()); } -size_t CircularBufferShell::GetWritePosition() const { +size_t CircularBufferShell::GetWritePosition_Locked() const { + lock_.AssertAcquired(); + return (read_position_ + length_) % capacity_; } -bool CircularBufferShell::EnsureCapacityToWrite(size_t length) { +bool CircularBufferShell::EnsureCapacityToWrite_Locked(size_t length) { + lock_.AssertAcquired(); + if (capacity_ - length_ < length) { size_t capacity = std::max(2 * capacity_, length_ + length); if (capacity > max_capacity_) @@ -206,13 +219,15 @@ return false; } - return IncreaseCapacityTo(capacity); + return IncreaseCapacityTo_Locked(capacity); } return true; } -bool CircularBufferShell::IncreaseCapacityTo(size_t capacity) { +bool CircularBufferShell::IncreaseCapacityTo_Locked(size_t capacity) { + lock_.AssertAcquired(); + if (capacity <= capacity_) { return true; } @@ -237,7 +252,7 @@ size_t length = length_; // Copy the data over to the new buffer. - ReadUnchecked(buffer, length_, 0, NULL); + ReadUnchecked_Locked(buffer, length_, 0, NULL); // Adjust the accounting. length_ = length; @@ -248,4 +263,19 @@ return true; } +size_t CircularBufferShell::GetMaxCapacity() const { + base::AutoLock l(lock_); + + return max_capacity_; +} + +void CircularBufferShell::IncreaseMaxCapacityTo(size_t new_max_capacity) { + base::AutoLock l(lock_); + + DCHECK_GT(new_max_capacity, max_capacity_); + if (new_max_capacity > max_capacity_) { + max_capacity_ = new_max_capacity; + } +} + } // namespace base
diff --git a/src/base/circular_buffer_shell.h b/src/base/circular_buffer_shell.h index 4350af1..d7b364a 100644 --- a/src/base/circular_buffer_shell.h +++ b/src/base/circular_buffer_shell.h
@@ -17,8 +17,8 @@ public: enum ReserveType { kDoNotReserve, kReserve }; - CircularBufferShell(size_t max_capacity, - ReserveType reserve_type = kDoNotReserve); + explicit CircularBufferShell(size_t max_capacity, + ReserveType reserve_type = kDoNotReserve); ~CircularBufferShell(); // Clears out all data in the buffer, releasing any allocated memory. @@ -53,16 +53,23 @@ // Returns the length of the data left in the buffer to read. size_t GetLength() const; + // Returns the maximum capacity this circular buffer can grow to. + size_t GetMaxCapacity() const; + + // Increase the max capacity to |new_max_capacity| which has to be greater + // than the previous one. The content of the class will be kept. + void IncreaseMaxCapacityTo(size_t new_max_capacity); + private: // Ensures that there is enough capacity to write length bytes to the // buffer. Returns false if it was unable to ensure that capacity due to an // allocation error, or if it would surpass the configured maximum capacity. - bool EnsureCapacityToWrite(size_t length); + bool EnsureCapacityToWrite_Locked(size_t length); // Increases the capacity to the given absolute size in bytes. Returns false // if there was an allocation error, or it would surpass the configured // maximum capacity. - bool IncreaseCapacityTo(size_t capacity); + bool IncreaseCapacityTo_Locked(size_t capacity); // Private workhorse for Read without the parameter validation or locking. // When |destination| is NULL, it purely calculates the the bytes that would @@ -71,24 +78,24 @@ // length. It is caller's responsibility to adjust |read_position_| and // |length_| according to the return value, which is the actual number of // bytes read. - void ReadUnchecked(void* destination, - size_t destination_length, - size_t source_offset, - size_t* bytes_read) const; + void ReadUnchecked_Locked(void* destination, + size_t destination_length, + size_t source_offset, + size_t* bytes_read) const; // The same the as above functions except that it also advance the // |read_position_| and adjust the |length_| accordingly. - void ReadAndAdvanceUnchecked(void* destination, - size_t destination_length, - size_t* bytes_read); + void ReadAndAdvanceUnchecked_Locked(void* destination, + size_t destination_length, + size_t* bytes_read); // Gets a pointer to the current write position. - void* GetWritePointer() const; + void* GetWritePointer_Locked() const; // Gets the current write position. - size_t GetWritePosition() const; + size_t GetWritePosition_Locked() const; - const size_t max_capacity_; + size_t max_capacity_; void* buffer_; size_t capacity_; size_t length_;
diff --git a/src/base/circular_buffer_shell_unittest.cc b/src/base/circular_buffer_shell_unittest.cc index 0d4aa1c..209ec74 100644 --- a/src/base/circular_buffer_shell_unittest.cc +++ b/src/base/circular_buffer_shell_unittest.cc
@@ -452,3 +452,78 @@ EXPECT_EQ(circular_buffer->GetLength(), 0); } } + +TEST(CircularBufferShellTest, IncreaseMaxCapacityTo) { + ClearPos(); + + scoped_ptr<base::CircularBufferShell> circular_buffer( + new base::CircularBufferShell(0)); + EXPECT_EQ(circular_buffer->GetMaxCapacity(), 0); + + // Increase max capacity by 20 to allow for expanding. + circular_buffer->IncreaseMaxCapacityTo(20); + EXPECT_EQ(circular_buffer->GetMaxCapacity(), 20); + + // Set the size with the first write. + TestWrite(circular_buffer.get(), 10); + + // Expand to the full capacity with the second write. + TestWrite(circular_buffer.get(), 10); + + // Verify if the buffer is full by check the failure of writing one byte. + char ch = 'a'; + size_t bytes_written = 0; + ASSERT_FALSE(circular_buffer->Write(&ch, 1, &bytes_written)); + + // Increase max capacity to 30 to allow for further expanding. + circular_buffer->IncreaseMaxCapacityTo(30); + EXPECT_EQ(circular_buffer->GetMaxCapacity(), 30); + + // Expand to capacity with the fourth write. + TestWrite(circular_buffer.get(), 10); + + // Verify if the buffer is full by check the failure of writing one byte. + ASSERT_FALSE(circular_buffer->Write(&ch, 1, &bytes_written)); + + // Drain the circular_buffer. + EXPECT_EQ(circular_buffer->GetLength(), 30); + TestRead(circular_buffer.get(), 30); + EXPECT_EQ(circular_buffer->GetLength(), 0); +} + +TEST(CircularBufferShellTest, IncreaseMaxCapacityToWrapped) { + ClearPos(); + + scoped_ptr<base::CircularBufferShell> circular_buffer( + new base::CircularBufferShell(10)); + EXPECT_EQ(circular_buffer->GetMaxCapacity(), 10); + + // Expand to the full capacity with the first write. + TestWrite(circular_buffer.get(), 10); + + // Partial read + TestRead(circular_buffer.get(), 5); + + // The buffer is wrapped after the second write. + TestWrite(circular_buffer.get(), 5); + + // Verify if the buffer is full by check the failure of writing one byte. + char ch = 'a'; + size_t bytes_written = 0; + ASSERT_FALSE(circular_buffer->Write(&ch, 1, &bytes_written)); + + // Increase max capacity to 20 to allow for further expanding. + circular_buffer->IncreaseMaxCapacityTo(20); + EXPECT_EQ(circular_buffer->GetMaxCapacity(), 20); + + // Expand to capacity with the fourth write. + TestWrite(circular_buffer.get(), 10); + + // Verify if the buffer is full by check the failure of writing one byte. + ASSERT_FALSE(circular_buffer->Write(&ch, 1, &bytes_written)); + + // Drain the circular_buffer. + EXPECT_EQ(circular_buffer->GetLength(), 20); + TestRead(circular_buffer.get(), 20); + EXPECT_EQ(circular_buffer->GetLength(), 0); +}
diff --git a/src/cobalt/audio/audio.gyp b/src/cobalt/audio/audio.gyp index 743b695..f13d2c3 100644 --- a/src/cobalt/audio/audio.gyp +++ b/src/cobalt/audio/audio.gyp
@@ -73,7 +73,7 @@ 'variables': { 'executable_name': 'audio_test', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, ], }
diff --git a/src/cobalt/base/base.gyp b/src/cobalt/base/base.gyp index c535446..6dc3864 100644 --- a/src/cobalt/base/base.gyp +++ b/src/cobalt/base/base.gyp
@@ -76,7 +76,7 @@ '<(DEPTH)/base/base.gyp:base', ], 'conditions': [ - ['OS != "starboard" or target_arch == "ps4"', { + ['OS != "starboard"', { 'includes': [ 'copy_i18n_data.gypi', ], @@ -107,7 +107,7 @@ 'variables': { 'executable_name': 'base_test', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, ], }
diff --git a/src/cobalt/bindings/code_generator_cobalt.py b/src/cobalt/bindings/code_generator_cobalt.py index 7b6b66d..2aa694a 100644 --- a/src/cobalt/bindings/code_generator_cobalt.py +++ b/src/cobalt/bindings/code_generator_cobalt.py
@@ -122,6 +122,12 @@ return setter_operation +def get_indexed_property_deleter(interface): + deleter_operation = get_indexed_special_operation(interface, 'deleter') + assert not deleter_operation or len(deleter_operation.arguments) == 1 + return deleter_operation + + def get_named_special_operation(interface, special): special_operations = list( operation for operation in interface.operations @@ -471,6 +477,8 @@ interface, get_indexed_property_getter(interface)) context['indexed_property_setter'] = contexts.special_method_context( interface, get_indexed_property_setter(interface)) + context['indexed_property_deleter'] = contexts.special_method_context( + interface, get_indexed_property_deleter(interface)) context['named_property_getter'] = contexts.special_method_context( interface, get_named_property_getter(interface)) context['named_property_setter'] = contexts.special_method_context(
diff --git a/src/cobalt/bindings/contexts.py b/src/cobalt/bindings/contexts.py index 0b91273..207d593 100644 --- a/src/cobalt/bindings/contexts.py +++ b/src/cobalt/bindings/contexts.py
@@ -37,6 +37,7 @@ 'short': 'int16_t', 'unsigned short': 'uint16_t', 'long': 'int32_t', + 'long long': 'int64_t', 'unsigned long': 'uint32_t', 'unsigned long long': 'uint64_t', 'float': 'float', @@ -211,28 +212,74 @@ } +def get_non_optional_arguments(arguments): + """Create non optional arguments list.""" + return [argument for argument in arguments + if not argument['is_optional'] and not argument['is_variadic']] + + +def get_optional_arguments(arguments): + """Create optional arguments list.""" + return [argument for argument in arguments if argument['is_optional']] + + +def get_num_default_arguments(optional_arguments): + """Return the number of default arguments.""" + num_default_arguments = 0 + + for argument in optional_arguments: + if argument['default_value'] is not None: + num_default_arguments += 1 + + return num_default_arguments + + +def get_variadic_argument(arguments): + """Return the variadic argument.""" + length = len(arguments) + + if length > 0 and arguments[length - 1]['is_variadic']: + return arguments[length - 1] + else: + return [] + + +def partial_context(interface, operation): + """Create partial template values for generating bindings.""" + arguments = [argument_context(interface, a) for a in operation.arguments] + optional_arguments = get_optional_arguments(arguments) + num_default_arguments = get_num_default_arguments(optional_arguments) + return { + 'arguments': arguments, + 'non_optional_arguments': get_non_optional_arguments(arguments), + 'optional_arguments': optional_arguments, + 'num_default_arguments': num_default_arguments, + 'variadic_argument': get_variadic_argument(arguments), + 'has_non_default_optional_arguments': len(optional_arguments) > + num_default_arguments, + } + + def constructor_context(interface, constructor): """Create template values for generating constructor bindings.""" - return { - 'arguments': - [argument_context(interface, a) for a in constructor.arguments], - 'call_with': - interface.extended_attributes.get('ConstructorCallWith', None), - 'raises_exception': - (interface.extended_attributes.get('RaisesException', None) - == 'Constructor'), + context = { + 'call_with': interface.extended_attributes.get('ConstructorCallWith', + None), + 'raises_exception': (interface.extended_attributes.get( + 'RaisesException', None) == 'Constructor'), } + context.update(partial_context(interface, constructor)) + return context + def method_context(interface, operation): """Create template values for generating method bindings.""" - return { + context = { 'idl_name': operation.name, 'name': capitalize_function_name(operation.name), 'type': typed_object_to_cobalt_type(interface, operation), 'is_static': operation.is_static, - 'arguments': - [argument_context(interface, a) for a in operation.arguments], 'call_with': operation.extended_attributes.get('CallWith', None), 'raises_exception': operation.extended_attributes.has_key('RaisesException'), @@ -240,6 +287,9 @@ 'unsupported': 'NotSupported' in operation.extended_attributes, } + context.update(partial_context(interface, operation)) + return context + def stringifier_context(interface): """Create template values for generating stringifier."""
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCDOMStringTestInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCDOMStringTestInterface.cc index 38676ea..6db2e1d 100644 --- a/src/cobalt/bindings/generated/jsc/testing/JSCDOMStringTestInterface.cc +++ b/src/cobalt/bindings/generated/jsc/testing/JSCDOMStringTestInterface.cc
@@ -107,6 +107,10 @@ JSC::ExecState* exec_state, JSC::JSValue slot_base, JSC::PropertyName property_name); +JSC::JSValue getJSreadOnlyTokenProperty( + JSC::ExecState* exec_state, + JSC::JSValue slot_base, + JSC::PropertyName property_name); JSC::JSValue getJSnullIsEmptyProperty( JSC::ExecState* exec_state, JSC::JSValue slot_base, @@ -451,6 +455,12 @@ 0, JSC::NoIntrinsic }, + { "readOnlyTokenProperty", + JSC::DontDelete | JSC::ReadOnly, + reinterpret_cast<intptr_t>(getJSreadOnlyTokenProperty), + 0, + JSC::NoIntrinsic + }, { "nullIsEmptyProperty", JSC::DontDelete , reinterpret_cast<intptr_t>(getJSnullIsEmptyProperty), @@ -474,7 +484,7 @@ // static const JSC::HashTable JSCDOMStringTestInterface::property_table_prototype = { - 20, // compactSize + 21, // compactSize 15, // compactSizeMask property_table_values, NULL // table allocated at runtime @@ -744,6 +754,25 @@ return result; } +JSC::JSValue getJSreadOnlyTokenProperty( + JSC::ExecState* exec_state, + JSC::JSValue slot_base, + JSC::PropertyName property_name) { + TRACE_EVENT0("JSCDOMStringTestInterface", "get readOnlyTokenProperty"); + JSCGlobalObject* global_object = + JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject()); + DOMStringTestInterface* impl = + GetWrappableOrSetException<DOMStringTestInterface>(exec_state, slot_base); + if (!impl) { + return exec_state->exception(); + } + + JSC::JSValue result = ToJSValue( + global_object, + impl->read_only_token_property()); + return result; +} + JSC::JSValue getJSnullIsEmptyProperty( JSC::ExecState* exec_state, JSC::JSValue slot_base,
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCDerivedInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCDerivedInterface.cc index 810b872..5a523e7 100644 --- a/src/cobalt/bindings/generated/jsc/testing/JSCDerivedInterface.cc +++ b/src/cobalt/bindings/generated/jsc/testing/JSCDerivedInterface.cc
@@ -99,6 +99,7 @@ JSC::ExecState* exec_state, JSC::JSValue slot_base, JSC::PropertyName property_name); +JSC::EncodedJSValue constructorJSDerivedInterface(JSC::ExecState*); JSC::EncodedJSValue functionJSderivedOperation(JSC::ExecState*); // These are declared unconditionally, but only defined if needed by the @@ -181,13 +182,6 @@ return JSC::CallTypeNone; } - // static override. This prevents this object from being called as a - // constructor, throwing a TypeError if the user attempts to do so. - // - // This method is defined when no constructors are defined on the IDL. - static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) { - return JSC::ConstructTypeNone; - } private: typedef ConstructorBase BaseClass; @@ -275,8 +269,7 @@ &s_info); const int kNumArguments = 0; - // NativeExecutable must be non-null even if this is not actually callable. - JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL); + JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, &constructorJSDerivedInterface); // Create the new interface object. InterfaceObject* new_interface_object = @@ -632,6 +625,16 @@ return result; } +JSC::EncodedJSValue constructorJSDerivedInterface(JSC::ExecState* exec_state) { + JSCGlobalObject* global_object = + JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject()); + JSCExceptionState exception_state(global_object); + scoped_refptr<DerivedInterface> new_object = + new DerivedInterface(); + return JSC::JSValue::encode(ToJSValue(global_object, new_object)); + +} + JSC::EncodedJSValue functionJSderivedOperation( JSC::ExecState* exec_state) { TRACE_EVENT0("JSCDerivedInterface", "call derivedOperation");
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCIndexedGetterInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCIndexedGetterInterface.cc index d7bb2ad..550c106 100644 --- a/src/cobalt/bindings/generated/jsc/testing/JSCIndexedGetterInterface.cc +++ b/src/cobalt/bindings/generated/jsc/testing/JSCIndexedGetterInterface.cc
@@ -99,6 +99,7 @@ JSC::ExecState* exec_state, JSC::JSValue slot_base, JSC::PropertyName property_name); +JSC::EncodedJSValue functionJSindexedDeleter(JSC::ExecState*); JSC::EncodedJSValue functionJSindexedGetter(JSC::ExecState*); JSC::EncodedJSValue functionJSindexedSetter(JSC::ExecState*); JSC::JSValue IndexedPropertyGetter(JSC::ExecState* exec_state, @@ -332,6 +333,12 @@ }; const JSC::HashTableValue JSCIndexedGetterInterface::Prototype::property_table_values[] = { + { "indexedDeleter", + JSC::DontDelete | JSC::Function, + reinterpret_cast<intptr_t>(functionJSindexedDeleter), + static_cast<intptr_t>(1), + JSC::NoIntrinsic + }, { "indexedGetter", JSC::DontDelete | JSC::Function, reinterpret_cast<intptr_t>(functionJSindexedGetter), @@ -355,8 +362,8 @@ // static const JSC::HashTable JSCIndexedGetterInterface::Prototype::property_table_prototype = { - 10, // compactSize - 7, // compactSizeMask + 19, // compactSize + 15, // compactSizeMask property_table_values, NULL // table allocated at runtime }; // JSCIndexedGetterInterface::Prototype::property_table_prototype @@ -744,6 +751,40 @@ return result; } +JSC::EncodedJSValue functionJSindexedDeleter( + JSC::ExecState* exec_state) { + TRACE_EVENT0("JSCIndexedGetterInterface", "call indexedDeleter"); + JSCGlobalObject* global_object = + JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject()); + JSCExceptionState exception_state(global_object); + JSC::JSObject* this_object = + exec_state->hostThisValue().toThisObject(exec_state); + IndexedGetterInterface* impl = + GetWrappableOrSetException<IndexedGetterInterface>(exec_state, this_object); + if (!impl) { + return JSC::JSValue::encode(exec_state->exception()); + } + + const size_t kMinArguments = 1; + if (exec_state->argumentCount() < kMinArguments) { + return JSC::throwVMNotEnoughArgumentsError(exec_state); + } + // Non-optional arguments + TypeTraits<uint32_t >::ConversionType index; + + DCHECK_LT(0, exec_state->argumentCount()); + FromJSValue(exec_state, + exec_state->argument(0), + kNoConversionFlags, + &exception_state, &index); + if (exception_state.is_exception_set()) { + return JSC::throwVMError(exec_state, exception_state.exception_object()); + } + impl->IndexedDeleter(index); + return JSC::JSValue::encode(JSC::jsUndefined()); + +} + JSC::EncodedJSValue functionJSindexedGetter( JSC::ExecState* exec_state) { TRACE_EVENT0("JSCIndexedGetterInterface", "call indexedGetter");
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCNumericTypesTestInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCNumericTypesTestInterface.cc index d24db6a..e76d0d6 100644 --- a/src/cobalt/bindings/generated/jsc/testing/JSCNumericTypesTestInterface.cc +++ b/src/cobalt/bindings/generated/jsc/testing/JSCNumericTypesTestInterface.cc
@@ -143,6 +143,22 @@ JSC::ExecState* exec, JSC::JSObject* this_object, JSC::JSValue value); +JSC::JSValue getJSlongLongProperty( + JSC::ExecState* exec_state, + JSC::JSValue slot_base, + JSC::PropertyName property_name); +void setJSlongLongProperty( + JSC::ExecState* exec, + JSC::JSObject* this_object, + JSC::JSValue value); +JSC::JSValue getJSunsignedLongLongProperty( + JSC::ExecState* exec_state, + JSC::JSValue slot_base, + JSC::PropertyName property_name); +void setJSunsignedLongLongProperty( + JSC::ExecState* exec, + JSC::JSObject* this_object, + JSC::JSValue value); JSC::JSValue getJSdoubleProperty( JSC::ExecState* exec_state, JSC::JSValue slot_base, @@ -164,6 +180,8 @@ JSC::EncodedJSValue functionJSdoubleArgumentOperation(JSC::ExecState*); JSC::EncodedJSValue functionJSdoubleReturnOperation(JSC::ExecState*); JSC::EncodedJSValue functionJSlongArgumentOperation(JSC::ExecState*); +JSC::EncodedJSValue functionJSlongLongArgumentOperation(JSC::ExecState*); +JSC::EncodedJSValue functionJSlongLongReturnOperation(JSC::ExecState*); JSC::EncodedJSValue functionJSlongReturnOperation(JSC::ExecState*); JSC::EncodedJSValue functionJSoctetArgumentOperation(JSC::ExecState*); JSC::EncodedJSValue functionJSoctetReturnOperation(JSC::ExecState*); @@ -172,6 +190,8 @@ JSC::EncodedJSValue functionJSunrestrictedDoubleArgumentOperation(JSC::ExecState*); JSC::EncodedJSValue functionJSunrestrictedDoubleReturnOperation(JSC::ExecState*); JSC::EncodedJSValue functionJSunsignedLongArgumentOperation(JSC::ExecState*); +JSC::EncodedJSValue functionJSunsignedLongLongArgumentOperation(JSC::ExecState*); +JSC::EncodedJSValue functionJSunsignedLongLongReturnOperation(JSC::ExecState*); JSC::EncodedJSValue functionJSunsignedLongReturnOperation(JSC::ExecState*); JSC::EncodedJSValue functionJSunsignedShortArgumentOperation(JSC::ExecState*); JSC::EncodedJSValue functionJSunsignedShortReturnOperation(JSC::ExecState*); @@ -432,6 +452,18 @@ static_cast<intptr_t>(1), JSC::NoIntrinsic }, + { "longLongArgumentOperation", + JSC::DontDelete | JSC::Function, + reinterpret_cast<intptr_t>(functionJSlongLongArgumentOperation), + static_cast<intptr_t>(1), + JSC::NoIntrinsic + }, + { "longLongReturnOperation", + JSC::DontDelete | JSC::Function, + reinterpret_cast<intptr_t>(functionJSlongLongReturnOperation), + static_cast<intptr_t>(0), + JSC::NoIntrinsic + }, { "longReturnOperation", JSC::DontDelete | JSC::Function, reinterpret_cast<intptr_t>(functionJSlongReturnOperation), @@ -480,6 +512,18 @@ static_cast<intptr_t>(1), JSC::NoIntrinsic }, + { "unsignedLongLongArgumentOperation", + JSC::DontDelete | JSC::Function, + reinterpret_cast<intptr_t>(functionJSunsignedLongLongArgumentOperation), + static_cast<intptr_t>(1), + JSC::NoIntrinsic + }, + { "unsignedLongLongReturnOperation", + JSC::DontDelete | JSC::Function, + reinterpret_cast<intptr_t>(functionJSunsignedLongLongReturnOperation), + static_cast<intptr_t>(0), + JSC::NoIntrinsic + }, { "unsignedLongReturnOperation", JSC::DontDelete | JSC::Function, reinterpret_cast<intptr_t>(functionJSunsignedLongReturnOperation), @@ -509,7 +553,7 @@ // static const JSC::HashTable JSCNumericTypesTestInterface::Prototype::property_table_prototype = { - 80, // compactSize + 84, // compactSize 63, // compactSizeMask property_table_values, NULL // table allocated at runtime @@ -615,6 +659,18 @@ reinterpret_cast<intptr_t>(setJSunsignedLongProperty), JSC::NoIntrinsic }, + { "longLongProperty", + JSC::DontDelete , + reinterpret_cast<intptr_t>(getJSlongLongProperty), + reinterpret_cast<intptr_t>(setJSlongLongProperty), + JSC::NoIntrinsic + }, + { "unsignedLongLongProperty", + JSC::DontDelete , + reinterpret_cast<intptr_t>(getJSunsignedLongLongProperty), + reinterpret_cast<intptr_t>(setJSunsignedLongLongProperty), + JSC::NoIntrinsic + }, { "doubleProperty", JSC::DontDelete , reinterpret_cast<intptr_t>(getJSdoubleProperty), @@ -632,7 +688,7 @@ // static const JSC::HashTable JSCNumericTypesTestInterface::property_table_prototype = { - 39, // compactSize + 41, // compactSize 31, // compactSizeMask property_table_values, NULL // table allocated at runtime @@ -1113,6 +1169,98 @@ } } +JSC::JSValue getJSlongLongProperty( + JSC::ExecState* exec_state, + JSC::JSValue slot_base, + JSC::PropertyName property_name) { + TRACE_EVENT0("JSCNumericTypesTestInterface", "get longLongProperty"); + JSCGlobalObject* global_object = + JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject()); + NumericTypesTestInterface* impl = + GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, slot_base); + if (!impl) { + return exec_state->exception(); + } + + JSC::JSValue result = ToJSValue( + global_object, + impl->long_long_property()); + return result; +} + +void setJSlongLongProperty( + JSC::ExecState* exec_state, + JSC::JSObject* this_object, + JSC::JSValue value) { + TRACE_EVENT0("JSCNumericTypesTestInterface", "set longLongProperty"); + JSCGlobalObject* global_object = + JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject()); + JSCExceptionState exception_state(global_object); + NumericTypesTestInterface* impl = + GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object); + if (!impl) { + return; + } + TypeTraits<int64_t >::ConversionType cobalt_value; + FromJSValue(exec_state, value, + kNoConversionFlags, &exception_state, + &cobalt_value); + if (exception_state.is_exception_set()) { + JSC::throwError(exec_state, exception_state.exception_object()); + return; + } + // Check if argument conversion raised an exception. + if (!exec_state->hadException()) { + impl->set_long_long_property(cobalt_value); + } +} + +JSC::JSValue getJSunsignedLongLongProperty( + JSC::ExecState* exec_state, + JSC::JSValue slot_base, + JSC::PropertyName property_name) { + TRACE_EVENT0("JSCNumericTypesTestInterface", "get unsignedLongLongProperty"); + JSCGlobalObject* global_object = + JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject()); + NumericTypesTestInterface* impl = + GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, slot_base); + if (!impl) { + return exec_state->exception(); + } + + JSC::JSValue result = ToJSValue( + global_object, + impl->unsigned_long_long_property()); + return result; +} + +void setJSunsignedLongLongProperty( + JSC::ExecState* exec_state, + JSC::JSObject* this_object, + JSC::JSValue value) { + TRACE_EVENT0("JSCNumericTypesTestInterface", "set unsignedLongLongProperty"); + JSCGlobalObject* global_object = + JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject()); + JSCExceptionState exception_state(global_object); + NumericTypesTestInterface* impl = + GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object); + if (!impl) { + return; + } + TypeTraits<uint64_t >::ConversionType cobalt_value; + FromJSValue(exec_state, value, + kNoConversionFlags, &exception_state, + &cobalt_value); + if (exception_state.is_exception_set()) { + JSC::throwError(exec_state, exception_state.exception_object()); + return; + } + // Check if argument conversion raised an exception. + if (!exec_state->hadException()) { + impl->set_unsigned_long_long_property(cobalt_value); + } +} + JSC::JSValue getJSdoubleProperty( JSC::ExecState* exec_state, JSC::JSValue slot_base, @@ -1345,6 +1493,59 @@ } +JSC::EncodedJSValue functionJSlongLongArgumentOperation( + JSC::ExecState* exec_state) { + TRACE_EVENT0("JSCNumericTypesTestInterface", "call longLongArgumentOperation"); + JSCGlobalObject* global_object = + JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject()); + JSCExceptionState exception_state(global_object); + JSC::JSObject* this_object = + exec_state->hostThisValue().toThisObject(exec_state); + NumericTypesTestInterface* impl = + GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object); + if (!impl) { + return JSC::JSValue::encode(exec_state->exception()); + } + + const size_t kMinArguments = 1; + if (exec_state->argumentCount() < kMinArguments) { + return JSC::throwVMNotEnoughArgumentsError(exec_state); + } + // Non-optional arguments + TypeTraits<int64_t >::ConversionType arg1; + + DCHECK_LT(0, exec_state->argumentCount()); + FromJSValue(exec_state, + exec_state->argument(0), + kNoConversionFlags, + &exception_state, &arg1); + if (exception_state.is_exception_set()) { + return JSC::throwVMError(exec_state, exception_state.exception_object()); + } + impl->LongLongArgumentOperation(arg1); + return JSC::JSValue::encode(JSC::jsUndefined()); + +} + +JSC::EncodedJSValue functionJSlongLongReturnOperation( + JSC::ExecState* exec_state) { + TRACE_EVENT0("JSCNumericTypesTestInterface", "call longLongReturnOperation"); + JSCGlobalObject* global_object = + JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject()); + JSCExceptionState exception_state(global_object); + JSC::JSObject* this_object = + exec_state->hostThisValue().toThisObject(exec_state); + NumericTypesTestInterface* impl = + GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object); + if (!impl) { + return JSC::JSValue::encode(exec_state->exception()); + } + + TypeTraits<int64_t >::ReturnType return_value = impl->LongLongReturnOperation(); + return JSC::JSValue::encode(ToJSValue(global_object, return_value)); + +} + JSC::EncodedJSValue functionJSlongReturnOperation( JSC::ExecState* exec_state) { TRACE_EVENT0("JSCNumericTypesTestInterface", "call longReturnOperation"); @@ -1557,6 +1758,59 @@ } +JSC::EncodedJSValue functionJSunsignedLongLongArgumentOperation( + JSC::ExecState* exec_state) { + TRACE_EVENT0("JSCNumericTypesTestInterface", "call unsignedLongLongArgumentOperation"); + JSCGlobalObject* global_object = + JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject()); + JSCExceptionState exception_state(global_object); + JSC::JSObject* this_object = + exec_state->hostThisValue().toThisObject(exec_state); + NumericTypesTestInterface* impl = + GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object); + if (!impl) { + return JSC::JSValue::encode(exec_state->exception()); + } + + const size_t kMinArguments = 1; + if (exec_state->argumentCount() < kMinArguments) { + return JSC::throwVMNotEnoughArgumentsError(exec_state); + } + // Non-optional arguments + TypeTraits<uint64_t >::ConversionType arg1; + + DCHECK_LT(0, exec_state->argumentCount()); + FromJSValue(exec_state, + exec_state->argument(0), + kNoConversionFlags, + &exception_state, &arg1); + if (exception_state.is_exception_set()) { + return JSC::throwVMError(exec_state, exception_state.exception_object()); + } + impl->UnsignedLongLongArgumentOperation(arg1); + return JSC::JSValue::encode(JSC::jsUndefined()); + +} + +JSC::EncodedJSValue functionJSunsignedLongLongReturnOperation( + JSC::ExecState* exec_state) { + TRACE_EVENT0("JSCNumericTypesTestInterface", "call unsignedLongLongReturnOperation"); + JSCGlobalObject* global_object = + JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject()); + JSCExceptionState exception_state(global_object); + JSC::JSObject* this_object = + exec_state->hostThisValue().toThisObject(exec_state); + NumericTypesTestInterface* impl = + GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object); + if (!impl) { + return JSC::JSValue::encode(exec_state->exception()); + } + + TypeTraits<uint64_t >::ReturnType return_value = impl->UnsignedLongLongReturnOperation(); + return JSC::JSValue::encode(ToJSValue(global_object, return_value)); + +} + JSC::EncodedJSValue functionJSunsignedLongReturnOperation( JSC::ExecState* exec_state) { TRACE_EVENT0("JSCNumericTypesTestInterface", "call unsignedLongReturnOperation");
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCOperationsTestInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCOperationsTestInterface.cc index c451bd3..2f95415 100644 --- a/src/cobalt/bindings/generated/jsc/testing/JSCOperationsTestInterface.cc +++ b/src/cobalt/bindings/generated/jsc/testing/JSCOperationsTestInterface.cc
@@ -121,6 +121,8 @@ JSC::EncodedJSValue functionJSvoidFunctionObjectArg(JSC::ExecState*); JSC::EncodedJSValue functionJSvoidFunctionStringArg(JSC::ExecState*); JSC::EncodedJSValue staticFunctionJSoverloadedFunction(JSC::ExecState*); +JSC::EncodedJSValue staticFunctionJSoverloadedFunction1(JSC::ExecState*); +JSC::EncodedJSValue staticFunctionJSoverloadedFunction2(JSC::ExecState*); // These are declared unconditionally, but only defined if needed by the // interface. @@ -1510,6 +1512,33 @@ JSC::EncodedJSValue staticFunctionJSoverloadedFunction( JSC::ExecState* exec_state) { TRACE_EVENT0("JSCOperationsTestInterface", "call overloadedFunction"); + const size_t num_arguments = exec_state->argumentCount(); + switch(num_arguments) { + case(1): { + // Overload resolution algorithm details found here: + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + if (true) { + return staticFunctionJSoverloadedFunction1(exec_state); + } + break; + } + case(2): { + // Overload resolution algorithm details found here: + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + if (true) { + return staticFunctionJSoverloadedFunction2(exec_state); + } + break; + } + } + // Invalid number of args + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + // 4. If S is empty, then throw a TypeError. + return JSC::throwVMTypeError(exec_state); +} + +JSC::EncodedJSValue staticFunctionJSoverloadedFunction1( + JSC::ExecState* exec_state) { JSCGlobalObject* global_object = JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject()); JSCExceptionState exception_state(global_object); @@ -1533,6 +1562,42 @@ return JSC::JSValue::encode(JSC::jsUndefined()); } + +JSC::EncodedJSValue staticFunctionJSoverloadedFunction2( + JSC::ExecState* exec_state) { + JSCGlobalObject* global_object = + JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject()); + JSCExceptionState exception_state(global_object); + + const size_t kMinArguments = 2; + if (exec_state->argumentCount() < kMinArguments) { + return JSC::throwVMNotEnoughArgumentsError(exec_state); + } + // Non-optional arguments + TypeTraits<double >::ConversionType arg1; + TypeTraits<double >::ConversionType arg2; + + DCHECK_LT(0, exec_state->argumentCount()); + FromJSValue(exec_state, + exec_state->argument(0), + (kConversionFlagRestricted), + &exception_state, &arg1); + if (exception_state.is_exception_set()) { + return JSC::throwVMError(exec_state, exception_state.exception_object()); + } + + DCHECK_LT(1, exec_state->argumentCount()); + FromJSValue(exec_state, + exec_state->argument(1), + (kConversionFlagRestricted), + &exception_state, &arg2); + if (exception_state.is_exception_set()) { + return JSC::throwVMError(exec_state, exception_state.exception_object()); + } + OperationsTestInterface::OverloadedFunction(arg1, arg2); + return JSC::JSValue::encode(JSC::jsUndefined()); + +} JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state, JSC::JSValue slot_base, JSC::PropertyName property_name) { NOTREACHED();
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCPutForwardsInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCPutForwardsInterface.cc index d1870dd..dd16e18 100644 --- a/src/cobalt/bindings/generated/jsc/testing/JSCPutForwardsInterface.cc +++ b/src/cobalt/bindings/generated/jsc/testing/JSCPutForwardsInterface.cc
@@ -107,6 +107,14 @@ JSC::ExecState* exec, JSC::JSObject* this_object, JSC::JSValue value); +JSC::JSValue getJSstaticForwardingAttribute( + JSC::ExecState* exec_state, + JSC::JSValue slot_base, + JSC::PropertyName property_name); +void setJSstaticForwardingAttribute( + JSC::ExecState* exec, + JSC::JSObject* this_object, + JSC::JSValue value); // These are declared unconditionally, but only defined if needed by the // interface. @@ -218,6 +226,12 @@ const JSC::HashTableValue JSCPutForwardsInterface::InterfaceObject::property_table_values[] = { // static functions will also go here. + { "staticForwardingAttribute", + JSC::DontDelete | JSC::ReadOnly, + reinterpret_cast<intptr_t>(getJSstaticForwardingAttribute), + 0, + JSC::NoIntrinsic + }, { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) } }; // JSCPutForwardsInterface::InterfaceObject::property_table_values @@ -225,8 +239,8 @@ const JSC::HashTable JSCPutForwardsInterface::InterfaceObject::property_table_prototype = { // Sizes will be calculated based on the number of static functions as well. - 2, // compactSize - 1, // compactSizeMask + 4, // compactSize + 3, // compactSizeMask property_table_values, NULL // table allocated at runtime }; // JSCPutForwardsInterface::InterfaceObject::property_table_prototype @@ -684,6 +698,50 @@ } } + +JSC::JSValue getJSstaticForwardingAttribute( + JSC::ExecState* exec_state, + JSC::JSValue slot_base, + JSC::PropertyName property_name) { + TRACE_EVENT0("JSCPutForwardsInterface", "get staticForwardingAttribute"); + JSCGlobalObject* global_object = + JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject()); + + JSC::JSValue result = ToJSValue( + global_object, + PutForwardsInterface::static_forwarding_attribute()); + return result; +} + +void setJSstaticForwardingAttribute( + JSC::ExecState* exec_state, + JSC::JSObject* this_object, + JSC::JSValue value) { + TRACE_EVENT0("JSCPutForwardsInterface", "set staticForwardingAttribute"); + JSCGlobalObject* global_object = + JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject()); + JSCExceptionState exception_state(global_object); + { + scoped_refptr<ArbitraryInterface> forwarded_impl = + PutForwardsInterface::static_forwarding_attribute(); + if (!forwarded_impl) { + return; + } + TypeTraits<std::string >::ConversionType cobalt_value; + FromJSValue(exec_state, value, + kNoConversionFlags, &exception_state, + &cobalt_value); + if (exception_state.is_exception_set()) { + JSC::throwError(exec_state, exception_state.exception_object()); + return; + } + // Check if argument conversion raised an exception. + if (!exec_state->hadException()) { + forwarded_impl->set_arbitrary_property(cobalt_value); + } + } + +} JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state, JSC::JSValue slot_base, JSC::PropertyName property_name) { NOTREACHED();
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCStaticPropertiesInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCStaticPropertiesInterface.cc index 965d7f0..4270480 100644 --- a/src/cobalt/bindings/generated/jsc/testing/JSCStaticPropertiesInterface.cc +++ b/src/cobalt/bindings/generated/jsc/testing/JSCStaticPropertiesInterface.cc
@@ -28,6 +28,8 @@ #include "cobalt/script/global_object_proxy.h" #include "cobalt/script/opaque_handle.h" #include "cobalt/script/script_object.h" +#include "JSCArbitraryInterface.h" +#include "cobalt/bindings/testing/arbitrary_interface.h" #include "cobalt/script/javascriptcore/constructor_base.h" #include "cobalt/script/javascriptcore/conversion_helpers.h" @@ -53,6 +55,8 @@ namespace { using cobalt::bindings::testing::StaticPropertiesInterface; using cobalt::bindings::testing::JSCStaticPropertiesInterface; +using cobalt::bindings::testing::ArbitraryInterface; +using cobalt::bindings::testing::JSCArbitraryInterface; using cobalt::script::CallbackInterfaceTraits; using cobalt::script::GlobalObjectProxy; using cobalt::script::OpaqueHandle; @@ -104,6 +108,11 @@ JSC::JSObject* this_object, JSC::JSValue value); JSC::EncodedJSValue staticFunctionJSstaticFunction(JSC::ExecState*); +JSC::EncodedJSValue staticFunctionJSstaticFunction1(JSC::ExecState*); +JSC::EncodedJSValue staticFunctionJSstaticFunction2(JSC::ExecState*); +JSC::EncodedJSValue staticFunctionJSstaticFunction3(JSC::ExecState*); +JSC::EncodedJSValue staticFunctionJSstaticFunction4(JSC::ExecState*); +JSC::EncodedJSValue staticFunctionJSstaticFunction5(JSC::ExecState*); // These are declared unconditionally, but only defined if needed by the // interface. @@ -673,6 +682,52 @@ JSC::EncodedJSValue staticFunctionJSstaticFunction( JSC::ExecState* exec_state) { TRACE_EVENT0("JSCStaticPropertiesInterface", "call staticFunction"); + const size_t num_arguments = exec_state->argumentCount(); + switch(num_arguments) { + case(0): { + // Overload resolution algorithm details found here: + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + if (true) { + return staticFunctionJSstaticFunction1(exec_state); + } + break; + } + case(1): { + // Overload resolution algorithm details found here: + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + JSC::JSValue arg = exec_state->argument(0); + if (arg.isNumber()) { + return staticFunctionJSstaticFunction2(exec_state); + } + if (true) { + return staticFunctionJSstaticFunction3(exec_state); + } + if (true) { + return staticFunctionJSstaticFunction2(exec_state); + } + break; + } + case(3): { + // Overload resolution algorithm details found here: + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + JSC::JSValue arg = exec_state->argument(2); + if (arg.inherits(JSCArbitraryInterface::s_classinfo())) { + return staticFunctionJSstaticFunction5(exec_state); + } + if (true) { + return staticFunctionJSstaticFunction4(exec_state); + } + break; + } + } + // Invalid number of args + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + // 4. If S is empty, then throw a TypeError. + return JSC::throwVMTypeError(exec_state); +} + +JSC::EncodedJSValue staticFunctionJSstaticFunction1( + JSC::ExecState* exec_state) { JSCGlobalObject* global_object = JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject()); JSCExceptionState exception_state(global_object); @@ -681,6 +736,150 @@ return JSC::JSValue::encode(JSC::jsUndefined()); } + +JSC::EncodedJSValue staticFunctionJSstaticFunction2( + JSC::ExecState* exec_state) { + JSCGlobalObject* global_object = + JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject()); + JSCExceptionState exception_state(global_object); + + const size_t kMinArguments = 1; + if (exec_state->argumentCount() < kMinArguments) { + return JSC::throwVMNotEnoughArgumentsError(exec_state); + } + // Non-optional arguments + TypeTraits<int32_t >::ConversionType arg; + + DCHECK_LT(0, exec_state->argumentCount()); + FromJSValue(exec_state, + exec_state->argument(0), + kNoConversionFlags, + &exception_state, &arg); + if (exception_state.is_exception_set()) { + return JSC::throwVMError(exec_state, exception_state.exception_object()); + } + StaticPropertiesInterface::StaticFunction(arg); + return JSC::JSValue::encode(JSC::jsUndefined()); + +} + +JSC::EncodedJSValue staticFunctionJSstaticFunction3( + JSC::ExecState* exec_state) { + JSCGlobalObject* global_object = + JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject()); + JSCExceptionState exception_state(global_object); + + const size_t kMinArguments = 1; + if (exec_state->argumentCount() < kMinArguments) { + return JSC::throwVMNotEnoughArgumentsError(exec_state); + } + // Non-optional arguments + TypeTraits<std::string >::ConversionType arg; + + DCHECK_LT(0, exec_state->argumentCount()); + FromJSValue(exec_state, + exec_state->argument(0), + kNoConversionFlags, + &exception_state, &arg); + if (exception_state.is_exception_set()) { + return JSC::throwVMError(exec_state, exception_state.exception_object()); + } + StaticPropertiesInterface::StaticFunction(arg); + return JSC::JSValue::encode(JSC::jsUndefined()); + +} + +JSC::EncodedJSValue staticFunctionJSstaticFunction4( + JSC::ExecState* exec_state) { + JSCGlobalObject* global_object = + JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject()); + JSCExceptionState exception_state(global_object); + + const size_t kMinArguments = 3; + if (exec_state->argumentCount() < kMinArguments) { + return JSC::throwVMNotEnoughArgumentsError(exec_state); + } + // Non-optional arguments + TypeTraits<int32_t >::ConversionType arg1; + TypeTraits<int32_t >::ConversionType arg2; + TypeTraits<int32_t >::ConversionType arg3; + + DCHECK_LT(0, exec_state->argumentCount()); + FromJSValue(exec_state, + exec_state->argument(0), + kNoConversionFlags, + &exception_state, &arg1); + if (exception_state.is_exception_set()) { + return JSC::throwVMError(exec_state, exception_state.exception_object()); + } + + DCHECK_LT(1, exec_state->argumentCount()); + FromJSValue(exec_state, + exec_state->argument(1), + kNoConversionFlags, + &exception_state, &arg2); + if (exception_state.is_exception_set()) { + return JSC::throwVMError(exec_state, exception_state.exception_object()); + } + + DCHECK_LT(2, exec_state->argumentCount()); + FromJSValue(exec_state, + exec_state->argument(2), + kNoConversionFlags, + &exception_state, &arg3); + if (exception_state.is_exception_set()) { + return JSC::throwVMError(exec_state, exception_state.exception_object()); + } + StaticPropertiesInterface::StaticFunction(arg1, arg2, arg3); + return JSC::JSValue::encode(JSC::jsUndefined()); + +} + +JSC::EncodedJSValue staticFunctionJSstaticFunction5( + JSC::ExecState* exec_state) { + JSCGlobalObject* global_object = + JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject()); + JSCExceptionState exception_state(global_object); + + const size_t kMinArguments = 3; + if (exec_state->argumentCount() < kMinArguments) { + return JSC::throwVMNotEnoughArgumentsError(exec_state); + } + // Non-optional arguments + TypeTraits<int32_t >::ConversionType arg1; + TypeTraits<int32_t >::ConversionType arg2; + TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType arg3; + + DCHECK_LT(0, exec_state->argumentCount()); + FromJSValue(exec_state, + exec_state->argument(0), + kNoConversionFlags, + &exception_state, &arg1); + if (exception_state.is_exception_set()) { + return JSC::throwVMError(exec_state, exception_state.exception_object()); + } + + DCHECK_LT(1, exec_state->argumentCount()); + FromJSValue(exec_state, + exec_state->argument(1), + kNoConversionFlags, + &exception_state, &arg2); + if (exception_state.is_exception_set()) { + return JSC::throwVMError(exec_state, exception_state.exception_object()); + } + + DCHECK_LT(2, exec_state->argumentCount()); + FromJSValue(exec_state, + exec_state->argument(2), + kNoConversionFlags, + &exception_state, &arg3); + if (exception_state.is_exception_set()) { + return JSC::throwVMError(exec_state, exception_state.exception_object()); + } + StaticPropertiesInterface::StaticFunction(arg1, arg2, arg3); + return JSC::JSValue::encode(JSC::jsUndefined()); + +} JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state, JSC::JSValue slot_base, JSC::PropertyName property_name) { NOTREACHED();
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCUnionTypesInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCUnionTypesInterface.cc index fd026f2..2b7afe1 100644 --- a/src/cobalt/bindings/generated/jsc/testing/JSCUnionTypesInterface.cc +++ b/src/cobalt/bindings/generated/jsc/testing/JSCUnionTypesInterface.cc
@@ -29,7 +29,9 @@ #include "cobalt/script/opaque_handle.h" #include "cobalt/script/script_object.h" #include "JSCArbitraryInterface.h" +#include "JSCBaseInterface.h" #include "cobalt/bindings/testing/arbitrary_interface.h" +#include "cobalt/bindings/testing/base_interface.h" #include "cobalt/script/javascriptcore/constructor_base.h" #include "cobalt/script/javascriptcore/conversion_helpers.h" @@ -56,7 +58,9 @@ using cobalt::bindings::testing::UnionTypesInterface; using cobalt::bindings::testing::JSCUnionTypesInterface; using cobalt::bindings::testing::ArbitraryInterface; +using cobalt::bindings::testing::BaseInterface; using cobalt::bindings::testing::JSCArbitraryInterface; +using cobalt::bindings::testing::JSCBaseInterface; using cobalt::script::CallbackInterfaceTraits; using cobalt::script::GlobalObjectProxy; using cobalt::script::OpaqueHandle; @@ -123,6 +127,14 @@ JSC::ExecState* exec, JSC::JSObject* this_object, JSC::JSValue value); +JSC::JSValue getJSunionBaseProperty( + JSC::ExecState* exec_state, + JSC::JSValue slot_base, + JSC::PropertyName property_name); +void setJSunionBaseProperty( + JSC::ExecState* exec, + JSC::JSObject* this_object, + JSC::JSValue value); // These are declared unconditionally, but only defined if needed by the // interface. @@ -449,13 +461,19 @@ reinterpret_cast<intptr_t>(setJSnullableUnionProperty), JSC::NoIntrinsic }, + { "unionBaseProperty", + JSC::DontDelete , + reinterpret_cast<intptr_t>(getJSunionBaseProperty), + reinterpret_cast<intptr_t>(setJSunionBaseProperty), + JSC::NoIntrinsic + }, { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) } }; // JSCUnionTypesInterface::property_table_values // static const JSC::HashTable JSCUnionTypesInterface::property_table_prototype = { - 10, // compactSize - 7, // compactSizeMask + 19, // compactSize + 15, // compactSizeMask property_table_values, NULL // table allocated at runtime }; // JSCUnionTypesInterface::property_table_prototype @@ -796,6 +814,52 @@ impl->set_nullable_union_property(cobalt_value); } } + +JSC::JSValue getJSunionBaseProperty( + JSC::ExecState* exec_state, + JSC::JSValue slot_base, + JSC::PropertyName property_name) { + TRACE_EVENT0("JSCUnionTypesInterface", "get unionBaseProperty"); + JSCGlobalObject* global_object = + JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject()); + UnionTypesInterface* impl = + GetWrappableOrSetException<UnionTypesInterface>(exec_state, slot_base); + if (!impl) { + return exec_state->exception(); + } + + JSC::JSValue result = ToJSValue( + global_object, + impl->union_base_property()); + return result; +} + +void setJSunionBaseProperty( + JSC::ExecState* exec_state, + JSC::JSObject* this_object, + JSC::JSValue value) { + TRACE_EVENT0("JSCUnionTypesInterface", "set unionBaseProperty"); + JSCGlobalObject* global_object = + JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject()); + JSCExceptionState exception_state(global_object); + UnionTypesInterface* impl = + GetWrappableOrSetException<UnionTypesInterface>(exec_state, this_object); + if (!impl) { + return; + } + TypeTraits<script::UnionType2<scoped_refptr<BaseInterface>, std::string > >::ConversionType cobalt_value; + FromJSValue(exec_state, value, + kNoConversionFlags, &exception_state, + &cobalt_value); + if (exception_state.is_exception_set()) { + JSC::throwError(exec_state, exception_state.exception_object()); + return; + } + // Check if argument conversion raised an exception. + if (!exec_state->hadException()) { + impl->set_union_base_property(cobalt_value); + } +} JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state, JSC::JSValue slot_base, JSC::PropertyName property_name) { NOTREACHED();
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.cc index 3b1262d..d314658 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -75,6 +84,128 @@ namespace { +bool IsSupportedIndexProperty(JSContext* context, JS::HandleObject object, + uint32_t index) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + AnonymousIndexedGetterInterface* impl = + wrapper_private->wrappable<AnonymousIndexedGetterInterface>().get(); + return index < impl->length(); +} + +void EnumerateSupportedIndexes(JSContext* context, JS::HandleObject object, + JS::AutoIdVector* properties) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + AnonymousIndexedGetterInterface* impl = + wrapper_private->wrappable<AnonymousIndexedGetterInterface>().get(); + const uint32_t kNumIndexedProperties = impl->length(); + for (uint32_t i = 0; i < kNumIndexedProperties; ++i) { + properties->append(INT_TO_JSID(i)); + } +} + +JSBool GetIndexedProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JS::MutableHandleValue vp) { + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + AnonymousIndexedGetterInterface* impl = + wrapper_private->wrappable<AnonymousIndexedGetterInterface>().get(); + uint32_t index; + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, &index); + if(exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->AnonymousIndexedGetter(index), + &result_value); + } + if (!exception_state.is_exception_set()) { + vp.set(result_value); + } + return !exception_state.is_exception_set(); +} + +JSBool SetIndexedProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JSBool strict, JS::MutableHandleValue vp) { + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + AnonymousIndexedGetterInterface* impl = + wrapper_private->wrappable<AnonymousIndexedGetterInterface>().get(); + uint32_t index; + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, &index); + if(exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } + TypeTraits<uint32_t >::ConversionType value; + FromJSValue(context, vp, kNoConversionFlags, + &exception_state, &value); + if (exception_state.is_exception_set()) { + return false; + } + + impl->AnonymousIndexedSetter(index, value); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +class MozjsAnonymousIndexedGetterInterfaceHandler : public ProxyHandler { + public: + MozjsAnonymousIndexedGetterInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsAnonymousIndexedGetterInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsAnonymousIndexedGetterInterfaceHandler::indexed_property_hooks = { + IsSupportedIndexProperty, + EnumerateSupportedIndexes, + GetIndexedProperty, + SetIndexedProperty, + NULL, +}; + +static base::LazyInstance<MozjsAnonymousIndexedGetterInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -111,7 +242,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "AnonymousIndexedGetterInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -129,18 +261,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - AnonymousIndexedGetterInterface* impl = - WrapperPrivate::GetWrappable<AnonymousIndexedGetterInterface>(object); - TypeTraits<uint32_t >::ReturnType value = - impl->length(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + AnonymousIndexedGetterInterface* impl = + wrapper_private->wrappable<AnonymousIndexedGetterInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->length(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -162,6 +297,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -181,7 +320,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -201,8 +341,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "AnonymousIndexedGetterInterface"; - name_value.setString(JS_NewStringCopyZ(context, "AnonymousIndexedGetterInterface")); + const char name[] = + "AnonymousIndexedGetterInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -211,8 +352,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -244,7 +390,7 @@ } // namespace // static -JSObject* MozjsAnonymousIndexedGetterInterface::CreateInstance( +JSObject* MozjsAnonymousIndexedGetterInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -252,8 +398,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsAnonymousIndexedGetterInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.h index 3a14754..56a2226 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.h
@@ -38,8 +38,9 @@ class MozjsAnonymousIndexedGetterInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.cc index 7306f34..7cc34a6 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -75,6 +84,128 @@ namespace { +bool IsSupportedNamedProperty(JSContext* context, JS::HandleObject object, + const std::string& property_name) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + AnonymousNamedGetterInterface* impl = + wrapper_private->wrappable<AnonymousNamedGetterInterface>().get(); + return impl->CanQueryNamedProperty(property_name); +} + +void EnumerateSupportedNames(JSContext* context, JS::HandleObject object, + JS::AutoIdVector* properties) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + AnonymousNamedGetterInterface* impl = + wrapper_private->wrappable<AnonymousNamedGetterInterface>().get(); + MozjsPropertyEnumerator enumerator(context, properties); + impl->EnumerateNamedProperties(&enumerator); +} + +JSBool GetNamedProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JS::MutableHandleValue vp) { + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + AnonymousNamedGetterInterface* impl = + wrapper_private->wrappable<AnonymousNamedGetterInterface>().get(); + std::string property_name; + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, + &property_name); + if(exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->AnonymousNamedGetter(property_name), + &result_value); + } + if (!exception_state.is_exception_set()) { + vp.set(result_value); + } + return !exception_state.is_exception_set(); +} + +JSBool SetNamedProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JSBool strict, JS::MutableHandleValue vp) { + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + AnonymousNamedGetterInterface* impl = + wrapper_private->wrappable<AnonymousNamedGetterInterface>().get(); + std::string property_name; + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, + &property_name); + if(exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } + TypeTraits<std::string >::ConversionType value; + FromJSValue(context, vp, kNoConversionFlags, + &exception_state, &value); + if (exception_state.is_exception_set()) { + return false; + } + + impl->AnonymousNamedSetter(property_name, value); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +class MozjsAnonymousNamedGetterInterfaceHandler : public ProxyHandler { + public: + MozjsAnonymousNamedGetterInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsAnonymousNamedGetterInterfaceHandler::named_property_hooks = { + IsSupportedNamedProperty, + EnumerateSupportedNames, + GetNamedProperty, + SetNamedProperty, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsAnonymousNamedGetterInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsAnonymousNamedGetterInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -111,7 +242,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "AnonymousNamedGetterInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -137,6 +269,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -156,7 +292,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -176,8 +313,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "AnonymousNamedGetterInterface"; - name_value.setString(JS_NewStringCopyZ(context, "AnonymousNamedGetterInterface")); + const char name[] = + "AnonymousNamedGetterInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -186,8 +324,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -219,7 +362,7 @@ } // namespace // static -JSObject* MozjsAnonymousNamedGetterInterface::CreateInstance( +JSObject* MozjsAnonymousNamedGetterInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -227,8 +370,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsAnonymousNamedGetterInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.h index 3b0337b..36537ae 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.h
@@ -38,8 +38,9 @@ class MozjsAnonymousNamedGetterInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.cc index 943b147..519c86f 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -75,6 +84,219 @@ namespace { +bool IsSupportedNamedProperty(JSContext* context, JS::HandleObject object, + const std::string& property_name) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + AnonymousNamedIndexedGetterInterface* impl = + wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get(); + return impl->CanQueryNamedProperty(property_name); +} + +void EnumerateSupportedNames(JSContext* context, JS::HandleObject object, + JS::AutoIdVector* properties) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + AnonymousNamedIndexedGetterInterface* impl = + wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get(); + MozjsPropertyEnumerator enumerator(context, properties); + impl->EnumerateNamedProperties(&enumerator); +} + +JSBool GetNamedProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JS::MutableHandleValue vp) { + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + AnonymousNamedIndexedGetterInterface* impl = + wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get(); + std::string property_name; + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, + &property_name); + if(exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->AnonymousNamedGetter(property_name), + &result_value); + } + if (!exception_state.is_exception_set()) { + vp.set(result_value); + } + return !exception_state.is_exception_set(); +} + +JSBool SetNamedProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JSBool strict, JS::MutableHandleValue vp) { + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + AnonymousNamedIndexedGetterInterface* impl = + wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get(); + std::string property_name; + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, + &property_name); + if(exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } + TypeTraits<std::string >::ConversionType value; + FromJSValue(context, vp, kNoConversionFlags, + &exception_state, &value); + if (exception_state.is_exception_set()) { + return false; + } + + impl->AnonymousNamedSetter(property_name, value); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +bool IsSupportedIndexProperty(JSContext* context, JS::HandleObject object, + uint32_t index) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + AnonymousNamedIndexedGetterInterface* impl = + wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get(); + return index < impl->length(); +} + +void EnumerateSupportedIndexes(JSContext* context, JS::HandleObject object, + JS::AutoIdVector* properties) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + AnonymousNamedIndexedGetterInterface* impl = + wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get(); + const uint32_t kNumIndexedProperties = impl->length(); + for (uint32_t i = 0; i < kNumIndexedProperties; ++i) { + properties->append(INT_TO_JSID(i)); + } +} + +JSBool GetIndexedProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JS::MutableHandleValue vp) { + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + AnonymousNamedIndexedGetterInterface* impl = + wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get(); + uint32_t index; + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, &index); + if(exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->AnonymousIndexedGetter(index), + &result_value); + } + if (!exception_state.is_exception_set()) { + vp.set(result_value); + } + return !exception_state.is_exception_set(); +} + +JSBool SetIndexedProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JSBool strict, JS::MutableHandleValue vp) { + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + AnonymousNamedIndexedGetterInterface* impl = + wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get(); + uint32_t index; + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, &index); + if(exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } + TypeTraits<uint32_t >::ConversionType value; + FromJSValue(context, vp, kNoConversionFlags, + &exception_state, &value); + if (exception_state.is_exception_set()) { + return false; + } + + impl->AnonymousIndexedSetter(index, value); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +class MozjsAnonymousNamedIndexedGetterInterfaceHandler : public ProxyHandler { + public: + MozjsAnonymousNamedIndexedGetterInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsAnonymousNamedIndexedGetterInterfaceHandler::named_property_hooks = { + IsSupportedNamedProperty, + EnumerateSupportedNames, + GetNamedProperty, + SetNamedProperty, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsAnonymousNamedIndexedGetterInterfaceHandler::indexed_property_hooks = { + IsSupportedIndexProperty, + EnumerateSupportedIndexes, + GetIndexedProperty, + SetIndexedProperty, + NULL, +}; + +static base::LazyInstance<MozjsAnonymousNamedIndexedGetterInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -111,7 +333,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "AnonymousNamedIndexedGetterInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -129,18 +352,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - AnonymousNamedIndexedGetterInterface* impl = - WrapperPrivate::GetWrappable<AnonymousNamedIndexedGetterInterface>(object); - TypeTraits<uint32_t >::ReturnType value = - impl->length(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + AnonymousNamedIndexedGetterInterface* impl = + wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->length(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -162,6 +388,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -181,7 +411,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -201,8 +432,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "AnonymousNamedIndexedGetterInterface"; - name_value.setString(JS_NewStringCopyZ(context, "AnonymousNamedIndexedGetterInterface")); + const char name[] = + "AnonymousNamedIndexedGetterInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -211,8 +443,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -244,7 +481,7 @@ } // namespace // static -JSObject* MozjsAnonymousNamedIndexedGetterInterface::CreateInstance( +JSObject* MozjsAnonymousNamedIndexedGetterInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -252,8 +489,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsAnonymousNamedIndexedGetterInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.h index 0cb4295..6665fe1 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.h
@@ -38,8 +38,9 @@ class MozjsAnonymousNamedIndexedGetterInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.cc index 7625787..eb16ae9 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -74,7 +83,38 @@ namespace testing { namespace { -JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args); + +class MozjsArbitraryInterfaceHandler : public ProxyHandler { + public: + MozjsArbitraryInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsArbitraryInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsArbitraryInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsArbitraryInterfaceHandler> + proxy_handler; + +JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp); InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); @@ -112,7 +152,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "ArbitraryInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -131,18 +172,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - ArbitraryInterface* impl = - WrapperPrivate::GetWrappable<ArbitraryInterface>(object); - TypeTraits<std::string >::ReturnType value = - impl->arbitrary_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + ArbitraryInterface* impl = + wrapper_private->wrappable<ArbitraryInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->arbitrary_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_arbitraryProperty( @@ -150,25 +194,26 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + ArbitraryInterface* impl = + wrapper_private->wrappable<ArbitraryInterface>().get(); TypeTraits<std::string >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - ArbitraryInterface* impl = - WrapperPrivate::GetWrappable<ArbitraryInterface>(object); + impl->set_arbitrary_property(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_arbitraryFunction( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -181,17 +226,17 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); ArbitraryInterface* impl = - WrapperPrivate::GetWrappable<ArbitraryInterface>(object); + wrapper_private->wrappable<ArbitraryInterface>().get(); + impl->ArbitraryFunction(); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -220,6 +265,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -239,7 +288,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -259,18 +309,34 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "ArbitraryInterface"; - name_value.setString(JS_NewStringCopyZ(context, "ArbitraryInterface")); + const char name[] = + "ArbitraryInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, JSPROP_READONLY); DCHECK(success); + // Add the InterfaceObject.length property. It is set to the length of the + // shortest argument list of all overload constructors. + JS::RootedValue length_value(context); + length_value.setInt32(0); + success = + JS_DefineProperty(context, rooted_interface_object, "length", + length_value, JS_PropertyStub, JS_StrictPropertyStub, + JSPROP_READONLY); + DCHECK(success); + // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -302,7 +368,7 @@ } // namespace // static -JSObject* MozjsArbitraryInterface::CreateInstance( +JSObject* MozjsArbitraryInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -310,8 +376,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsArbitraryInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static @@ -337,9 +414,17 @@ namespace { -JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args) { - // TODO: Implement support for constructors. - NOTIMPLEMENTED(); +JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp) { + MozjsExceptionState exception_state(context); + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + + scoped_refptr<ArbitraryInterface> new_object = + new ArbitraryInterface(); + JS::RootedValue result_value(context); + ToJSValue(context, new_object, &result_value); + DCHECK(result_value.isObject()); + JS::RootedObject result_object(context, JSVAL_TO_OBJECT(result_value)); + args.rval().setObject(*result_object); return true; } } // namespace
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.h index ab9c011..1ca5d0d 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.h
@@ -38,8 +38,9 @@ class MozjsArbitraryInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.cc index 99489af..1213bf6 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -74,7 +83,38 @@ namespace testing { namespace { -JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args); + +class MozjsBaseInterfaceHandler : public ProxyHandler { + public: + MozjsBaseInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsBaseInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsBaseInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsBaseInterfaceHandler> + proxy_handler; + +JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp); InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); @@ -112,7 +152,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "BaseInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -131,25 +172,26 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - BaseInterface* impl = - WrapperPrivate::GetWrappable<BaseInterface>(object); - TypeTraits<std::string >::ReturnType value = - impl->base_attribute(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + BaseInterface* impl = + wrapper_private->wrappable<BaseInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->base_attribute(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_baseOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -162,17 +204,17 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); BaseInterface* impl = - WrapperPrivate::GetWrappable<BaseInterface>(object); + wrapper_private->wrappable<BaseInterface>().get(); + impl->BaseOperation(); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -201,6 +243,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -220,7 +266,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -240,18 +287,34 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "BaseInterface"; - name_value.setString(JS_NewStringCopyZ(context, "BaseInterface")); + const char name[] = + "BaseInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, JSPROP_READONLY); DCHECK(success); + // Add the InterfaceObject.length property. It is set to the length of the + // shortest argument list of all overload constructors. + JS::RootedValue length_value(context); + length_value.setInt32(0); + success = + JS_DefineProperty(context, rooted_interface_object, "length", + length_value, JS_PropertyStub, JS_StrictPropertyStub, + JSPROP_READONLY); + DCHECK(success); + // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -283,7 +346,7 @@ } // namespace // static -JSObject* MozjsBaseInterface::CreateInstance( +JSObject* MozjsBaseInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -291,8 +354,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsBaseInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static @@ -318,9 +392,17 @@ namespace { -JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args) { - // TODO: Implement support for constructors. - NOTIMPLEMENTED(); +JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp) { + MozjsExceptionState exception_state(context); + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + + scoped_refptr<BaseInterface> new_object = + new BaseInterface(); + JS::RootedValue result_value(context); + ToJSValue(context, new_object, &result_value); + DCHECK(result_value.isObject()); + JS::RootedObject result_object(context, JSVAL_TO_OBJECT(result_value)); + args.rval().setObject(*result_object); return true; } } // namespace
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.h index d170a1f..6a9f2c0 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.h
@@ -38,8 +38,9 @@ class MozjsBaseInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.cc index 9cd00aa..b334f88 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -75,6 +84,37 @@ namespace { +class MozjsBooleanTypeTestInterfaceHandler : public ProxyHandler { + public: + MozjsBooleanTypeTestInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsBooleanTypeTestInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsBooleanTypeTestInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsBooleanTypeTestInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -111,7 +151,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "BooleanTypeTestInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -129,18 +170,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - BooleanTypeTestInterface* impl = - WrapperPrivate::GetWrappable<BooleanTypeTestInterface>(object); - TypeTraits<bool >::ReturnType value = - impl->boolean_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + BooleanTypeTestInterface* impl = + wrapper_private->wrappable<BooleanTypeTestInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->boolean_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_booleanProperty( @@ -148,25 +192,26 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + BooleanTypeTestInterface* impl = + wrapper_private->wrappable<BooleanTypeTestInterface>().get(); TypeTraits<bool >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - BooleanTypeTestInterface* impl = - WrapperPrivate::GetWrappable<BooleanTypeTestInterface>(object); + impl->set_boolean_property(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_booleanArgumentOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -179,37 +224,41 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + BooleanTypeTestInterface* impl = + wrapper_private->wrappable<BooleanTypeTestInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<bool >::ConversionType arg1; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &arg1); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg1); + if (exception_state.is_exception_set()) { return false; } - BooleanTypeTestInterface* impl = - WrapperPrivate::GetWrappable<BooleanTypeTestInterface>(object); + impl->BooleanArgumentOperation(arg1); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_booleanReturnOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -222,20 +271,23 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); BooleanTypeTestInterface* impl = - WrapperPrivate::GetWrappable<BooleanTypeTestInterface>(object); - TypeTraits<bool >::ReturnType value = - impl->BooleanReturnOperation(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } + wrapper_private->wrappable<BooleanTypeTestInterface>().get(); - if (!exception_state.IsExceptionSet()) { + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->BooleanReturnOperation(), + &result_value); + } + if (!exception_state.is_exception_set()) { args.rval().set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -271,6 +323,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -290,7 +346,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -310,8 +367,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "BooleanTypeTestInterface"; - name_value.setString(JS_NewStringCopyZ(context, "BooleanTypeTestInterface")); + const char name[] = + "BooleanTypeTestInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -320,8 +378,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -353,7 +416,7 @@ } // namespace // static -JSObject* MozjsBooleanTypeTestInterface::CreateInstance( +JSObject* MozjsBooleanTypeTestInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -361,8 +424,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsBooleanTypeTestInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.h index 667bde9..d240a38 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.h
@@ -38,8 +38,9 @@ class MozjsBooleanTypeTestInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.cc index c7865a2..a6360ce 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.cc
@@ -30,14 +30,20 @@ #include "cobalt/bindings/testing/arbitrary_interface.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -55,6 +61,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -65,7 +72,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -79,6 +88,37 @@ namespace { +class MozjsCallbackFunctionInterfaceHandler : public ProxyHandler { + public: + MozjsCallbackFunctionInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsCallbackFunctionInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsCallbackFunctionInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsCallbackFunctionInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -115,7 +155,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "CallbackFunctionInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -133,18 +174,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - CallbackFunctionInterface* impl = - WrapperPrivate::GetWrappable<CallbackFunctionInterface>(object); - TypeTraits<CallbackFunctionInterface::VoidFunction >::ReturnType value = - impl->callback_attribute(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + CallbackFunctionInterface* impl = + wrapper_private->wrappable<CallbackFunctionInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->callback_attribute(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_callbackAttribute( @@ -152,18 +196,21 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + CallbackFunctionInterface* impl = + wrapper_private->wrappable<CallbackFunctionInterface>().get(); TypeTraits<CallbackFunctionInterface::VoidFunction >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - CallbackFunctionInterface* impl = - WrapperPrivate::GetWrappable<CallbackFunctionInterface>(object); + impl->set_callback_attribute(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool get_nullableCallbackAttribute( @@ -171,18 +218,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - CallbackFunctionInterface* impl = - WrapperPrivate::GetWrappable<CallbackFunctionInterface>(object); - TypeTraits<CallbackFunctionInterface::VoidFunction >::ReturnType value = - impl->nullable_callback_attribute(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + CallbackFunctionInterface* impl = + wrapper_private->wrappable<CallbackFunctionInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->nullable_callback_attribute(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_nullableCallbackAttribute( @@ -190,25 +240,26 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + CallbackFunctionInterface* impl = + wrapper_private->wrappable<CallbackFunctionInterface>().get(); TypeTraits<CallbackFunctionInterface::VoidFunction >::ConversionType value; FromJSValue(context, vp, (kConversionFlagNullable), &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - CallbackFunctionInterface* impl = - WrapperPrivate::GetWrappable<CallbackFunctionInterface>(object); + impl->set_nullable_callback_attribute(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_takesFunctionThatReturnsString( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -221,37 +272,41 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + CallbackFunctionInterface* impl = + wrapper_private->wrappable<CallbackFunctionInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<CallbackFunctionInterface::FunctionThatReturnsString >::ConversionType cb; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &cb); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &cb); + if (exception_state.is_exception_set()) { return false; } - CallbackFunctionInterface* impl = - WrapperPrivate::GetWrappable<CallbackFunctionInterface>(object); + impl->TakesFunctionThatReturnsString(cb); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_takesFunctionWithNullableParameters( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -264,37 +319,41 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + CallbackFunctionInterface* impl = + wrapper_private->wrappable<CallbackFunctionInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<CallbackFunctionInterface::FunctionWithNullableParameters >::ConversionType cb; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &cb); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &cb); + if (exception_state.is_exception_set()) { return false; } - CallbackFunctionInterface* impl = - WrapperPrivate::GetWrappable<CallbackFunctionInterface>(object); + impl->TakesFunctionWithNullableParameters(cb); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_takesFunctionWithOneParameter( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -307,37 +366,41 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + CallbackFunctionInterface* impl = + wrapper_private->wrappable<CallbackFunctionInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<CallbackFunctionInterface::FunctionWithOneParameter >::ConversionType cb; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &cb); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &cb); + if (exception_state.is_exception_set()) { return false; } - CallbackFunctionInterface* impl = - WrapperPrivate::GetWrappable<CallbackFunctionInterface>(object); + impl->TakesFunctionWithOneParameter(cb); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_takesFunctionWithSeveralParameters( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -350,37 +413,41 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + CallbackFunctionInterface* impl = + wrapper_private->wrappable<CallbackFunctionInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<CallbackFunctionInterface::FunctionWithSeveralParameters >::ConversionType cb; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &cb); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &cb); + if (exception_state.is_exception_set()) { return false; } - CallbackFunctionInterface* impl = - WrapperPrivate::GetWrappable<CallbackFunctionInterface>(object); + impl->TakesFunctionWithSeveralParameters(cb); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_takesVoidFunction( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -393,30 +460,36 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + CallbackFunctionInterface* impl = + wrapper_private->wrappable<CallbackFunctionInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<CallbackFunctionInterface::VoidFunction >::ConversionType cb; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &cb); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &cb); + if (exception_state.is_exception_set()) { return false; } - CallbackFunctionInterface* impl = - WrapperPrivate::GetWrappable<CallbackFunctionInterface>(object); + impl->TakesVoidFunction(cb); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -479,6 +552,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -498,7 +575,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -518,8 +596,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "CallbackFunctionInterface"; - name_value.setString(JS_NewStringCopyZ(context, "CallbackFunctionInterface")); + const char name[] = + "CallbackFunctionInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -528,8 +607,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -561,7 +645,7 @@ } // namespace // static -JSObject* MozjsCallbackFunctionInterface::CreateInstance( +JSObject* MozjsCallbackFunctionInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -569,8 +653,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsCallbackFunctionInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.h index 31b6166..e85e0f2 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.h
@@ -38,8 +38,9 @@ class MozjsCallbackFunctionInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.cc index a08045a..3a9b54c 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.cc
@@ -30,14 +30,20 @@ #include "cobalt/bindings/testing/single_operation_interface.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -55,6 +61,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -65,7 +72,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -79,6 +88,37 @@ namespace { +class MozjsCallbackInterfaceInterfaceHandler : public ProxyHandler { + public: + MozjsCallbackInterfaceInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsCallbackInterfaceInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsCallbackInterfaceInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsCallbackInterfaceInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -115,7 +155,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "CallbackInterfaceInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -133,18 +174,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - CallbackInterfaceInterface* impl = - WrapperPrivate::GetWrappable<CallbackInterfaceInterface>(object); - TypeTraits<CallbackInterfaceTraits<SingleOperationInterface > >::ReturnType value = - impl->callback_attribute(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + CallbackInterfaceInterface* impl = + wrapper_private->wrappable<CallbackInterfaceInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->callback_attribute(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_callbackAttribute( @@ -152,25 +196,26 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + CallbackInterfaceInterface* impl = + wrapper_private->wrappable<CallbackInterfaceInterface>().get(); TypeTraits<CallbackInterfaceTraits<SingleOperationInterface > >::ConversionType value; FromJSValue(context, vp, (kConversionFlagNullable), &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - CallbackInterfaceInterface* impl = - WrapperPrivate::GetWrappable<CallbackInterfaceInterface>(object); + impl->set_callback_attribute(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_registerCallback( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -183,37 +228,41 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + CallbackInterfaceInterface* impl = + wrapper_private->wrappable<CallbackInterfaceInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<CallbackInterfaceTraits<SingleOperationInterface > >::ConversionType callback_interface; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &callback_interface); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &callback_interface); + if (exception_state.is_exception_set()) { return false; } - CallbackInterfaceInterface* impl = - WrapperPrivate::GetWrappable<CallbackInterfaceInterface>(object); + impl->RegisterCallback(callback_interface); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_someOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -226,17 +275,17 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); CallbackInterfaceInterface* impl = - WrapperPrivate::GetWrappable<CallbackInterfaceInterface>(object); + wrapper_private->wrappable<CallbackInterfaceInterface>().get(); + impl->SomeOperation(); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -272,6 +321,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -291,7 +344,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -311,8 +365,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "CallbackInterfaceInterface"; - name_value.setString(JS_NewStringCopyZ(context, "CallbackInterfaceInterface")); + const char name[] = + "CallbackInterfaceInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -321,8 +376,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -354,7 +414,7 @@ } // namespace // static -JSObject* MozjsCallbackInterfaceInterface::CreateInstance( +JSObject* MozjsCallbackInterfaceInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -362,8 +422,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsCallbackInterfaceInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.h index 5b77c590..ea10dca 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.h
@@ -38,8 +38,9 @@ class MozjsCallbackInterfaceInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.cc index 8bb960b..eae8530 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.cc
@@ -30,14 +30,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -53,6 +59,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -63,7 +70,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -77,6 +86,37 @@ namespace { +class MozjsConditionalInterfaceHandler : public ProxyHandler { + public: + MozjsConditionalInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsConditionalInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsConditionalInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsConditionalInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -113,7 +153,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "ConditionalInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -132,18 +173,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - ConditionalInterface* impl = - WrapperPrivate::GetWrappable<ConditionalInterface>(object); - TypeTraits<int32_t >::ReturnType value = - impl->enabled_attribute(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + ConditionalInterface* impl = + wrapper_private->wrappable<ConditionalInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->enabled_attribute(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_enabledAttribute( @@ -151,18 +195,21 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + ConditionalInterface* impl = + wrapper_private->wrappable<ConditionalInterface>().get(); TypeTraits<int32_t >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - ConditionalInterface* impl = - WrapperPrivate::GetWrappable<ConditionalInterface>(object); + impl->set_enabled_attribute(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } #endif // ENABLE_CONDITIONAL_PROPERTY @@ -172,18 +219,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - ConditionalInterface* impl = - WrapperPrivate::GetWrappable<ConditionalInterface>(object); - TypeTraits<int32_t >::ReturnType value = - impl->disabled_attribute(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + ConditionalInterface* impl = + wrapper_private->wrappable<ConditionalInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->disabled_attribute(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_disabledAttribute( @@ -191,27 +241,28 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + ConditionalInterface* impl = + wrapper_private->wrappable<ConditionalInterface>().get(); TypeTraits<int32_t >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - ConditionalInterface* impl = - WrapperPrivate::GetWrappable<ConditionalInterface>(object); + impl->set_disabled_attribute(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } #endif // NO_ENABLE_CONDITIONAL_PROPERTY #if defined(NO_ENABLE_CONDITIONAL_PROPERTY) JSBool fcn_disabledOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -224,26 +275,24 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); ConditionalInterface* impl = - WrapperPrivate::GetWrappable<ConditionalInterface>(object); + wrapper_private->wrappable<ConditionalInterface>().get(); + impl->DisabledOperation(); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } #endif // NO_ENABLE_CONDITIONAL_PROPERTY #if defined(ENABLE_CONDITIONAL_PROPERTY) JSBool fcn_enabledOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -256,17 +305,17 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); ConditionalInterface* impl = - WrapperPrivate::GetWrappable<ConditionalInterface>(object); + wrapper_private->wrappable<ConditionalInterface>().get(); + impl->EnabledOperation(); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } #endif // ENABLE_CONDITIONAL_PROPERTY @@ -317,6 +366,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -336,7 +389,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -356,8 +410,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "ConditionalInterface"; - name_value.setString(JS_NewStringCopyZ(context, "ConditionalInterface")); + const char name[] = + "ConditionalInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -366,8 +421,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -399,7 +459,7 @@ } // namespace // static -JSObject* MozjsConditionalInterface::CreateInstance( +JSObject* MozjsConditionalInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -407,8 +467,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsConditionalInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.h index 93e67b4..76eae81 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.h
@@ -40,8 +40,9 @@ class MozjsConditionalInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.cc index 3648f49..06ca83e 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -74,6 +83,37 @@ namespace testing { namespace { + +class MozjsConstantsInterfaceHandler : public ProxyHandler { + public: + MozjsConstantsInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsConstantsInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsConstantsInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsConstantsInterfaceHandler> + proxy_handler; + JSBool get_INTEGER_CONSTANT( JSContext* context, JS::HandleObject object, JS::HandleId id, JS::MutableHandleValue vp) { @@ -81,11 +121,11 @@ ValueForConstantsInterface_kIntegerConstantDoesNotMatchIDL); MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - ToJSValue(context, 5, &exception_state, &result_value); - if (!exception_state.IsExceptionSet()) { - vp.set(result_value); + ToJSValue(context, 5, &result_value); + if (!exception_state.is_exception_set()) { + vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool get_DOUBLE_CONSTANT( @@ -96,11 +136,11 @@ "the value in the interface definition."; MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - ToJSValue(context, 2.718, &exception_state, &result_value); - if (!exception_state.IsExceptionSet()) { - vp.set(result_value); + ToJSValue(context, 2.718, &result_value); + if (!exception_state.is_exception_set()) { + vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -140,7 +180,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "ConstantsInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -190,6 +231,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -209,7 +254,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -229,8 +275,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "ConstantsInterface"; - name_value.setString(JS_NewStringCopyZ(context, "ConstantsInterface")); + const char name[] = + "ConstantsInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -239,8 +286,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -272,7 +324,7 @@ } // namespace // static -JSObject* MozjsConstantsInterface::CreateInstance( +JSObject* MozjsConstantsInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -280,8 +332,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsConstantsInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.h index 3d9384c..fe793ef 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.h
@@ -38,8 +38,9 @@ class MozjsConstantsInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.cc index c70a26d..7ca19b8 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -74,7 +83,38 @@ namespace testing { namespace { -JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args); + +class MozjsConstructorInterfaceHandler : public ProxyHandler { + public: + MozjsConstructorInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsConstructorInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsConstructorInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsConstructorInterfaceHandler> + proxy_handler; + +JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp); InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); @@ -112,7 +152,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "ConstructorInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -139,6 +180,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -158,7 +203,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -178,18 +224,34 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "ConstructorInterface"; - name_value.setString(JS_NewStringCopyZ(context, "ConstructorInterface")); + const char name[] = + "ConstructorInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, JSPROP_READONLY); DCHECK(success); + // Add the InterfaceObject.length property. It is set to the length of the + // shortest argument list of all overload constructors. + JS::RootedValue length_value(context); + length_value.setInt32(0); + success = + JS_DefineProperty(context, rooted_interface_object, "length", + length_value, JS_PropertyStub, JS_StrictPropertyStub, + JSPROP_READONLY); + DCHECK(success); + // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -221,7 +283,7 @@ } // namespace // static -JSObject* MozjsConstructorInterface::CreateInstance( +JSObject* MozjsConstructorInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -229,8 +291,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsConstructorInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static @@ -256,11 +329,85 @@ namespace { -JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args) { - // TODO: Implement support for constructors. - NOTIMPLEMENTED(); +JSBool Constructor1( + JSContext* context, unsigned int argc, JS::Value* vp) { + MozjsExceptionState exception_state(context); + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + + scoped_refptr<ConstructorInterface> new_object = + new ConstructorInterface(); + JS::RootedValue result_value(context); + ToJSValue(context, new_object, &result_value); + DCHECK(result_value.isObject()); + JS::RootedObject result_object(context, JSVAL_TO_OBJECT(result_value)); + args.rval().setObject(*result_object); return true; } + +JSBool Constructor2( + JSContext* context, unsigned int argc, JS::Value* vp) { + MozjsExceptionState exception_state(context); + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + const size_t kMinArguments = 1; + if (args.length() < kMinArguments) { + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Not enough arguments."); + return false; + } + // Non-optional arguments + TypeTraits<bool >::ConversionType arg; + + DCHECK_LT(0, args.length()); + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg); + if (exception_state.is_exception_set()) { + return false; + } + + scoped_refptr<ConstructorInterface> new_object = + new ConstructorInterface(arg); + JS::RootedValue result_value(context); + ToJSValue(context, new_object, &result_value); + DCHECK(result_value.isObject()); + JS::RootedObject result_object(context, JSVAL_TO_OBJECT(result_value)); + args.rval().setObject(*result_object); + return true; +} + +JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp) { + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + switch(argc) { + case(0): { + // Overload resolution algorithm details found here: + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + if (true) { + return Constructor1( + context, argc, vp); + } + break; + } + case(1): { + // Overload resolution algorithm details found here: + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + if (true) { + return Constructor2( + context, argc, vp); + } + break; + } + } + // Invalid number of args + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + // 4. If S is empty, then throw a TypeError. + MozjsExceptionState exception_state(context); + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Invalid number of arguments."); + return false; +} } // namespace
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.h index 12b63d4..d04a69f 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.h
@@ -38,8 +38,9 @@ class MozjsConstructorInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.cc index d235a17..cdc6b94 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -74,7 +83,38 @@ namespace testing { namespace { -JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args); + +class MozjsConstructorWithArgumentsInterfaceHandler : public ProxyHandler { + public: + MozjsConstructorWithArgumentsInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsConstructorWithArgumentsInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsConstructorWithArgumentsInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsConstructorWithArgumentsInterfaceHandler> + proxy_handler; + +JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp); InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); @@ -112,7 +152,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "ConstructorWithArgumentsInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -131,18 +172,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - ConstructorWithArgumentsInterface* impl = - WrapperPrivate::GetWrappable<ConstructorWithArgumentsInterface>(object); - TypeTraits<int32_t >::ReturnType value = - impl->long_arg(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + ConstructorWithArgumentsInterface* impl = + wrapper_private->wrappable<ConstructorWithArgumentsInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->long_arg(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool get_booleanArg( @@ -150,18 +194,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - ConstructorWithArgumentsInterface* impl = - WrapperPrivate::GetWrappable<ConstructorWithArgumentsInterface>(object); - TypeTraits<bool >::ReturnType value = - impl->boolean_arg(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + ConstructorWithArgumentsInterface* impl = + wrapper_private->wrappable<ConstructorWithArgumentsInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->boolean_arg(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool get_stringArg( @@ -169,18 +216,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - ConstructorWithArgumentsInterface* impl = - WrapperPrivate::GetWrappable<ConstructorWithArgumentsInterface>(object); - TypeTraits<std::string >::ReturnType value = - impl->string_arg(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + ConstructorWithArgumentsInterface* impl = + wrapper_private->wrappable<ConstructorWithArgumentsInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->string_arg(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -214,6 +264,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -233,7 +287,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -253,18 +308,34 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "ConstructorWithArgumentsInterface"; - name_value.setString(JS_NewStringCopyZ(context, "ConstructorWithArgumentsInterface")); + const char name[] = + "ConstructorWithArgumentsInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, JSPROP_READONLY); DCHECK(success); + // Add the InterfaceObject.length property. It is set to the length of the + // shortest argument list of all overload constructors. + JS::RootedValue length_value(context); + length_value.setInt32(2); + success = + JS_DefineProperty(context, rooted_interface_object, "length", + length_value, JS_PropertyStub, JS_StrictPropertyStub, + JSPROP_READONLY); + DCHECK(success); + // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -296,7 +367,7 @@ } // namespace // static -JSObject* MozjsConstructorWithArgumentsInterface::CreateInstance( +JSObject* MozjsConstructorWithArgumentsInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -304,8 +375,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsConstructorWithArgumentsInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static @@ -331,9 +413,64 @@ namespace { -JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args) { - // TODO: Implement support for constructors. - NOTIMPLEMENTED(); +JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp) { + MozjsExceptionState exception_state(context); + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + const size_t kMinArguments = 2; + if (args.length() < kMinArguments) { + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Not enough arguments."); + return false; + } + // Non-optional arguments + TypeTraits<int32_t >::ConversionType arg1; + TypeTraits<bool >::ConversionType arg2; + // Optional arguments with default values + TypeTraits<std::string >::ConversionType default_arg = + "default"; + + DCHECK_LT(0, args.length()); + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg1); + if (exception_state.is_exception_set()) { + return false; + } + + DCHECK_LT(1, args.length()); + JS::RootedValue non_optional_value1( + context, args[1]); + FromJSValue(context, + non_optional_value1, + kNoConversionFlags, + &exception_state, &arg2); + if (exception_state.is_exception_set()) { + return false; + } + size_t num_set_arguments = 3; + if (args.length() > 2) { + JS::RootedValue optional_value0( + context, args[2]); + FromJSValue(context, + optional_value0, + kNoConversionFlags, + &exception_state, + &default_arg); + if (exception_state.is_exception_set()) { + return false; + } + } + + scoped_refptr<ConstructorWithArgumentsInterface> new_object = + new ConstructorWithArgumentsInterface(arg1, arg2, default_arg); + JS::RootedValue result_value(context); + ToJSValue(context, new_object, &result_value); + DCHECK(result_value.isObject()); + JS::RootedObject result_object(context, JSVAL_TO_OBJECT(result_value)); + args.rval().setObject(*result_object); return true; } } // namespace
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.h index cb43afe..44d36d4 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.h
@@ -38,8 +38,9 @@ class MozjsConstructorWithArgumentsInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.cc index 1621a7b..bc6eb8b 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -75,6 +84,37 @@ namespace { +class MozjsDOMStringTestInterfaceHandler : public ProxyHandler { + public: + MozjsDOMStringTestInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsDOMStringTestInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsDOMStringTestInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsDOMStringTestInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -111,7 +151,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "DOMStringTestInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -129,18 +170,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - DOMStringTestInterface* impl = - WrapperPrivate::GetWrappable<DOMStringTestInterface>(object); - TypeTraits<std::string >::ReturnType value = - impl->property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DOMStringTestInterface* impl = + wrapper_private->wrappable<DOMStringTestInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_property( @@ -148,18 +192,21 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DOMStringTestInterface* impl = + wrapper_private->wrappable<DOMStringTestInterface>().get(); TypeTraits<std::string >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - DOMStringTestInterface* impl = - WrapperPrivate::GetWrappable<DOMStringTestInterface>(object); + impl->set_property(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool get_readOnlyProperty( @@ -167,18 +214,43 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - DOMStringTestInterface* impl = - WrapperPrivate::GetWrappable<DOMStringTestInterface>(object); - TypeTraits<std::string >::ReturnType value = - impl->read_only_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DOMStringTestInterface* impl = + wrapper_private->wrappable<DOMStringTestInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->read_only_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); +} + +JSBool get_readOnlyTokenProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JS::MutableHandleValue vp) { + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DOMStringTestInterface* impl = + wrapper_private->wrappable<DOMStringTestInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->read_only_token_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { + vp.set(result_value); + } + return !exception_state.is_exception_set(); } JSBool get_nullIsEmptyProperty( @@ -186,18 +258,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - DOMStringTestInterface* impl = - WrapperPrivate::GetWrappable<DOMStringTestInterface>(object); - TypeTraits<std::string >::ReturnType value = - impl->null_is_empty_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DOMStringTestInterface* impl = + wrapper_private->wrappable<DOMStringTestInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->null_is_empty_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_nullIsEmptyProperty( @@ -205,18 +280,21 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DOMStringTestInterface* impl = + wrapper_private->wrappable<DOMStringTestInterface>().get(); TypeTraits<std::string >::ConversionType value; FromJSValue(context, vp, (kConversionFlagTreatNullAsEmptyString), &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - DOMStringTestInterface* impl = - WrapperPrivate::GetWrappable<DOMStringTestInterface>(object); + impl->set_null_is_empty_property(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool get_undefinedIsEmptyProperty( @@ -224,18 +302,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - DOMStringTestInterface* impl = - WrapperPrivate::GetWrappable<DOMStringTestInterface>(object); - TypeTraits<std::string >::ReturnType value = - impl->undefined_is_empty_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DOMStringTestInterface* impl = + wrapper_private->wrappable<DOMStringTestInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->undefined_is_empty_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_undefinedIsEmptyProperty( @@ -243,18 +324,21 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DOMStringTestInterface* impl = + wrapper_private->wrappable<DOMStringTestInterface>().get(); TypeTraits<std::string >::ConversionType value; FromJSValue(context, vp, (kConversionFlagTreatUndefinedAsEmptyString), &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - DOMStringTestInterface* impl = - WrapperPrivate::GetWrappable<DOMStringTestInterface>(object); + impl->set_undefined_is_empty_property(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool get_nullableUndefinedIsEmptyProperty( @@ -262,18 +346,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - DOMStringTestInterface* impl = - WrapperPrivate::GetWrappable<DOMStringTestInterface>(object); - TypeTraits<base::optional<std::string > >::ReturnType value = - impl->nullable_undefined_is_empty_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DOMStringTestInterface* impl = + wrapper_private->wrappable<DOMStringTestInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->nullable_undefined_is_empty_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_nullableUndefinedIsEmptyProperty( @@ -281,18 +368,21 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DOMStringTestInterface* impl = + wrapper_private->wrappable<DOMStringTestInterface>().get(); TypeTraits<base::optional<std::string > >::ConversionType value; FromJSValue(context, vp, (kConversionFlagNullable | kConversionFlagTreatUndefinedAsEmptyString), &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - DOMStringTestInterface* impl = - WrapperPrivate::GetWrappable<DOMStringTestInterface>(object); + impl->set_nullable_undefined_is_empty_property(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -309,6 +399,12 @@ JSOP_WRAPPER(&get_readOnlyProperty), JSOP_NULLWRAPPER, }, + { // Readonly attribute + "readOnlyTokenProperty", 0, + JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_READONLY, + JSOP_WRAPPER(&get_readOnlyTokenProperty), + JSOP_NULLWRAPPER, + }, { // Read/Write property "nullIsEmptyProperty", 0, JSPROP_SHARED | JSPROP_ENUMERATE, @@ -338,6 +434,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -357,7 +457,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -377,8 +478,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "DOMStringTestInterface"; - name_value.setString(JS_NewStringCopyZ(context, "DOMStringTestInterface")); + const char name[] = + "DOMStringTestInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -387,8 +489,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -420,7 +527,7 @@ } // namespace // static -JSObject* MozjsDOMStringTestInterface::CreateInstance( +JSObject* MozjsDOMStringTestInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -428,8 +535,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsDOMStringTestInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.h index a6b0007..0cde0d8 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.h
@@ -38,8 +38,9 @@ class MozjsDOMStringTestInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc index cbca054..7770e5c 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -75,6 +84,219 @@ namespace { +bool IsSupportedNamedProperty(JSContext* context, JS::HandleObject object, + const std::string& property_name) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DerivedGetterSetterInterface* impl = + wrapper_private->wrappable<DerivedGetterSetterInterface>().get(); + return impl->CanQueryNamedProperty(property_name); +} + +void EnumerateSupportedNames(JSContext* context, JS::HandleObject object, + JS::AutoIdVector* properties) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DerivedGetterSetterInterface* impl = + wrapper_private->wrappable<DerivedGetterSetterInterface>().get(); + MozjsPropertyEnumerator enumerator(context, properties); + impl->EnumerateNamedProperties(&enumerator); +} + +JSBool GetNamedProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JS::MutableHandleValue vp) { + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DerivedGetterSetterInterface* impl = + wrapper_private->wrappable<DerivedGetterSetterInterface>().get(); + std::string property_name; + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, + &property_name); + if(exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->AnonymousNamedGetter(property_name), + &result_value); + } + if (!exception_state.is_exception_set()) { + vp.set(result_value); + } + return !exception_state.is_exception_set(); +} + +JSBool SetNamedProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JSBool strict, JS::MutableHandleValue vp) { + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DerivedGetterSetterInterface* impl = + wrapper_private->wrappable<DerivedGetterSetterInterface>().get(); + std::string property_name; + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, + &property_name); + if(exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } + TypeTraits<std::string >::ConversionType value; + FromJSValue(context, vp, kNoConversionFlags, + &exception_state, &value); + if (exception_state.is_exception_set()) { + return false; + } + + impl->AnonymousNamedSetter(property_name, value); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +bool IsSupportedIndexProperty(JSContext* context, JS::HandleObject object, + uint32_t index) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DerivedGetterSetterInterface* impl = + wrapper_private->wrappable<DerivedGetterSetterInterface>().get(); + return index < impl->length(); +} + +void EnumerateSupportedIndexes(JSContext* context, JS::HandleObject object, + JS::AutoIdVector* properties) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DerivedGetterSetterInterface* impl = + wrapper_private->wrappable<DerivedGetterSetterInterface>().get(); + const uint32_t kNumIndexedProperties = impl->length(); + for (uint32_t i = 0; i < kNumIndexedProperties; ++i) { + properties->append(INT_TO_JSID(i)); + } +} + +JSBool GetIndexedProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JS::MutableHandleValue vp) { + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DerivedGetterSetterInterface* impl = + wrapper_private->wrappable<DerivedGetterSetterInterface>().get(); + uint32_t index; + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, &index); + if(exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->DerivedIndexedGetter(index), + &result_value); + } + if (!exception_state.is_exception_set()) { + vp.set(result_value); + } + return !exception_state.is_exception_set(); +} + +JSBool SetIndexedProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JSBool strict, JS::MutableHandleValue vp) { + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DerivedGetterSetterInterface* impl = + wrapper_private->wrappable<DerivedGetterSetterInterface>().get(); + uint32_t index; + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, &index); + if(exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } + TypeTraits<uint32_t >::ConversionType value; + FromJSValue(context, vp, kNoConversionFlags, + &exception_state, &value); + if (exception_state.is_exception_set()) { + return false; + } + + impl->DerivedIndexedSetter(index, value); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +class MozjsDerivedGetterSetterInterfaceHandler : public ProxyHandler { + public: + MozjsDerivedGetterSetterInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsDerivedGetterSetterInterfaceHandler::named_property_hooks = { + IsSupportedNamedProperty, + EnumerateSupportedNames, + GetNamedProperty, + SetNamedProperty, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsDerivedGetterSetterInterfaceHandler::indexed_property_hooks = { + IsSupportedIndexProperty, + EnumerateSupportedIndexes, + GetIndexedProperty, + SetIndexedProperty, + NULL, +}; + +static base::LazyInstance<MozjsDerivedGetterSetterInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -111,7 +333,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "DerivedGetterSetterInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -129,18 +352,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - DerivedGetterSetterInterface* impl = - WrapperPrivate::GetWrappable<DerivedGetterSetterInterface>(object); - TypeTraits<uint32_t >::ReturnType value = - impl->length(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DerivedGetterSetterInterface* impl = + wrapper_private->wrappable<DerivedGetterSetterInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->length(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool get_propertyOnDerivedClass( @@ -148,18 +374,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - DerivedGetterSetterInterface* impl = - WrapperPrivate::GetWrappable<DerivedGetterSetterInterface>(object); - TypeTraits<bool >::ReturnType value = - impl->property_on_derived_class(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DerivedGetterSetterInterface* impl = + wrapper_private->wrappable<DerivedGetterSetterInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->property_on_derived_class(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_propertyOnDerivedClass( @@ -167,25 +396,26 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DerivedGetterSetterInterface* impl = + wrapper_private->wrappable<DerivedGetterSetterInterface>().get(); TypeTraits<bool >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - DerivedGetterSetterInterface* impl = - WrapperPrivate::GetWrappable<DerivedGetterSetterInterface>(object); + impl->set_property_on_derived_class(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_derivedIndexedGetter( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -198,40 +428,47 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DerivedGetterSetterInterface* impl = + wrapper_private->wrappable<DerivedGetterSetterInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<uint32_t >::ConversionType index; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &index); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &index); + if (exception_state.is_exception_set()) { return false; } - DerivedGetterSetterInterface* impl = - WrapperPrivate::GetWrappable<DerivedGetterSetterInterface>(object); - TypeTraits<uint32_t >::ReturnType value = - impl->DerivedIndexedGetter(index); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->DerivedIndexedGetter(index), + &result_value); + } + if (!exception_state.is_exception_set()) { args.rval().set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_derivedIndexedSetter( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -244,44 +481,53 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DerivedGetterSetterInterface* impl = + wrapper_private->wrappable<DerivedGetterSetterInterface>().get(); const size_t kMinArguments = 2; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<uint32_t >::ConversionType index; - DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &index); - if (exception_state.IsExceptionSet()) { - return false; - } TypeTraits<uint32_t >::ConversionType value; - DCHECK_LT(1, args.length()); - FromJSValue(context, args.handleAt(1), - kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + + DCHECK_LT(0, args.length()); + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &index); + if (exception_state.is_exception_set()) { return false; } - DerivedGetterSetterInterface* impl = - WrapperPrivate::GetWrappable<DerivedGetterSetterInterface>(object); + + DCHECK_LT(1, args.length()); + JS::RootedValue non_optional_value1( + context, args[1]); + FromJSValue(context, + non_optional_value1, + kNoConversionFlags, + &exception_state, &value); + if (exception_state.is_exception_set()) { + return false; + } + impl->DerivedIndexedSetter(index, value); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_operationOnDerivedClass( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -294,17 +540,17 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); DerivedGetterSetterInterface* impl = - WrapperPrivate::GetWrappable<DerivedGetterSetterInterface>(object); + wrapper_private->wrappable<DerivedGetterSetterInterface>().get(); + impl->OperationOnDerivedClass(); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -353,6 +599,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -372,7 +622,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -392,8 +643,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "DerivedGetterSetterInterface"; - name_value.setString(JS_NewStringCopyZ(context, "DerivedGetterSetterInterface")); + const char name[] = + "DerivedGetterSetterInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -402,8 +654,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -435,7 +692,7 @@ } // namespace // static -JSObject* MozjsDerivedGetterSetterInterface::CreateInstance( +JSObject* MozjsDerivedGetterSetterInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -443,8 +700,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsDerivedGetterSetterInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.h index 3aeb1ad..6913c19 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.h
@@ -39,8 +39,9 @@ class MozjsDerivedGetterSetterInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.cc index 2112c3d..96a27ce 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -75,6 +84,38 @@ namespace { +class MozjsDerivedInterfaceHandler : public ProxyHandler { + public: + MozjsDerivedInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsDerivedInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsDerivedInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsDerivedInterfaceHandler> + proxy_handler; + +JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp); + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -111,7 +152,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "DerivedInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -121,6 +163,7 @@ interface_object_class->enumerate = JS_EnumerateStub; interface_object_class->resolve = JS_ResolveStub; interface_object_class->convert = JS_ConvertStub; + interface_object_class->construct = Constructor; return interface_data; } @@ -129,25 +172,26 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - DerivedInterface* impl = - WrapperPrivate::GetWrappable<DerivedInterface>(object); - TypeTraits<std::string >::ReturnType value = - impl->derived_attribute(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DerivedInterface* impl = + wrapper_private->wrappable<DerivedInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->derived_attribute(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_derivedOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -160,17 +204,17 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); DerivedInterface* impl = - WrapperPrivate::GetWrappable<DerivedInterface>(object); + wrapper_private->wrappable<DerivedInterface>().get(); + impl->DerivedOperation(); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -199,6 +243,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -218,7 +266,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -238,18 +287,34 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "DerivedInterface"; - name_value.setString(JS_NewStringCopyZ(context, "DerivedInterface")); + const char name[] = + "DerivedInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, JSPROP_READONLY); DCHECK(success); + // Add the InterfaceObject.length property. It is set to the length of the + // shortest argument list of all overload constructors. + JS::RootedValue length_value(context); + length_value.setInt32(0); + success = + JS_DefineProperty(context, rooted_interface_object, "length", + length_value, JS_PropertyStub, JS_StrictPropertyStub, + JSPROP_READONLY); + DCHECK(success); + // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -281,7 +346,7 @@ } // namespace // static -JSObject* MozjsDerivedInterface::CreateInstance( +JSObject* MozjsDerivedInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -289,8 +354,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsDerivedInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static @@ -316,6 +392,19 @@ namespace { +JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp) { + MozjsExceptionState exception_state(context); + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + + scoped_refptr<DerivedInterface> new_object = + new DerivedInterface(); + JS::RootedValue result_value(context); + ToJSValue(context, new_object, &result_value); + DCHECK(result_value.isObject()); + JS::RootedObject result_object(context, JSVAL_TO_OBJECT(result_value)); + args.rval().setObject(*result_object); + return true; +} } // namespace
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.h index 328c87b..59beb06 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.h
@@ -39,8 +39,9 @@ class MozjsDerivedInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.cc index 862c849..baf4573 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.cc
@@ -30,14 +30,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -53,6 +59,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -63,7 +70,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -77,6 +86,37 @@ namespace { +class MozjsDisabledInterfaceHandler : public ProxyHandler { + public: + MozjsDisabledInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsDisabledInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsDisabledInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsDisabledInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -113,7 +153,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "DisabledInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -131,18 +172,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - DisabledInterface* impl = - WrapperPrivate::GetWrappable<DisabledInterface>(object); - TypeTraits<int32_t >::ReturnType value = - impl->disabled_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DisabledInterface* impl = + wrapper_private->wrappable<DisabledInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->disabled_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_disabledProperty( @@ -150,25 +194,26 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + DisabledInterface* impl = + wrapper_private->wrappable<DisabledInterface>().get(); TypeTraits<int32_t >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - DisabledInterface* impl = - WrapperPrivate::GetWrappable<DisabledInterface>(object); + impl->set_disabled_property(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_disabledFunction( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -181,17 +226,17 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); DisabledInterface* impl = - WrapperPrivate::GetWrappable<DisabledInterface>(object); + wrapper_private->wrappable<DisabledInterface>().get(); + impl->DisabledFunction(); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -220,6 +265,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -239,7 +288,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -259,8 +309,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "DisabledInterface"; - name_value.setString(JS_NewStringCopyZ(context, "DisabledInterface")); + const char name[] = + "DisabledInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -269,8 +320,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -302,7 +358,7 @@ } // namespace // static -JSObject* MozjsDisabledInterface::CreateInstance( +JSObject* MozjsDisabledInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -310,8 +366,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsDisabledInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.h index 6b5f628..360c946 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.h
@@ -40,8 +40,9 @@ class MozjsDisabledInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.cc index 8255e6f..2ed75aa 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,12 +68,23 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; using cobalt::script::mozjs::WrapperFactory; using cobalt::script::Wrappable; +// Declare and define these in the same namespace that the other overloads +// were brought into with the using declaration. +void ToJSValue( + JSContext* context, + EnumerationInterface::TestEnum in_enum, + JS::MutableHandleValue out_value); +void FromJSValue(JSContext* context, JS::HandleValue value, + int conversion_flags, ExceptionState* exception_state, + EnumerationInterface::TestEnum* out_enum); } // namespace namespace cobalt { @@ -74,7 +92,38 @@ namespace testing { namespace { -JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args); + +class MozjsEnumerationInterfaceHandler : public ProxyHandler { + public: + MozjsEnumerationInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsEnumerationInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsEnumerationInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsEnumerationInterfaceHandler> + proxy_handler; + +JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp); InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); @@ -112,7 +161,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "EnumerationInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -131,18 +181,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - EnumerationInterface* impl = - WrapperPrivate::GetWrappable<EnumerationInterface>(object); - TypeTraits<EnumerationInterface::TestEnum >::ReturnType value = - impl->enum_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + EnumerationInterface* impl = + wrapper_private->wrappable<EnumerationInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->enum_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_enumProperty( @@ -150,18 +203,21 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + EnumerationInterface* impl = + wrapper_private->wrappable<EnumerationInterface>().get(); TypeTraits<EnumerationInterface::TestEnum >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - EnumerationInterface* impl = - WrapperPrivate::GetWrappable<EnumerationInterface>(object); + impl->set_enum_property(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -183,6 +239,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -202,7 +262,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -222,18 +283,34 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "EnumerationInterface"; - name_value.setString(JS_NewStringCopyZ(context, "EnumerationInterface")); + const char name[] = + "EnumerationInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, JSPROP_READONLY); DCHECK(success); + // Add the InterfaceObject.length property. It is set to the length of the + // shortest argument list of all overload constructors. + JS::RootedValue length_value(context); + length_value.setInt32(0); + success = + JS_DefineProperty(context, rooted_interface_object, "length", + length_value, JS_PropertyStub, JS_StrictPropertyStub, + JSPROP_READONLY); + DCHECK(success); + // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -265,7 +342,7 @@ } // namespace // static -JSObject* MozjsEnumerationInterface::CreateInstance( +JSObject* MozjsEnumerationInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -273,8 +350,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsEnumerationInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static @@ -300,9 +388,17 @@ namespace { -JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args) { - // TODO: Implement support for constructors. - NOTIMPLEMENTED(); +JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp) { + MozjsExceptionState exception_state(context); + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + + scoped_refptr<EnumerationInterface> new_object = + new EnumerationInterface(); + JS::RootedValue result_value(context); + ToJSValue(context, new_object, &result_value); + DCHECK(result_value.isObject()); + JS::RootedObject result_object(context, JSVAL_TO_OBJECT(result_value)); + args.rval().setObject(*result_object); return true; } } // namespace @@ -313,4 +409,55 @@ } // namespace cobalt namespace { + +inline void ToJSValue( + JSContext* context, + EnumerationInterface::TestEnum in_enum, + JS::MutableHandleValue out_value) { + + switch (in_enum) { + case EnumerationInterface::kAlpha: + ToJSValue(context, std::string("alpha"), out_value); + return; + case EnumerationInterface::kBeta: + ToJSValue(context, std::string("beta"), out_value); + return; + case EnumerationInterface::kGamma: + ToJSValue(context, std::string("gamma"), out_value); + return; + } +} + + +inline void FromJSValue(JSContext* context, JS::HandleValue value, + int conversion_flags, ExceptionState* exception_state, + EnumerationInterface::TestEnum* out_enum) { + DCHECK_EQ(0, conversion_flags) << "Unexpected conversion flags."; + // JSValue -> IDL enum algorithm described here: + // http://heycam.github.io/webidl/#es-enumeration + // 1. Let S be the result of calling ToString(V). + JS::RootedString rooted_string(context, JS_ValueToString(context, value)); + + JSBool match = JS_FALSE; +// 3. Return the enumeration value of type E that is equal to S. +if (JS_StringEqualsAscii( + context, rooted_string, "alpha", &match) + && match) { + *out_enum = EnumerationInterface::kAlpha; + } else if (JS_StringEqualsAscii( + context, rooted_string, "beta", &match) + && match) { + *out_enum = EnumerationInterface::kBeta; + } else if (JS_StringEqualsAscii( + context, rooted_string, "gamma", &match) + && match) { + *out_enum = EnumerationInterface::kGamma; + } else { + // 2. If S is not one of E's enumeration values, then throw a TypeError. + exception_state-> + SetSimpleException(ExceptionState::kTypeError, + "Cannot convert JavaScript value to Enum."); + return; + } +} } // namespace
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.h index 20b7fcc..b4b3e19 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.h
@@ -38,8 +38,9 @@ class MozjsEnumerationInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.cc index 39285e8..498e223 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -75,6 +84,37 @@ namespace { +class MozjsExceptionObjectInterfaceHandler : public ProxyHandler { + public: + MozjsExceptionObjectInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsExceptionObjectInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsExceptionObjectInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsExceptionObjectInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -111,7 +151,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "ExceptionObjectInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -129,18 +170,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - ExceptionObjectInterface* impl = - WrapperPrivate::GetWrappable<ExceptionObjectInterface>(object); - TypeTraits<std::string >::ReturnType value = - impl->error(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + ExceptionObjectInterface* impl = + wrapper_private->wrappable<ExceptionObjectInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->error(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool get_message( @@ -148,18 +192,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - ExceptionObjectInterface* impl = - WrapperPrivate::GetWrappable<ExceptionObjectInterface>(object); - TypeTraits<std::string >::ReturnType value = - impl->message(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + ExceptionObjectInterface* impl = + wrapper_private->wrappable<ExceptionObjectInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->message(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -187,6 +234,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -206,7 +257,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -226,8 +278,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "ExceptionObjectInterface"; - name_value.setString(JS_NewStringCopyZ(context, "ExceptionObjectInterface")); + const char name[] = + "ExceptionObjectInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -236,8 +289,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -269,7 +327,7 @@ } // namespace // static -JSObject* MozjsExceptionObjectInterface::CreateInstance( +JSObject* MozjsExceptionObjectInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -277,8 +335,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsExceptionObjectInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.h index 747e528..0ba0055 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.h
@@ -38,8 +38,9 @@ class MozjsExceptionObjectInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.cc index dc19788..21cbe31 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -74,7 +83,38 @@ namespace testing { namespace { -JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args); + +class MozjsExceptionsInterfaceHandler : public ProxyHandler { + public: + MozjsExceptionsInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsExceptionsInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsExceptionsInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsExceptionsInterfaceHandler> + proxy_handler; + +JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp); InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); @@ -112,7 +152,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "ExceptionsInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -131,18 +172,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - ExceptionsInterface* impl = - WrapperPrivate::GetWrappable<ExceptionsInterface>(object); - TypeTraits<bool >::ReturnType value = - impl->attribute_throws_exception(&exception_state); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + ExceptionsInterface* impl = + wrapper_private->wrappable<ExceptionsInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->attribute_throws_exception(&exception_state), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_attributeThrowsException( @@ -150,25 +194,26 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + ExceptionsInterface* impl = + wrapper_private->wrappable<ExceptionsInterface>().get(); TypeTraits<bool >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - ExceptionsInterface* impl = - WrapperPrivate::GetWrappable<ExceptionsInterface>(object); + impl->set_attribute_throws_exception(value, &exception_state); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_functionThrowsException( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -181,17 +226,17 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); ExceptionsInterface* impl = - WrapperPrivate::GetWrappable<ExceptionsInterface>(object); + wrapper_private->wrappable<ExceptionsInterface>().get(); + impl->FunctionThrowsException(&exception_state); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -220,6 +265,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -239,7 +288,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -259,18 +309,34 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "ExceptionsInterface"; - name_value.setString(JS_NewStringCopyZ(context, "ExceptionsInterface")); + const char name[] = + "ExceptionsInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, JSPROP_READONLY); DCHECK(success); + // Add the InterfaceObject.length property. It is set to the length of the + // shortest argument list of all overload constructors. + JS::RootedValue length_value(context); + length_value.setInt32(0); + success = + JS_DefineProperty(context, rooted_interface_object, "length", + length_value, JS_PropertyStub, JS_StrictPropertyStub, + JSPROP_READONLY); + DCHECK(success); + // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -302,7 +368,7 @@ } // namespace // static -JSObject* MozjsExceptionsInterface::CreateInstance( +JSObject* MozjsExceptionsInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -310,8 +376,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsExceptionsInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static @@ -337,9 +414,17 @@ namespace { -JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args) { - // TODO: Implement support for constructors. - NOTIMPLEMENTED(); +JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp) { + MozjsExceptionState exception_state(context); + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + + scoped_refptr<ExceptionsInterface> new_object = + new ExceptionsInterface(&exception_state); + JS::RootedValue result_value(context); + ToJSValue(context, new_object, &result_value); + DCHECK(result_value.isObject()); + JS::RootedObject result_object(context, JSVAL_TO_OBJECT(result_value)); + args.rval().setObject(*result_object); return true; } } // namespace
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.h index f85051d..b5fe100 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.h
@@ -38,8 +38,9 @@ class MozjsExceptionsInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.cc index a9c4572..06bcf72 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -75,6 +84,37 @@ namespace { +class MozjsExtendedIDLAttributesInterfaceHandler : public ProxyHandler { + public: + MozjsExtendedIDLAttributesInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsExtendedIDLAttributesInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsExtendedIDLAttributesInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsExtendedIDLAttributesInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -111,7 +151,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "ExtendedIDLAttributesInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -126,9 +167,7 @@ JSBool fcn_callWithSettings( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -141,19 +180,19 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + ExtendedIDLAttributesInterface* impl = + wrapper_private->wrappable<ExtendedIDLAttributesInterface>().get(); MozjsGlobalObjectProxy* global_object_proxy = static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context)); - ExtendedIDLAttributesInterface* impl = - WrapperPrivate::GetWrappable<ExtendedIDLAttributesInterface>(object); + impl->CallWithSettings(global_object_proxy->GetEnvironmentSettings()); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -176,6 +215,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -195,7 +238,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -215,8 +259,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "ExtendedIDLAttributesInterface"; - name_value.setString(JS_NewStringCopyZ(context, "ExtendedIDLAttributesInterface")); + const char name[] = + "ExtendedIDLAttributesInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -225,8 +270,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -258,7 +308,7 @@ } // namespace // static -JSObject* MozjsExtendedIDLAttributesInterface::CreateInstance( +JSObject* MozjsExtendedIDLAttributesInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -266,8 +316,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsExtendedIDLAttributesInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.h index de023e6..68909d5 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.h
@@ -38,8 +38,9 @@ class MozjsExtendedIDLAttributesInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.cc index 859f695..fbfc60a 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -74,7 +83,38 @@ namespace testing { namespace { -JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args); + +class MozjsGetOpaqueRootInterfaceHandler : public ProxyHandler { + public: + MozjsGetOpaqueRootInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsGetOpaqueRootInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsGetOpaqueRootInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsGetOpaqueRootInterfaceHandler> + proxy_handler; + +JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp); InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); @@ -112,7 +152,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "GetOpaqueRootInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -139,6 +180,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -158,7 +203,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -178,18 +224,34 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "GetOpaqueRootInterface"; - name_value.setString(JS_NewStringCopyZ(context, "GetOpaqueRootInterface")); + const char name[] = + "GetOpaqueRootInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, JSPROP_READONLY); DCHECK(success); + // Add the InterfaceObject.length property. It is set to the length of the + // shortest argument list of all overload constructors. + JS::RootedValue length_value(context); + length_value.setInt32(0); + success = + JS_DefineProperty(context, rooted_interface_object, "length", + length_value, JS_PropertyStub, JS_StrictPropertyStub, + JSPROP_READONLY); + DCHECK(success); + // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -221,7 +283,7 @@ } // namespace // static -JSObject* MozjsGetOpaqueRootInterface::CreateInstance( +JSObject* MozjsGetOpaqueRootInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -229,8 +291,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsGetOpaqueRootInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static @@ -256,9 +329,17 @@ namespace { -JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args) { - // TODO: Implement support for constructors. - NOTIMPLEMENTED(); +JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp) { + MozjsExceptionState exception_state(context); + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + + scoped_refptr<GetOpaqueRootInterface> new_object = + new GetOpaqueRootInterface(); + JS::RootedValue result_value(context); + ToJSValue(context, new_object, &result_value); + DCHECK(result_value.isObject()); + JS::RootedObject result_object(context, JSVAL_TO_OBJECT(result_value)); + args.rval().setObject(*result_object); return true; } } // namespace
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.h index da38f15..343e465 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.h
@@ -38,8 +38,9 @@ class MozjsGetOpaqueRootInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.cc index a1f623b..27e94db 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -75,6 +84,37 @@ namespace { +class MozjsGlobalInterfaceParentHandler : public ProxyHandler { + public: + MozjsGlobalInterfaceParentHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsGlobalInterfaceParentHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsGlobalInterfaceParentHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsGlobalInterfaceParentHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -111,7 +151,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "GlobalInterfaceParentConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -126,9 +167,7 @@ JSBool fcn_parentOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -141,17 +180,17 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); GlobalInterfaceParent* impl = - WrapperPrivate::GetWrappable<GlobalInterfaceParent>(object); + wrapper_private->wrappable<GlobalInterfaceParent>().get(); + impl->ParentOperation(); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -174,6 +213,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -193,7 +236,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -213,8 +257,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "GlobalInterfaceParent"; - name_value.setString(JS_NewStringCopyZ(context, "GlobalInterfaceParent")); + const char name[] = + "GlobalInterfaceParent"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -223,8 +268,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -256,7 +306,7 @@ } // namespace // static -JSObject* MozjsGlobalInterfaceParent::CreateInstance( +JSObject* MozjsGlobalInterfaceParent::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -264,8 +314,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsGlobalInterfaceParent::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.h index c81bb0a..0ed43cb 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.h
@@ -38,8 +38,9 @@ class MozjsGlobalInterfaceParent { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.cc index 054c19a..e67543f 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -75,6 +84,143 @@ namespace { +bool IsSupportedIndexProperty(JSContext* context, JS::HandleObject object, + uint32_t index) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + IndexedGetterInterface* impl = + wrapper_private->wrappable<IndexedGetterInterface>().get(); + return index < impl->length(); +} + +void EnumerateSupportedIndexes(JSContext* context, JS::HandleObject object, + JS::AutoIdVector* properties) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + IndexedGetterInterface* impl = + wrapper_private->wrappable<IndexedGetterInterface>().get(); + const uint32_t kNumIndexedProperties = impl->length(); + for (uint32_t i = 0; i < kNumIndexedProperties; ++i) { + properties->append(INT_TO_JSID(i)); + } +} + +JSBool GetIndexedProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JS::MutableHandleValue vp) { + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + IndexedGetterInterface* impl = + wrapper_private->wrappable<IndexedGetterInterface>().get(); + uint32_t index; + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, &index); + if(exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->IndexedGetter(index), + &result_value); + } + if (!exception_state.is_exception_set()) { + vp.set(result_value); + } + return !exception_state.is_exception_set(); +} + +JSBool SetIndexedProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JSBool strict, JS::MutableHandleValue vp) { + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + IndexedGetterInterface* impl = + wrapper_private->wrappable<IndexedGetterInterface>().get(); + uint32_t index; + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, &index); + if(exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } + TypeTraits<uint32_t >::ConversionType value; + FromJSValue(context, vp, kNoConversionFlags, + &exception_state, &value); + if (exception_state.is_exception_set()) { + return false; + } + + impl->IndexedSetter(index, value); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +bool DeleteIndexedProperty( + JSContext* context, JS::HandleObject object, uint32_t index) { + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + IndexedGetterInterface* impl = + wrapper_private->wrappable<IndexedGetterInterface>().get(); + + impl->IndexedDeleter(index); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +class MozjsIndexedGetterInterfaceHandler : public ProxyHandler { + public: + MozjsIndexedGetterInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsIndexedGetterInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsIndexedGetterInterfaceHandler::indexed_property_hooks = { + IsSupportedIndexProperty, + EnumerateSupportedIndexes, + GetIndexedProperty, + SetIndexedProperty, + DeleteIndexedProperty, +}; + +static base::LazyInstance<MozjsIndexedGetterInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -111,7 +257,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "IndexedGetterInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -129,25 +276,26 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - IndexedGetterInterface* impl = - WrapperPrivate::GetWrappable<IndexedGetterInterface>(object); - TypeTraits<uint32_t >::ReturnType value = - impl->length(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + IndexedGetterInterface* impl = + wrapper_private->wrappable<IndexedGetterInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->length(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } -JSBool fcn_indexedGetter( +JSBool fcn_indexedDeleter( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -160,40 +308,41 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + IndexedGetterInterface* impl = + wrapper_private->wrappable<IndexedGetterInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<uint32_t >::ConversionType index; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &index); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &index); + if (exception_state.is_exception_set()) { return false; } - IndexedGetterInterface* impl = - WrapperPrivate::GetWrappable<IndexedGetterInterface>(object); - TypeTraits<uint32_t >::ReturnType value = - impl->IndexedGetter(index); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + impl->IndexedDeleter(index); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); } -JSBool fcn_indexedSetter( +JSBool fcn_indexedGetter( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -206,37 +355,101 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + IndexedGetterInterface* impl = + wrapper_private->wrappable<IndexedGetterInterface>().get(); + const size_t kMinArguments = 1; + if (args.length() < kMinArguments) { + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Not enough arguments."); + return false; + } + // Non-optional arguments + TypeTraits<uint32_t >::ConversionType index; + + DCHECK_LT(0, args.length()); + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &index); + if (exception_state.is_exception_set()) { + return false; + } + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->IndexedGetter(index), + &result_value); + } + if (!exception_state.is_exception_set()) { + args.rval().set(result_value); + } + return !exception_state.is_exception_set(); +} + +JSBool fcn_indexedSetter( + JSContext* context, uint32_t argc, JS::Value *vp) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + // Compute the 'this' value. + JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); + // 'this' should be an object. + JS::RootedObject object(context); + if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) { + NOTREACHED(); + return false; + } + if (!JS_ValueToObject(context, this_value, object.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + IndexedGetterInterface* impl = + wrapper_private->wrappable<IndexedGetterInterface>().get(); const size_t kMinArguments = 2; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<uint32_t >::ConversionType index; - DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &index); - if (exception_state.IsExceptionSet()) { - return false; - } TypeTraits<uint32_t >::ConversionType value; - DCHECK_LT(1, args.length()); - FromJSValue(context, args.handleAt(1), - kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + + DCHECK_LT(0, args.length()); + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &index); + if (exception_state.is_exception_set()) { return false; } - IndexedGetterInterface* impl = - WrapperPrivate::GetWrappable<IndexedGetterInterface>(object); + + DCHECK_LT(1, args.length()); + JS::RootedValue non_optional_value1( + context, args[1]); + FromJSValue(context, + non_optional_value1, + kNoConversionFlags, + &exception_state, &value); + if (exception_state.is_exception_set()) { + return false; + } + impl->IndexedSetter(index, value); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -252,6 +465,13 @@ const JSFunctionSpec prototype_functions[] = { { + "indexedDeleter", + JSOP_WRAPPER(&fcn_indexedDeleter), + 1, + JSPROP_ENUMERATE, + NULL, + }, + { "indexedGetter", JSOP_WRAPPER(&fcn_indexedGetter), 1, @@ -272,6 +492,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -291,7 +515,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -311,8 +536,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "IndexedGetterInterface"; - name_value.setString(JS_NewStringCopyZ(context, "IndexedGetterInterface")); + const char name[] = + "IndexedGetterInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -321,8 +547,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -354,7 +585,7 @@ } // namespace // static -JSObject* MozjsIndexedGetterInterface::CreateInstance( +JSObject* MozjsIndexedGetterInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -362,8 +593,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsIndexedGetterInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.h index 3b2300b..a61619c 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.h
@@ -38,8 +38,9 @@ class MozjsIndexedGetterInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.cc index 274bea7..5831dae 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -75,6 +84,37 @@ namespace { +class MozjsInterfaceWithUnsupportedPropertiesHandler : public ProxyHandler { + public: + MozjsInterfaceWithUnsupportedPropertiesHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsInterfaceWithUnsupportedPropertiesHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsInterfaceWithUnsupportedPropertiesHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsInterfaceWithUnsupportedPropertiesHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -111,7 +151,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "InterfaceWithUnsupportedPropertiesConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -129,18 +170,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - InterfaceWithUnsupportedProperties* impl = - WrapperPrivate::GetWrappable<InterfaceWithUnsupportedProperties>(object); - TypeTraits<int32_t >::ReturnType value = - impl->supported_attribute(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + InterfaceWithUnsupportedProperties* impl = + wrapper_private->wrappable<InterfaceWithUnsupportedProperties>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->supported_attribute(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -162,6 +206,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -181,7 +229,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -201,8 +250,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "InterfaceWithUnsupportedProperties"; - name_value.setString(JS_NewStringCopyZ(context, "InterfaceWithUnsupportedProperties")); + const char name[] = + "InterfaceWithUnsupportedProperties"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -211,8 +261,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -244,7 +299,7 @@ } // namespace // static -JSObject* MozjsInterfaceWithUnsupportedProperties::CreateInstance( +JSObject* MozjsInterfaceWithUnsupportedProperties::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -252,8 +307,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsInterfaceWithUnsupportedProperties::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.h index 06a8adb..417e204 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.h
@@ -38,8 +38,9 @@ class MozjsInterfaceWithUnsupportedProperties { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.cc index 284f86b..f0a1359 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -74,7 +83,38 @@ namespace testing { namespace { -JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args); + +class MozjsNamedConstructorInterfaceHandler : public ProxyHandler { + public: + MozjsNamedConstructorInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsNamedConstructorInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsNamedConstructorInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsNamedConstructorInterfaceHandler> + proxy_handler; + +JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp); InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); @@ -112,7 +152,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "NamedConstructorInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -139,6 +180,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -158,7 +203,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -178,18 +224,34 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "SomeNamedConstructor"; - name_value.setString(JS_NewStringCopyZ(context, "NamedConstructorInterface")); + const char name[] = + "SomeNamedConstructor"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, JSPROP_READONLY); DCHECK(success); + // Add the InterfaceObject.length property. It is set to the length of the + // shortest argument list of all overload constructors. + JS::RootedValue length_value(context); + length_value.setInt32(0); + success = + JS_DefineProperty(context, rooted_interface_object, "length", + length_value, JS_PropertyStub, JS_StrictPropertyStub, + JSPROP_READONLY); + DCHECK(success); + // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -221,7 +283,7 @@ } // namespace // static -JSObject* MozjsNamedConstructorInterface::CreateInstance( +JSObject* MozjsNamedConstructorInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -229,8 +291,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsNamedConstructorInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static @@ -256,9 +329,17 @@ namespace { -JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args) { - // TODO: Implement support for constructors. - NOTIMPLEMENTED(); +JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp) { + MozjsExceptionState exception_state(context); + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + + scoped_refptr<NamedConstructorInterface> new_object = + new NamedConstructorInterface(); + JS::RootedValue result_value(context); + ToJSValue(context, new_object, &result_value); + DCHECK(result_value.isObject()); + JS::RootedObject result_object(context, JSVAL_TO_OBJECT(result_value)); + args.rval().setObject(*result_object); return true; } } // namespace
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.h index 297534c..670e6fc 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.h
@@ -38,8 +38,9 @@ class MozjsNamedConstructorInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.cc index 4c4bf01..d9debc4 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -75,6 +84,143 @@ namespace { +bool IsSupportedNamedProperty(JSContext* context, JS::HandleObject object, + const std::string& property_name) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NamedGetterInterface* impl = + wrapper_private->wrappable<NamedGetterInterface>().get(); + return impl->CanQueryNamedProperty(property_name); +} + +void EnumerateSupportedNames(JSContext* context, JS::HandleObject object, + JS::AutoIdVector* properties) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NamedGetterInterface* impl = + wrapper_private->wrappable<NamedGetterInterface>().get(); + MozjsPropertyEnumerator enumerator(context, properties); + impl->EnumerateNamedProperties(&enumerator); +} + +JSBool GetNamedProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JS::MutableHandleValue vp) { + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NamedGetterInterface* impl = + wrapper_private->wrappable<NamedGetterInterface>().get(); + std::string property_name; + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, + &property_name); + if(exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->NamedGetter(property_name), + &result_value); + } + if (!exception_state.is_exception_set()) { + vp.set(result_value); + } + return !exception_state.is_exception_set(); +} + +JSBool SetNamedProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JSBool strict, JS::MutableHandleValue vp) { + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NamedGetterInterface* impl = + wrapper_private->wrappable<NamedGetterInterface>().get(); + std::string property_name; + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, + &property_name); + if(exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } + TypeTraits<std::string >::ConversionType value; + FromJSValue(context, vp, kNoConversionFlags, + &exception_state, &value); + if (exception_state.is_exception_set()) { + return false; + } + + impl->NamedSetter(property_name, value); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +bool DeleteNamedProperty(JSContext* context, JS::HandleObject object, + const std::string& property_name) { + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NamedGetterInterface* impl = + wrapper_private->wrappable<NamedGetterInterface>().get(); + + impl->NamedDeleter(property_name); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +class MozjsNamedGetterInterfaceHandler : public ProxyHandler { + public: + MozjsNamedGetterInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsNamedGetterInterfaceHandler::named_property_hooks = { + IsSupportedNamedProperty, + EnumerateSupportedNames, + GetNamedProperty, + SetNamedProperty, + DeleteNamedProperty, +}; +ProxyHandler::IndexedPropertyHooks +MozjsNamedGetterInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsNamedGetterInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -111,7 +257,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "NamedGetterInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -126,9 +273,7 @@ JSBool fcn_namedDeleter( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -141,37 +286,41 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NamedGetterInterface* impl = + wrapper_private->wrappable<NamedGetterInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<std::string >::ConversionType name; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &name); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &name); + if (exception_state.is_exception_set()) { return false; } - NamedGetterInterface* impl = - WrapperPrivate::GetWrappable<NamedGetterInterface>(object); + impl->NamedDeleter(name); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_namedGetter( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -184,40 +333,47 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NamedGetterInterface* impl = + wrapper_private->wrappable<NamedGetterInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<std::string >::ConversionType name; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &name); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &name); + if (exception_state.is_exception_set()) { return false; } - NamedGetterInterface* impl = - WrapperPrivate::GetWrappable<NamedGetterInterface>(object); - TypeTraits<std::string >::ReturnType value = - impl->NamedGetter(name); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->NamedGetter(name), + &result_value); + } + if (!exception_state.is_exception_set()) { args.rval().set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_namedSetter( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -230,37 +386,48 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NamedGetterInterface* impl = + wrapper_private->wrappable<NamedGetterInterface>().get(); const size_t kMinArguments = 2; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<std::string >::ConversionType name; - DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &name); - if (exception_state.IsExceptionSet()) { - return false; - } TypeTraits<std::string >::ConversionType value; - DCHECK_LT(1, args.length()); - FromJSValue(context, args.handleAt(1), - kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + + DCHECK_LT(0, args.length()); + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &name); + if (exception_state.is_exception_set()) { return false; } - NamedGetterInterface* impl = - WrapperPrivate::GetWrappable<NamedGetterInterface>(object); + + DCHECK_LT(1, args.length()); + JS::RootedValue non_optional_value1( + context, args[1]); + FromJSValue(context, + non_optional_value1, + kNoConversionFlags, + &exception_state, &value); + if (exception_state.is_exception_set()) { + return false; + } + impl->NamedSetter(name, value); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -297,6 +464,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -316,7 +487,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -336,8 +508,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "NamedGetterInterface"; - name_value.setString(JS_NewStringCopyZ(context, "NamedGetterInterface")); + const char name[] = + "NamedGetterInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -346,8 +519,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -379,7 +557,7 @@ } // namespace // static -JSObject* MozjsNamedGetterInterface::CreateInstance( +JSObject* MozjsNamedGetterInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -387,8 +565,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsNamedGetterInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.h index cd2035f..613c1b9 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.h
@@ -38,8 +38,9 @@ class MozjsNamedGetterInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc index f8d0d7b..e63ec48 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -75,6 +84,219 @@ namespace { +bool IsSupportedNamedProperty(JSContext* context, JS::HandleObject object, + const std::string& property_name) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NamedIndexedGetterInterface* impl = + wrapper_private->wrappable<NamedIndexedGetterInterface>().get(); + return impl->CanQueryNamedProperty(property_name); +} + +void EnumerateSupportedNames(JSContext* context, JS::HandleObject object, + JS::AutoIdVector* properties) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NamedIndexedGetterInterface* impl = + wrapper_private->wrappable<NamedIndexedGetterInterface>().get(); + MozjsPropertyEnumerator enumerator(context, properties); + impl->EnumerateNamedProperties(&enumerator); +} + +JSBool GetNamedProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JS::MutableHandleValue vp) { + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NamedIndexedGetterInterface* impl = + wrapper_private->wrappable<NamedIndexedGetterInterface>().get(); + std::string property_name; + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, + &property_name); + if(exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->NamedGetter(property_name), + &result_value); + } + if (!exception_state.is_exception_set()) { + vp.set(result_value); + } + return !exception_state.is_exception_set(); +} + +JSBool SetNamedProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JSBool strict, JS::MutableHandleValue vp) { + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NamedIndexedGetterInterface* impl = + wrapper_private->wrappable<NamedIndexedGetterInterface>().get(); + std::string property_name; + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, + &property_name); + if(exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } + TypeTraits<std::string >::ConversionType value; + FromJSValue(context, vp, kNoConversionFlags, + &exception_state, &value); + if (exception_state.is_exception_set()) { + return false; + } + + impl->NamedSetter(property_name, value); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +bool IsSupportedIndexProperty(JSContext* context, JS::HandleObject object, + uint32_t index) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NamedIndexedGetterInterface* impl = + wrapper_private->wrappable<NamedIndexedGetterInterface>().get(); + return index < impl->length(); +} + +void EnumerateSupportedIndexes(JSContext* context, JS::HandleObject object, + JS::AutoIdVector* properties) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NamedIndexedGetterInterface* impl = + wrapper_private->wrappable<NamedIndexedGetterInterface>().get(); + const uint32_t kNumIndexedProperties = impl->length(); + for (uint32_t i = 0; i < kNumIndexedProperties; ++i) { + properties->append(INT_TO_JSID(i)); + } +} + +JSBool GetIndexedProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JS::MutableHandleValue vp) { + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NamedIndexedGetterInterface* impl = + wrapper_private->wrappable<NamedIndexedGetterInterface>().get(); + uint32_t index; + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, &index); + if(exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->IndexedGetter(index), + &result_value); + } + if (!exception_state.is_exception_set()) { + vp.set(result_value); + } + return !exception_state.is_exception_set(); +} + +JSBool SetIndexedProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JSBool strict, JS::MutableHandleValue vp) { + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NamedIndexedGetterInterface* impl = + wrapper_private->wrappable<NamedIndexedGetterInterface>().get(); + uint32_t index; + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, &index); + if(exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } + TypeTraits<uint32_t >::ConversionType value; + FromJSValue(context, vp, kNoConversionFlags, + &exception_state, &value); + if (exception_state.is_exception_set()) { + return false; + } + + impl->IndexedSetter(index, value); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +class MozjsNamedIndexedGetterInterfaceHandler : public ProxyHandler { + public: + MozjsNamedIndexedGetterInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsNamedIndexedGetterInterfaceHandler::named_property_hooks = { + IsSupportedNamedProperty, + EnumerateSupportedNames, + GetNamedProperty, + SetNamedProperty, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsNamedIndexedGetterInterfaceHandler::indexed_property_hooks = { + IsSupportedIndexProperty, + EnumerateSupportedIndexes, + GetIndexedProperty, + SetIndexedProperty, + NULL, +}; + +static base::LazyInstance<MozjsNamedIndexedGetterInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -111,7 +333,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "NamedIndexedGetterInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -129,18 +352,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - NamedIndexedGetterInterface* impl = - WrapperPrivate::GetWrappable<NamedIndexedGetterInterface>(object); - TypeTraits<uint32_t >::ReturnType value = - impl->length(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NamedIndexedGetterInterface* impl = + wrapper_private->wrappable<NamedIndexedGetterInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->length(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool get_propertyOnBaseClass( @@ -148,18 +374,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - NamedIndexedGetterInterface* impl = - WrapperPrivate::GetWrappable<NamedIndexedGetterInterface>(object); - TypeTraits<bool >::ReturnType value = - impl->property_on_base_class(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NamedIndexedGetterInterface* impl = + wrapper_private->wrappable<NamedIndexedGetterInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->property_on_base_class(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_propertyOnBaseClass( @@ -167,25 +396,26 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NamedIndexedGetterInterface* impl = + wrapper_private->wrappable<NamedIndexedGetterInterface>().get(); TypeTraits<bool >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - NamedIndexedGetterInterface* impl = - WrapperPrivate::GetWrappable<NamedIndexedGetterInterface>(object); + impl->set_property_on_base_class(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_indexedGetter( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -198,40 +428,47 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NamedIndexedGetterInterface* impl = + wrapper_private->wrappable<NamedIndexedGetterInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<uint32_t >::ConversionType index; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &index); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &index); + if (exception_state.is_exception_set()) { return false; } - NamedIndexedGetterInterface* impl = - WrapperPrivate::GetWrappable<NamedIndexedGetterInterface>(object); - TypeTraits<uint32_t >::ReturnType value = - impl->IndexedGetter(index); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->IndexedGetter(index), + &result_value); + } + if (!exception_state.is_exception_set()) { args.rval().set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_indexedSetter( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -244,44 +481,53 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NamedIndexedGetterInterface* impl = + wrapper_private->wrappable<NamedIndexedGetterInterface>().get(); const size_t kMinArguments = 2; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<uint32_t >::ConversionType index; - DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &index); - if (exception_state.IsExceptionSet()) { - return false; - } TypeTraits<uint32_t >::ConversionType value; - DCHECK_LT(1, args.length()); - FromJSValue(context, args.handleAt(1), - kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + + DCHECK_LT(0, args.length()); + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &index); + if (exception_state.is_exception_set()) { return false; } - NamedIndexedGetterInterface* impl = - WrapperPrivate::GetWrappable<NamedIndexedGetterInterface>(object); + + DCHECK_LT(1, args.length()); + JS::RootedValue non_optional_value1( + context, args[1]); + FromJSValue(context, + non_optional_value1, + kNoConversionFlags, + &exception_state, &value); + if (exception_state.is_exception_set()) { + return false; + } + impl->IndexedSetter(index, value); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_namedGetter( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -294,40 +540,47 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NamedIndexedGetterInterface* impl = + wrapper_private->wrappable<NamedIndexedGetterInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<std::string >::ConversionType name; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &name); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &name); + if (exception_state.is_exception_set()) { return false; } - NamedIndexedGetterInterface* impl = - WrapperPrivate::GetWrappable<NamedIndexedGetterInterface>(object); - TypeTraits<std::string >::ReturnType value = - impl->NamedGetter(name); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->NamedGetter(name), + &result_value); + } + if (!exception_state.is_exception_set()) { args.rval().set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_namedSetter( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -340,44 +593,53 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NamedIndexedGetterInterface* impl = + wrapper_private->wrappable<NamedIndexedGetterInterface>().get(); const size_t kMinArguments = 2; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<std::string >::ConversionType name; - DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &name); - if (exception_state.IsExceptionSet()) { - return false; - } TypeTraits<std::string >::ConversionType value; - DCHECK_LT(1, args.length()); - FromJSValue(context, args.handleAt(1), - kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + + DCHECK_LT(0, args.length()); + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &name); + if (exception_state.is_exception_set()) { return false; } - NamedIndexedGetterInterface* impl = - WrapperPrivate::GetWrappable<NamedIndexedGetterInterface>(object); + + DCHECK_LT(1, args.length()); + JS::RootedValue non_optional_value1( + context, args[1]); + FromJSValue(context, + non_optional_value1, + kNoConversionFlags, + &exception_state, &value); + if (exception_state.is_exception_set()) { + return false; + } + impl->NamedSetter(name, value); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_operationOnBaseClass( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -390,17 +652,17 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); NamedIndexedGetterInterface* impl = - WrapperPrivate::GetWrappable<NamedIndexedGetterInterface>(object); + wrapper_private->wrappable<NamedIndexedGetterInterface>().get(); + impl->OperationOnBaseClass(); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -463,6 +725,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -482,7 +748,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -502,8 +769,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "NamedIndexedGetterInterface"; - name_value.setString(JS_NewStringCopyZ(context, "NamedIndexedGetterInterface")); + const char name[] = + "NamedIndexedGetterInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -512,8 +780,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -545,7 +818,7 @@ } // namespace // static -JSObject* MozjsNamedIndexedGetterInterface::CreateInstance( +JSObject* MozjsNamedIndexedGetterInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -553,8 +826,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsNamedIndexedGetterInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.h index b0a15cc..d0cc78a 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.h
@@ -38,8 +38,9 @@ class MozjsNamedIndexedGetterInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.cc index 43a0e5c..e665fea 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.cc
@@ -30,14 +30,20 @@ #include "cobalt/bindings/testing/put_forwards_interface.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -55,6 +61,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -65,7 +72,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -79,6 +88,37 @@ namespace { +class MozjsNestedPutForwardsInterfaceHandler : public ProxyHandler { + public: + MozjsNestedPutForwardsInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsNestedPutForwardsInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsNestedPutForwardsInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsNestedPutForwardsInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -115,7 +155,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "NestedPutForwardsInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -133,18 +174,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - NestedPutForwardsInterface* impl = - WrapperPrivate::GetWrappable<NestedPutForwardsInterface>(object); - TypeTraits<scoped_refptr<PutForwardsInterface> >::ReturnType value = - impl->nested_forwarding_attribute(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NestedPutForwardsInterface* impl = + wrapper_private->wrappable<NestedPutForwardsInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->nested_forwarding_attribute(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_nestedForwardingAttribute( @@ -152,14 +196,43 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - TypeTraits<scoped_refptr<PutForwardsInterface> >::ConversionType value; + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NestedPutForwardsInterface* impl = + wrapper_private->wrappable<NestedPutForwardsInterface>().get(); + { // Begin scope of scoped_refptr<PutForwardsInterface> forwarded_impl. + scoped_refptr<PutForwardsInterface> forwarded_impl = + impl->nested_forwarding_attribute(); + if (!forwarded_impl) { + NOTREACHED(); + return false; + } + if (!exception_state.is_exception_set()) { + { // Begin scope of scoped_refptr<ArbitraryInterface> forwarded_forwarded_impl. + scoped_refptr<ArbitraryInterface> forwarded_forwarded_impl = + forwarded_impl->forwarding_attribute(); + if (!forwarded_forwarded_impl) { + NOTREACHED(); + return false; + } + if (!exception_state.is_exception_set()) { + TypeTraits<std::string >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - NOTIMPLEMENTED(); - return !exception_state.IsExceptionSet(); + + forwarded_forwarded_impl->set_arbitrary_property(value); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + return !exception_state.is_exception_set(); + } // End scope of scoped_refptr<ArbitraryInterface> forwarded_forwarded_impl. +} + return !exception_state.is_exception_set(); + } // End scope of scoped_refptr<PutForwardsInterface> forwarded_impl. } @@ -181,6 +254,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -200,7 +277,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -220,8 +298,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "NestedPutForwardsInterface"; - name_value.setString(JS_NewStringCopyZ(context, "NestedPutForwardsInterface")); + const char name[] = + "NestedPutForwardsInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -230,8 +309,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -263,7 +347,7 @@ } // namespace // static -JSObject* MozjsNestedPutForwardsInterface::CreateInstance( +JSObject* MozjsNestedPutForwardsInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -271,8 +355,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsNestedPutForwardsInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.h index 899b2b9..47b1965 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.h
@@ -38,8 +38,9 @@ class MozjsNestedPutForwardsInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.cc index fa03c71..ecf9e98 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -75,6 +84,37 @@ namespace { +class MozjsNoConstructorInterfaceHandler : public ProxyHandler { + public: + MozjsNoConstructorInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsNoConstructorInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsNoConstructorInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsNoConstructorInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -111,7 +151,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "NoConstructorInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -137,6 +178,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -156,7 +201,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -176,8 +222,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "NoConstructorInterface"; - name_value.setString(JS_NewStringCopyZ(context, "NoConstructorInterface")); + const char name[] = + "NoConstructorInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -186,8 +233,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -219,7 +271,7 @@ } // namespace // static -JSObject* MozjsNoConstructorInterface::CreateInstance( +JSObject* MozjsNoConstructorInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -227,8 +279,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsNoConstructorInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.h index a7da004..1c2a1c8 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.h
@@ -38,8 +38,9 @@ class MozjsNoConstructorInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.cc index 780ecb1..27d50a2 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -75,6 +84,37 @@ namespace { +class MozjsNoInterfaceObjectInterfaceHandler : public ProxyHandler { + public: + MozjsNoInterfaceObjectInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsNoInterfaceObjectInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsNoInterfaceObjectInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsNoInterfaceObjectInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -111,7 +151,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "NoInterfaceObjectInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -137,6 +178,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -156,7 +201,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -185,7 +231,7 @@ } // namespace // static -JSObject* MozjsNoInterfaceObjectInterface::CreateInstance( +JSObject* MozjsNoInterfaceObjectInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -193,8 +239,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsNoInterfaceObjectInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.h index c44bc47..8d5c0f1 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.h
@@ -38,8 +38,9 @@ class MozjsNoInterfaceObjectInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.cc index 95629dc..3176045 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.cc
@@ -30,14 +30,20 @@ #include "cobalt/bindings/testing/arbitrary_interface.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -55,6 +61,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -65,7 +72,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -79,6 +88,37 @@ namespace { +class MozjsNullableTypesTestInterfaceHandler : public ProxyHandler { + public: + MozjsNullableTypesTestInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsNullableTypesTestInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsNullableTypesTestInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsNullableTypesTestInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -115,7 +155,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "NullableTypesTestInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -133,18 +174,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - NullableTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object); - TypeTraits<base::optional<bool > >::ReturnType value = - impl->nullable_boolean_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NullableTypesTestInterface* impl = + wrapper_private->wrappable<NullableTypesTestInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->nullable_boolean_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_nullableBooleanProperty( @@ -152,18 +196,21 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NullableTypesTestInterface* impl = + wrapper_private->wrappable<NullableTypesTestInterface>().get(); TypeTraits<base::optional<bool > >::ConversionType value; FromJSValue(context, vp, (kConversionFlagNullable), &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - NullableTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object); + impl->set_nullable_boolean_property(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool get_nullableNumericProperty( @@ -171,18 +218,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - NullableTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object); - TypeTraits<base::optional<int32_t > >::ReturnType value = - impl->nullable_numeric_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NullableTypesTestInterface* impl = + wrapper_private->wrappable<NullableTypesTestInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->nullable_numeric_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_nullableNumericProperty( @@ -190,18 +240,21 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NullableTypesTestInterface* impl = + wrapper_private->wrappable<NullableTypesTestInterface>().get(); TypeTraits<base::optional<int32_t > >::ConversionType value; FromJSValue(context, vp, (kConversionFlagNullable), &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - NullableTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object); + impl->set_nullable_numeric_property(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool get_nullableStringProperty( @@ -209,18 +262,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - NullableTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object); - TypeTraits<base::optional<std::string > >::ReturnType value = - impl->nullable_string_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NullableTypesTestInterface* impl = + wrapper_private->wrappable<NullableTypesTestInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->nullable_string_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_nullableStringProperty( @@ -228,18 +284,21 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NullableTypesTestInterface* impl = + wrapper_private->wrappable<NullableTypesTestInterface>().get(); TypeTraits<base::optional<std::string > >::ConversionType value; FromJSValue(context, vp, (kConversionFlagNullable), &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - NullableTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object); + impl->set_nullable_string_property(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool get_nullableObjectProperty( @@ -247,18 +306,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - NullableTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object); - TypeTraits<scoped_refptr<ArbitraryInterface> >::ReturnType value = - impl->nullable_object_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NullableTypesTestInterface* impl = + wrapper_private->wrappable<NullableTypesTestInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->nullable_object_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_nullableObjectProperty( @@ -266,25 +328,26 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NullableTypesTestInterface* impl = + wrapper_private->wrappable<NullableTypesTestInterface>().get(); TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType value; FromJSValue(context, vp, (kConversionFlagNullable), &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - NullableTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object); + impl->set_nullable_object_property(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_nullableBooleanArgument( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -297,37 +360,41 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NullableTypesTestInterface* impl = + wrapper_private->wrappable<NullableTypesTestInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<base::optional<bool > >::ConversionType arg; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - (kConversionFlagNullable), &exception_state, &arg); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + (kConversionFlagNullable), + &exception_state, &arg); + if (exception_state.is_exception_set()) { return false; } - NullableTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object); + impl->NullableBooleanArgument(arg); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_nullableBooleanOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -340,27 +407,28 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); NullableTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object); - TypeTraits<base::optional<bool > >::ReturnType value = - impl->NullableBooleanOperation(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } + wrapper_private->wrappable<NullableTypesTestInterface>().get(); - if (!exception_state.IsExceptionSet()) { + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->NullableBooleanOperation(), + &result_value); + } + if (!exception_state.is_exception_set()) { args.rval().set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_nullableNumericArgument( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -373,37 +441,41 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NullableTypesTestInterface* impl = + wrapper_private->wrappable<NullableTypesTestInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<base::optional<int32_t > >::ConversionType arg; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - (kConversionFlagNullable), &exception_state, &arg); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + (kConversionFlagNullable), + &exception_state, &arg); + if (exception_state.is_exception_set()) { return false; } - NullableTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object); + impl->NullableNumericArgument(arg); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_nullableNumericOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -416,27 +488,28 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); NullableTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object); - TypeTraits<base::optional<int32_t > >::ReturnType value = - impl->NullableNumericOperation(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } + wrapper_private->wrappable<NullableTypesTestInterface>().get(); - if (!exception_state.IsExceptionSet()) { + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->NullableNumericOperation(), + &result_value); + } + if (!exception_state.is_exception_set()) { args.rval().set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_nullableObjectArgument( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -449,37 +522,41 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NullableTypesTestInterface* impl = + wrapper_private->wrappable<NullableTypesTestInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType arg; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - (kConversionFlagNullable), &exception_state, &arg); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + (kConversionFlagNullable), + &exception_state, &arg); + if (exception_state.is_exception_set()) { return false; } - NullableTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object); + impl->NullableObjectArgument(arg); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_nullableObjectOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -492,27 +569,28 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); NullableTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object); - TypeTraits<scoped_refptr<ArbitraryInterface> >::ReturnType value = - impl->NullableObjectOperation(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } + wrapper_private->wrappable<NullableTypesTestInterface>().get(); - if (!exception_state.IsExceptionSet()) { + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->NullableObjectOperation(), + &result_value); + } + if (!exception_state.is_exception_set()) { args.rval().set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_nullableStringArgument( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -525,37 +603,41 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NullableTypesTestInterface* impl = + wrapper_private->wrappable<NullableTypesTestInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<base::optional<std::string > >::ConversionType arg; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - (kConversionFlagNullable), &exception_state, &arg); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + (kConversionFlagNullable), + &exception_state, &arg); + if (exception_state.is_exception_set()) { return false; } - NullableTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object); + impl->NullableStringArgument(arg); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_nullableStringOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -568,20 +650,23 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); NullableTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object); - TypeTraits<base::optional<std::string > >::ReturnType value = - impl->NullableStringOperation(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } + wrapper_private->wrappable<NullableTypesTestInterface>().get(); - if (!exception_state.IsExceptionSet()) { + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->NullableStringOperation(), + &result_value); + } + if (!exception_state.is_exception_set()) { args.rval().set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -677,6 +762,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -696,7 +785,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -716,8 +806,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "NullableTypesTestInterface"; - name_value.setString(JS_NewStringCopyZ(context, "NullableTypesTestInterface")); + const char name[] = + "NullableTypesTestInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -726,8 +817,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -759,7 +855,7 @@ } // namespace // static -JSObject* MozjsNullableTypesTestInterface::CreateInstance( +JSObject* MozjsNullableTypesTestInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -767,8 +863,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsNullableTypesTestInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.h index 95895b7..69bfddd 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.h
@@ -38,8 +38,9 @@ class MozjsNullableTypesTestInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.cc index ce72076..bfa31b4 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -75,6 +84,37 @@ namespace { +class MozjsNumericTypesTestInterfaceHandler : public ProxyHandler { + public: + MozjsNumericTypesTestInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsNumericTypesTestInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsNumericTypesTestInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsNumericTypesTestInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -111,7 +151,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "NumericTypesTestInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -129,18 +170,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); - TypeTraits<int8_t >::ReturnType value = - impl->byte_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->byte_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_byteProperty( @@ -148,18 +192,21 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); TypeTraits<int8_t >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); + impl->set_byte_property(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool get_octetProperty( @@ -167,18 +214,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); - TypeTraits<uint8_t >::ReturnType value = - impl->octet_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->octet_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_octetProperty( @@ -186,18 +236,21 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); TypeTraits<uint8_t >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); + impl->set_octet_property(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool get_shortProperty( @@ -205,18 +258,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); - TypeTraits<int16_t >::ReturnType value = - impl->short_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->short_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_shortProperty( @@ -224,18 +280,21 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); TypeTraits<int16_t >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); + impl->set_short_property(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool get_unsignedShortProperty( @@ -243,18 +302,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); - TypeTraits<uint16_t >::ReturnType value = - impl->unsigned_short_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->unsigned_short_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_unsignedShortProperty( @@ -262,18 +324,21 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); TypeTraits<uint16_t >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); + impl->set_unsigned_short_property(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool get_longProperty( @@ -281,18 +346,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); - TypeTraits<int32_t >::ReturnType value = - impl->long_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->long_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_longProperty( @@ -300,18 +368,21 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); TypeTraits<int32_t >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); + impl->set_long_property(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool get_unsignedLongProperty( @@ -319,18 +390,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); - TypeTraits<uint32_t >::ReturnType value = - impl->unsigned_long_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->unsigned_long_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_unsignedLongProperty( @@ -338,18 +412,109 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); TypeTraits<uint32_t >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); + impl->set_unsigned_long_property(value); result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} - return !exception_state.IsExceptionSet(); +JSBool get_longLongProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JS::MutableHandleValue vp) { + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->long_long_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { + vp.set(result_value); + } + return !exception_state.is_exception_set(); +} + +JSBool set_longLongProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JSBool strict, JS::MutableHandleValue vp) { + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); + TypeTraits<int64_t >::ConversionType value; + FromJSValue(context, vp, kNoConversionFlags, &exception_state, + &value); + if (exception_state.is_exception_set()) { + return false; + } + + impl->set_long_long_property(value); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +JSBool get_unsignedLongLongProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JS::MutableHandleValue vp) { + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->unsigned_long_long_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { + vp.set(result_value); + } + return !exception_state.is_exception_set(); +} + +JSBool set_unsignedLongLongProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JSBool strict, JS::MutableHandleValue vp) { + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); + TypeTraits<uint64_t >::ConversionType value; + FromJSValue(context, vp, kNoConversionFlags, &exception_state, + &value); + if (exception_state.is_exception_set()) { + return false; + } + + impl->set_unsigned_long_long_property(value); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); } JSBool get_doubleProperty( @@ -357,18 +522,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); - TypeTraits<double >::ReturnType value = - impl->double_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->double_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_doubleProperty( @@ -376,18 +544,21 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); TypeTraits<double >::ConversionType value; FromJSValue(context, vp, (kConversionFlagRestricted), &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); + impl->set_double_property(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool get_unrestrictedDoubleProperty( @@ -395,18 +566,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); - TypeTraits<double >::ReturnType value = - impl->unrestricted_double_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->unrestricted_double_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_unrestrictedDoubleProperty( @@ -414,25 +588,26 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); TypeTraits<double >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); + impl->set_unrestricted_double_property(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_byteArgumentOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -445,37 +620,41 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<int8_t >::ConversionType arg1; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &arg1); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg1); + if (exception_state.is_exception_set()) { return false; } - NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); + impl->ByteArgumentOperation(arg1); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_byteReturnOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -488,27 +667,28 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); - TypeTraits<int8_t >::ReturnType value = - impl->ByteReturnOperation(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } + wrapper_private->wrappable<NumericTypesTestInterface>().get(); - if (!exception_state.IsExceptionSet()) { + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->ByteReturnOperation(), + &result_value); + } + if (!exception_state.is_exception_set()) { args.rval().set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_doubleArgumentOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -521,37 +701,41 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<double >::ConversionType arg1; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - (kConversionFlagRestricted), &exception_state, &arg1); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + (kConversionFlagRestricted), + &exception_state, &arg1); + if (exception_state.is_exception_set()) { return false; } - NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); + impl->DoubleArgumentOperation(arg1); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_doubleReturnOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -564,27 +748,28 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); - TypeTraits<double >::ReturnType value = - impl->DoubleReturnOperation(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } + wrapper_private->wrappable<NumericTypesTestInterface>().get(); - if (!exception_state.IsExceptionSet()) { + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->DoubleReturnOperation(), + &result_value); + } + if (!exception_state.is_exception_set()) { args.rval().set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_longArgumentOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -597,37 +782,122 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<int32_t >::ConversionType arg1; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &arg1); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg1); + if (exception_state.is_exception_set()) { return false; } - NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); + impl->LongArgumentOperation(arg1); result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} - if (!exception_state.IsExceptionSet()) { +JSBool fcn_longLongArgumentOperation( + JSContext* context, uint32_t argc, JS::Value *vp) { + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + // Compute the 'this' value. + JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); + // 'this' should be an object. + JS::RootedObject object(context); + if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) { + NOTREACHED(); + return false; + } + if (!JS_ValueToObject(context, this_value, object.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); + const size_t kMinArguments = 1; + if (args.length() < kMinArguments) { + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Not enough arguments."); + return false; + } + // Non-optional arguments + TypeTraits<int64_t >::ConversionType arg1; + + DCHECK_LT(0, args.length()); + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg1); + if (exception_state.is_exception_set()) { + return false; + } + + impl->LongLongArgumentOperation(arg1); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +JSBool fcn_longLongReturnOperation( + JSContext* context, uint32_t argc, JS::Value *vp) { + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + // Compute the 'this' value. + JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); + // 'this' should be an object. + JS::RootedObject object(context); + if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) { + NOTREACHED(); + return false; + } + if (!JS_ValueToObject(context, this_value, object.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->LongLongReturnOperation(), + &result_value); + } + if (!exception_state.is_exception_set()) { args.rval().set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_longReturnOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -640,27 +910,28 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); - TypeTraits<int32_t >::ReturnType value = - impl->LongReturnOperation(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } + wrapper_private->wrappable<NumericTypesTestInterface>().get(); - if (!exception_state.IsExceptionSet()) { + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->LongReturnOperation(), + &result_value); + } + if (!exception_state.is_exception_set()) { args.rval().set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_octetArgumentOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -673,37 +944,41 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<uint8_t >::ConversionType arg1; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &arg1); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg1); + if (exception_state.is_exception_set()) { return false; } - NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); + impl->OctetArgumentOperation(arg1); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_octetReturnOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -716,27 +991,28 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); - TypeTraits<uint8_t >::ReturnType value = - impl->OctetReturnOperation(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } + wrapper_private->wrappable<NumericTypesTestInterface>().get(); - if (!exception_state.IsExceptionSet()) { + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->OctetReturnOperation(), + &result_value); + } + if (!exception_state.is_exception_set()) { args.rval().set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_shortArgumentOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -749,37 +1025,41 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<int16_t >::ConversionType arg1; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &arg1); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg1); + if (exception_state.is_exception_set()) { return false; } - NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); + impl->ShortArgumentOperation(arg1); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_shortReturnOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -792,27 +1072,28 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); - TypeTraits<int16_t >::ReturnType value = - impl->ShortReturnOperation(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } + wrapper_private->wrappable<NumericTypesTestInterface>().get(); - if (!exception_state.IsExceptionSet()) { + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->ShortReturnOperation(), + &result_value); + } + if (!exception_state.is_exception_set()) { args.rval().set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_unrestrictedDoubleArgumentOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -825,37 +1106,41 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<double >::ConversionType arg1; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &arg1); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg1); + if (exception_state.is_exception_set()) { return false; } - NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); + impl->UnrestrictedDoubleArgumentOperation(arg1); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_unrestrictedDoubleReturnOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -868,27 +1153,28 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); - TypeTraits<double >::ReturnType value = - impl->UnrestrictedDoubleReturnOperation(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } + wrapper_private->wrappable<NumericTypesTestInterface>().get(); - if (!exception_state.IsExceptionSet()) { + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->UnrestrictedDoubleReturnOperation(), + &result_value); + } + if (!exception_state.is_exception_set()) { args.rval().set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_unsignedLongArgumentOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -901,37 +1187,122 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<uint32_t >::ConversionType arg1; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &arg1); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg1); + if (exception_state.is_exception_set()) { return false; } - NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); + impl->UnsignedLongArgumentOperation(arg1); result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} - if (!exception_state.IsExceptionSet()) { +JSBool fcn_unsignedLongLongArgumentOperation( + JSContext* context, uint32_t argc, JS::Value *vp) { + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + // Compute the 'this' value. + JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); + // 'this' should be an object. + JS::RootedObject object(context); + if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) { + NOTREACHED(); + return false; + } + if (!JS_ValueToObject(context, this_value, object.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); + const size_t kMinArguments = 1; + if (args.length() < kMinArguments) { + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Not enough arguments."); + return false; + } + // Non-optional arguments + TypeTraits<uint64_t >::ConversionType arg1; + + DCHECK_LT(0, args.length()); + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg1); + if (exception_state.is_exception_set()) { + return false; + } + + impl->UnsignedLongLongArgumentOperation(arg1); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +JSBool fcn_unsignedLongLongReturnOperation( + JSContext* context, uint32_t argc, JS::Value *vp) { + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + // Compute the 'this' value. + JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); + // 'this' should be an object. + JS::RootedObject object(context); + if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) { + NOTREACHED(); + return false; + } + if (!JS_ValueToObject(context, this_value, object.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->UnsignedLongLongReturnOperation(), + &result_value); + } + if (!exception_state.is_exception_set()) { args.rval().set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_unsignedLongReturnOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -944,27 +1315,28 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); - TypeTraits<uint32_t >::ReturnType value = - impl->UnsignedLongReturnOperation(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } + wrapper_private->wrappable<NumericTypesTestInterface>().get(); - if (!exception_state.IsExceptionSet()) { + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->UnsignedLongReturnOperation(), + &result_value); + } + if (!exception_state.is_exception_set()) { args.rval().set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_unsignedShortArgumentOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -977,37 +1349,41 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + NumericTypesTestInterface* impl = + wrapper_private->wrappable<NumericTypesTestInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<uint16_t >::ConversionType arg1; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &arg1); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg1); + if (exception_state.is_exception_set()) { return false; } - NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); + impl->UnsignedShortArgumentOperation(arg1); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_unsignedShortReturnOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -1020,20 +1396,23 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); NumericTypesTestInterface* impl = - WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object); - TypeTraits<uint16_t >::ReturnType value = - impl->UnsignedShortReturnOperation(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } + wrapper_private->wrappable<NumericTypesTestInterface>().get(); - if (!exception_state.IsExceptionSet()) { + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->UnsignedShortReturnOperation(), + &result_value); + } + if (!exception_state.is_exception_set()) { args.rval().set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -1075,6 +1454,18 @@ JSOP_WRAPPER(&set_unsignedLongProperty), }, { // Read/Write property + "longLongProperty", 0, + JSPROP_SHARED | JSPROP_ENUMERATE, + JSOP_WRAPPER(&get_longLongProperty), + JSOP_WRAPPER(&set_longLongProperty), + }, + { // Read/Write property + "unsignedLongLongProperty", 0, + JSPROP_SHARED | JSPROP_ENUMERATE, + JSOP_WRAPPER(&get_unsignedLongLongProperty), + JSOP_WRAPPER(&set_unsignedLongLongProperty), + }, + { // Read/Write property "doubleProperty", 0, JSPROP_SHARED | JSPROP_ENUMERATE, JSOP_WRAPPER(&get_doubleProperty), @@ -1126,6 +1517,20 @@ NULL, }, { + "longLongArgumentOperation", + JSOP_WRAPPER(&fcn_longLongArgumentOperation), + 1, + JSPROP_ENUMERATE, + NULL, + }, + { + "longLongReturnOperation", + JSOP_WRAPPER(&fcn_longLongReturnOperation), + 0, + JSPROP_ENUMERATE, + NULL, + }, + { "longReturnOperation", JSOP_WRAPPER(&fcn_longReturnOperation), 0, @@ -1182,6 +1587,20 @@ NULL, }, { + "unsignedLongLongArgumentOperation", + JSOP_WRAPPER(&fcn_unsignedLongLongArgumentOperation), + 1, + JSPROP_ENUMERATE, + NULL, + }, + { + "unsignedLongLongReturnOperation", + JSOP_WRAPPER(&fcn_unsignedLongLongReturnOperation), + 0, + JSPROP_ENUMERATE, + NULL, + }, + { "unsignedLongReturnOperation", JSOP_WRAPPER(&fcn_unsignedLongReturnOperation), 0, @@ -1209,6 +1628,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -1228,7 +1651,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -1248,8 +1672,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "NumericTypesTestInterface"; - name_value.setString(JS_NewStringCopyZ(context, "NumericTypesTestInterface")); + const char name[] = + "NumericTypesTestInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -1258,8 +1683,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -1291,7 +1721,7 @@ } // namespace // static -JSObject* MozjsNumericTypesTestInterface::CreateInstance( +JSObject* MozjsNumericTypesTestInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -1299,8 +1729,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsNumericTypesTestInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.h index 696d709..f33342b 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.h
@@ -38,8 +38,9 @@ class MozjsNumericTypesTestInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.cc index 9fcc745..5e32d87 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.cc
@@ -34,14 +34,20 @@ #include "cobalt/bindings/testing/derived_interface.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -63,6 +69,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -73,7 +80,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -87,6 +96,37 @@ namespace { +class MozjsObjectTypeBindingsInterfaceHandler : public ProxyHandler { + public: + MozjsObjectTypeBindingsInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsObjectTypeBindingsInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsObjectTypeBindingsInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsObjectTypeBindingsInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -123,7 +163,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "ObjectTypeBindingsInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -141,18 +182,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - ObjectTypeBindingsInterface* impl = - WrapperPrivate::GetWrappable<ObjectTypeBindingsInterface>(object); - TypeTraits<scoped_refptr<ArbitraryInterface> >::ReturnType value = - impl->arbitrary_object(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + ObjectTypeBindingsInterface* impl = + wrapper_private->wrappable<ObjectTypeBindingsInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->arbitrary_object(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_arbitraryObject( @@ -160,18 +204,21 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + ObjectTypeBindingsInterface* impl = + wrapper_private->wrappable<ObjectTypeBindingsInterface>().get(); TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - ObjectTypeBindingsInterface* impl = - WrapperPrivate::GetWrappable<ObjectTypeBindingsInterface>(object); + impl->set_arbitrary_object(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool get_baseInterface( @@ -179,18 +226,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - ObjectTypeBindingsInterface* impl = - WrapperPrivate::GetWrappable<ObjectTypeBindingsInterface>(object); - TypeTraits<scoped_refptr<BaseInterface> >::ReturnType value = - impl->base_interface(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + ObjectTypeBindingsInterface* impl = + wrapper_private->wrappable<ObjectTypeBindingsInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->base_interface(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool get_derivedInterface( @@ -198,18 +248,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - ObjectTypeBindingsInterface* impl = - WrapperPrivate::GetWrappable<ObjectTypeBindingsInterface>(object); - TypeTraits<scoped_refptr<DerivedInterface> >::ReturnType value = - impl->derived_interface(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + ObjectTypeBindingsInterface* impl = + wrapper_private->wrappable<ObjectTypeBindingsInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->derived_interface(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_derivedInterface( @@ -217,18 +270,21 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + ObjectTypeBindingsInterface* impl = + wrapper_private->wrappable<ObjectTypeBindingsInterface>().get(); TypeTraits<scoped_refptr<DerivedInterface> >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - ObjectTypeBindingsInterface* impl = - WrapperPrivate::GetWrappable<ObjectTypeBindingsInterface>(object); + impl->set_derived_interface(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool get_objectProperty( @@ -236,18 +292,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - ObjectTypeBindingsInterface* impl = - WrapperPrivate::GetWrappable<ObjectTypeBindingsInterface>(object); - TypeTraits<OpaqueHandle >::ReturnType value = - impl->object_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + ObjectTypeBindingsInterface* impl = + wrapper_private->wrappable<ObjectTypeBindingsInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->object_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_objectProperty( @@ -255,18 +314,21 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + ObjectTypeBindingsInterface* impl = + wrapper_private->wrappable<ObjectTypeBindingsInterface>().get(); TypeTraits<OpaqueHandle >::ConversionType value; FromJSValue(context, vp, (kConversionFlagNullable), &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - ObjectTypeBindingsInterface* impl = - WrapperPrivate::GetWrappable<ObjectTypeBindingsInterface>(object); + impl->set_object_property(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -306,6 +368,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -325,7 +391,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -345,8 +412,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "ObjectTypeBindingsInterface"; - name_value.setString(JS_NewStringCopyZ(context, "ObjectTypeBindingsInterface")); + const char name[] = + "ObjectTypeBindingsInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -355,8 +423,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -388,7 +461,7 @@ } // namespace // static -JSObject* MozjsObjectTypeBindingsInterface::CreateInstance( +JSObject* MozjsObjectTypeBindingsInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -396,8 +469,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsObjectTypeBindingsInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.h index 1c53b9c..27aa23c 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.h
@@ -38,8 +38,9 @@ class MozjsObjectTypeBindingsInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.cc index ee67897..473b292 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.cc
@@ -30,14 +30,20 @@ #include "cobalt/bindings/testing/arbitrary_interface.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -55,6 +61,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -65,7 +72,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -79,6 +88,37 @@ namespace { +class MozjsOperationsTestInterfaceHandler : public ProxyHandler { + public: + MozjsOperationsTestInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsOperationsTestInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsOperationsTestInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsOperationsTestInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -115,7 +155,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "OperationsTestInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -130,9 +171,7 @@ JSBool fcn_longFunctionNoArgs( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -145,27 +184,28 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); OperationsTestInterface* impl = - WrapperPrivate::GetWrappable<OperationsTestInterface>(object); - TypeTraits<int32_t >::ReturnType value = - impl->LongFunctionNoArgs(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } + wrapper_private->wrappable<OperationsTestInterface>().get(); - if (!exception_state.IsExceptionSet()) { + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->LongFunctionNoArgs(), + &result_value); + } + if (!exception_state.is_exception_set()) { args.rval().set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_objectFunctionNoArgs( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -178,27 +218,28 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); OperationsTestInterface* impl = - WrapperPrivate::GetWrappable<OperationsTestInterface>(object); - TypeTraits<scoped_refptr<ArbitraryInterface> >::ReturnType value = - impl->ObjectFunctionNoArgs(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } + wrapper_private->wrappable<OperationsTestInterface>().get(); - if (!exception_state.IsExceptionSet()) { + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->ObjectFunctionNoArgs(), + &result_value); + } + if (!exception_state.is_exception_set()) { args.rval().set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_optionalArgumentWithDefault( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -211,37 +252,137 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + OperationsTestInterface* impl = + wrapper_private->wrappable<OperationsTestInterface>().get(); + // Optional arguments with default values + TypeTraits<double >::ConversionType arg1 = + 2.718; + size_t num_set_arguments = 1; + if (args.length() > 0) { + JS::RootedValue optional_value0( + context, args[0]); + FromJSValue(context, + optional_value0, + (kConversionFlagRestricted), + &exception_state, + &arg1); + if (exception_state.is_exception_set()) { + return false; + } + } + + impl->OptionalArgumentWithDefault(arg1); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +JSBool fcn_optionalArguments( + JSContext* context, uint32_t argc, JS::Value *vp) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + // Compute the 'this' value. + JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); + // 'this' should be an object. + JS::RootedObject object(context); + if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) { + NOTREACHED(); + return false; + } + if (!JS_ValueToObject(context, this_value, object.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + OperationsTestInterface* impl = + wrapper_private->wrappable<OperationsTestInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } - TypeTraits<double >::ConversionType arg1; + // Non-optional arguments + TypeTraits<int32_t >::ConversionType arg1; + // Optional arguments + TypeTraits<int32_t >::ConversionType arg2; + TypeTraits<int32_t >::ConversionType arg3; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - (kConversionFlagRestricted), &exception_state, &arg1); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg1); + if (exception_state.is_exception_set()) { return false; } - OperationsTestInterface* impl = - WrapperPrivate::GetWrappable<OperationsTestInterface>(object); - impl->OptionalArgumentWithDefault(arg1); - result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); + size_t num_set_arguments = 1; + if (args.length() > 1) { + JS::RootedValue optional_value0( + context, args[1]); + FromJSValue(context, + optional_value0, + kNoConversionFlags, + &exception_state, + &arg2); + if (exception_state.is_exception_set()) { + return false; + } + ++num_set_arguments; } - return !exception_state.IsExceptionSet(); + if (args.length() > 2) { + JS::RootedValue optional_value1( + context, args[2]); + FromJSValue(context, + optional_value1, + kNoConversionFlags, + &exception_state, + &arg3); + if (exception_state.is_exception_set()) { + return false; + } + ++num_set_arguments; + } + switch (num_set_arguments) { + case 1: + { + impl->OptionalArguments(arg1); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); + } + break; + case 2: + { + impl->OptionalArguments(arg1, arg2); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); + } + break; + case 3: + { + impl->OptionalArguments(arg1, arg2, arg3); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); + } + break; + default: + NOTREACHED(); + return false; + } } -JSBool fcn_optionalArguments( +JSBool fcn_optionalNullableArgumentsWithDefaults( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -254,51 +395,245 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + OperationsTestInterface* impl = + wrapper_private->wrappable<OperationsTestInterface>().get(); + // Optional arguments with default values + TypeTraits<base::optional<bool > >::ConversionType arg1 = + base::nullopt; + TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType arg2 = + NULL; + size_t num_set_arguments = 2; + if (args.length() > 0) { + JS::RootedValue optional_value0( + context, args[0]); + FromJSValue(context, + optional_value0, + (kConversionFlagNullable), + &exception_state, + &arg1); + if (exception_state.is_exception_set()) { + return false; + } + } + if (args.length() > 1) { + JS::RootedValue optional_value1( + context, args[1]); + FromJSValue(context, + optional_value1, + (kConversionFlagNullable), + &exception_state, + &arg2); + if (exception_state.is_exception_set()) { + return false; + } + } + + impl->OptionalNullableArgumentsWithDefaults(arg1, arg2); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +JSBool fcn_overloadedFunction1( + JSContext* context, uint32_t argc, JS::Value *vp) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + // Compute the 'this' value. + JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); + // 'this' should be an object. + JS::RootedObject object(context); + if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) { + NOTREACHED(); + return false; + } + if (!JS_ValueToObject(context, this_value, object.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + OperationsTestInterface* impl = + wrapper_private->wrappable<OperationsTestInterface>().get(); + + impl->OverloadedFunction(); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +JSBool fcn_overloadedFunction2( + JSContext* context, uint32_t argc, JS::Value *vp) { + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + // Compute the 'this' value. + JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); + // 'this' should be an object. + JS::RootedObject object(context); + if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) { + NOTREACHED(); + return false; + } + if (!JS_ValueToObject(context, this_value, object.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + OperationsTestInterface* impl = + wrapper_private->wrappable<OperationsTestInterface>().get(); + const size_t kMinArguments = 1; + if (args.length() < kMinArguments) { + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Not enough arguments."); + return false; + } + // Non-optional arguments + TypeTraits<int32_t >::ConversionType arg; + + DCHECK_LT(0, args.length()); + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg); + if (exception_state.is_exception_set()) { + return false; + } + + impl->OverloadedFunction(arg); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +JSBool fcn_overloadedFunction3( + JSContext* context, uint32_t argc, JS::Value *vp) { + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + // Compute the 'this' value. + JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); + // 'this' should be an object. + JS::RootedObject object(context); + if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) { + NOTREACHED(); + return false; + } + if (!JS_ValueToObject(context, this_value, object.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + OperationsTestInterface* impl = + wrapper_private->wrappable<OperationsTestInterface>().get(); + const size_t kMinArguments = 1; + if (args.length() < kMinArguments) { + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Not enough arguments."); + return false; + } + // Non-optional arguments + TypeTraits<std::string >::ConversionType arg; + + DCHECK_LT(0, args.length()); + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg); + if (exception_state.is_exception_set()) { + return false; + } + + impl->OverloadedFunction(arg); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +JSBool fcn_overloadedFunction4( + JSContext* context, uint32_t argc, JS::Value *vp) { + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + // Compute the 'this' value. + JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); + // 'this' should be an object. + JS::RootedObject object(context); + if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) { + NOTREACHED(); + return false; + } + if (!JS_ValueToObject(context, this_value, object.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + OperationsTestInterface* impl = + wrapper_private->wrappable<OperationsTestInterface>().get(); const size_t kMinArguments = 3; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } + // Non-optional arguments TypeTraits<int32_t >::ConversionType arg1; - DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &arg1); - if (exception_state.IsExceptionSet()) { - return false; - } TypeTraits<int32_t >::ConversionType arg2; - DCHECK_LT(1, args.length()); - FromJSValue(context, args.handleAt(1), - kNoConversionFlags, &exception_state, &arg2); - if (exception_state.IsExceptionSet()) { - return false; - } TypeTraits<int32_t >::ConversionType arg3; - DCHECK_LT(2, args.length()); - FromJSValue(context, args.handleAt(2), - kNoConversionFlags, &exception_state, &arg3); - if (exception_state.IsExceptionSet()) { + + DCHECK_LT(0, args.length()); + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg1); + if (exception_state.is_exception_set()) { return false; } - OperationsTestInterface* impl = - WrapperPrivate::GetWrappable<OperationsTestInterface>(object); - impl->OptionalArguments(arg1, arg2, arg3); - result_value.set(JS::UndefinedHandleValue); - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); + DCHECK_LT(1, args.length()); + JS::RootedValue non_optional_value1( + context, args[1]); + FromJSValue(context, + non_optional_value1, + kNoConversionFlags, + &exception_state, &arg2); + if (exception_state.is_exception_set()) { + return false; } - return !exception_state.IsExceptionSet(); + + DCHECK_LT(2, args.length()); + JS::RootedValue non_optional_value2( + context, args[2]); + FromJSValue(context, + non_optional_value2, + kNoConversionFlags, + &exception_state, &arg3); + if (exception_state.is_exception_set()) { + return false; + } + + impl->OverloadedFunction(arg1, arg2, arg3); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); } -JSBool fcn_optionalNullableArgumentsWithDefaults( +JSBool fcn_overloadedFunction5( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -311,44 +646,128 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); - const size_t kMinArguments = 2; + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + OperationsTestInterface* impl = + wrapper_private->wrappable<OperationsTestInterface>().get(); + const size_t kMinArguments = 3; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } - TypeTraits<base::optional<bool > >::ConversionType arg1; - DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - (kConversionFlagNullable), &exception_state, &arg1); - if (exception_state.IsExceptionSet()) { - return false; - } - TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType arg2; - DCHECK_LT(1, args.length()); - FromJSValue(context, args.handleAt(1), - (kConversionFlagNullable), &exception_state, &arg2); - if (exception_state.IsExceptionSet()) { - return false; - } - OperationsTestInterface* impl = - WrapperPrivate::GetWrappable<OperationsTestInterface>(object); - impl->OptionalNullableArgumentsWithDefaults(arg1, arg2); - result_value.set(JS::UndefinedHandleValue); + // Non-optional arguments + TypeTraits<int32_t >::ConversionType arg1; + TypeTraits<int32_t >::ConversionType arg2; + TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType arg3; - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); + DCHECK_LT(0, args.length()); + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg1); + if (exception_state.is_exception_set()) { + return false; } - return !exception_state.IsExceptionSet(); + + DCHECK_LT(1, args.length()); + JS::RootedValue non_optional_value1( + context, args[1]); + FromJSValue(context, + non_optional_value1, + kNoConversionFlags, + &exception_state, &arg2); + if (exception_state.is_exception_set()) { + return false; + } + + DCHECK_LT(2, args.length()); + JS::RootedValue non_optional_value2( + context, args[2]); + FromJSValue(context, + non_optional_value2, + kNoConversionFlags, + &exception_state, &arg3); + if (exception_state.is_exception_set()) { + return false; + } + + impl->OverloadedFunction(arg1, arg2, arg3); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); } JSBool fcn_overloadedFunction( JSContext* context, uint32_t argc, JS::Value *vp) { + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + switch(argc) { + case(0): { + // Overload resolution algorithm details found here: + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + if (true) { + return fcn_overloadedFunction1( + context, argc, vp); + } + break; + } + case(1): { + // Overload resolution algorithm details found here: + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + JS::RootedValue arg(context, args[0]); + MozjsGlobalObjectProxy* global_object_proxy = + static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_object_proxy->wrapper_factory(); + if (arg.isNumber()) { + return fcn_overloadedFunction2( + context, argc, vp); + } + if (true) { + return fcn_overloadedFunction3( + context, argc, vp); + } + if (true) { + return fcn_overloadedFunction2( + context, argc, vp); + } + break; + } + case(3): { + // Overload resolution algorithm details found here: + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + JS::RootedValue arg(context, args[2]); + MozjsGlobalObjectProxy* global_object_proxy = + static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_object_proxy->wrapper_factory(); + if (arg.isObject() ? wrapper_factory->DoesObjectImplementInterface( + JSVAL_TO_OBJECT(arg), base::GetTypeId<ArbitraryInterface>()) : + false) { + return fcn_overloadedFunction5( + context, argc, vp); + } + if (true) { + return fcn_overloadedFunction4( + context, argc, vp); + } + break; + } + } + // Invalid number of args + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + // 4. If S is empty, then throw a TypeError. MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Invalid number of arguments."); + return false; +} +JSBool fcn_overloadedNullable1( + JSContext* context, uint32_t argc, JS::Value *vp) { + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -361,67 +780,119 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); OperationsTestInterface* impl = - WrapperPrivate::GetWrappable<OperationsTestInterface>(object); - impl->OverloadedFunction(); - result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); + wrapper_private->wrappable<OperationsTestInterface>().get(); + const size_t kMinArguments = 1; + if (args.length() < kMinArguments) { + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Not enough arguments."); + return false; } - return !exception_state.IsExceptionSet(); + // Non-optional arguments + TypeTraits<int32_t >::ConversionType arg; + + DCHECK_LT(0, args.length()); + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg); + if (exception_state.is_exception_set()) { + return false; + } + + impl->OverloadedNullable(arg); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +JSBool fcn_overloadedNullable2( + JSContext* context, uint32_t argc, JS::Value *vp) { + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + // Compute the 'this' value. + JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); + // 'this' should be an object. + JS::RootedObject object(context); + if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) { + NOTREACHED(); + return false; + } + if (!JS_ValueToObject(context, this_value, object.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + OperationsTestInterface* impl = + wrapper_private->wrappable<OperationsTestInterface>().get(); + const size_t kMinArguments = 1; + if (args.length() < kMinArguments) { + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Not enough arguments."); + return false; + } + // Non-optional arguments + TypeTraits<base::optional<bool > >::ConversionType arg; + + DCHECK_LT(0, args.length()); + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + (kConversionFlagNullable), + &exception_state, &arg); + if (exception_state.is_exception_set()) { + return false; + } + + impl->OverloadedNullable(arg); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); } JSBool fcn_overloadedNullable( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - - // Compute the 'this' value. - JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); - // 'this' should be an object. - JS::RootedObject object(context); - if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) { - NOTREACHED(); - return false; - } - if (!JS_ValueToObject(context, this_value, object.address())) { - NOTREACHED(); - return false; - } - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); - const size_t kMinArguments = 1; - if (args.length() < kMinArguments) { - exception_state.SetSimpleException( - script::ExceptionState::kTypeError, "Not enough arguments."); - return false; + switch(argc) { + case(1): { + // Overload resolution algorithm details found here: + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + JS::RootedValue arg(context, args[0]); + MozjsGlobalObjectProxy* global_object_proxy = + static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_object_proxy->wrapper_factory(); + if (arg.isNullOrUndefined()) { + return fcn_overloadedNullable2( + context, argc, vp); + } + if (true) { + return fcn_overloadedNullable1( + context, argc, vp); + } + break; + } } - TypeTraits<int32_t >::ConversionType arg; - DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &arg); - if (exception_state.IsExceptionSet()) { - return false; - } - OperationsTestInterface* impl = - WrapperPrivate::GetWrappable<OperationsTestInterface>(object); - impl->OverloadedNullable(arg); - result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + // Invalid number of args + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + // 4. If S is empty, then throw a TypeError. + MozjsExceptionState exception_state(context); + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Invalid number of arguments."); + return false; } JSBool fcn_stringFunctionNoArgs( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -434,27 +905,28 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); OperationsTestInterface* impl = - WrapperPrivate::GetWrappable<OperationsTestInterface>(object); - TypeTraits<std::string >::ReturnType value = - impl->StringFunctionNoArgs(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } + wrapper_private->wrappable<OperationsTestInterface>().get(); - if (!exception_state.IsExceptionSet()) { + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->StringFunctionNoArgs(), + &result_value); + } + if (!exception_state.is_exception_set()) { args.rval().set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_variadicPrimitiveArguments( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -467,37 +939,175 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + OperationsTestInterface* impl = + wrapper_private->wrappable<OperationsTestInterface>().get(); + // Variadic argument + TypeTraits<std::vector<int32_t> >::ConversionType bools; + + // Get variadic arguments. + const size_t kFirstVariadicArgIndex = 0; + if (args.length() > kFirstVariadicArgIndex) { + bools.resize(args.length() - kFirstVariadicArgIndex); + for (int i = 0; i + kFirstVariadicArgIndex < args.length(); ++i) { + JS::RootedValue variadic_argument_value( + context, args[i + kFirstVariadicArgIndex]); + FromJSValue(context, + variadic_argument_value, + kNoConversionFlags, + &exception_state, + &bools[i]); + if (exception_state.is_exception_set()) { + return false; + } + } + } + + impl->VariadicPrimitiveArguments(bools); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +JSBool fcn_variadicStringArgumentsAfterOptionalArgument( + JSContext* context, uint32_t argc, JS::Value *vp) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + // Compute the 'this' value. + JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); + // 'this' should be an object. + JS::RootedObject object(context); + if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) { + NOTREACHED(); + return false; + } + if (!JS_ValueToObject(context, this_value, object.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + OperationsTestInterface* impl = + wrapper_private->wrappable<OperationsTestInterface>().get(); + // Optional arguments + TypeTraits<bool >::ConversionType optional_arg; + // Variadic argument + TypeTraits<std::vector<std::string> >::ConversionType strings; + size_t num_set_arguments = 0; + if (args.length() > 0) { + JS::RootedValue optional_value0( + context, args[0]); + FromJSValue(context, + optional_value0, + kNoConversionFlags, + &exception_state, + &optional_arg); + if (exception_state.is_exception_set()) { + return false; + } + ++num_set_arguments; + } + + // Get variadic arguments. + const size_t kLastOptionalArgIndex = 1; + if (num_set_arguments == kLastOptionalArgIndex) { + // If the last optional argument has been set, we will call the overload + // that takes the variadic argument, possibly with an empty vector in the + // case that there are no more arguments left. + ++num_set_arguments; + } + const size_t kFirstVariadicArgIndex = 1; + if (args.length() > kFirstVariadicArgIndex) { + strings.resize(args.length() - kFirstVariadicArgIndex); + for (int i = 0; i + kFirstVariadicArgIndex < args.length(); ++i) { + JS::RootedValue variadic_argument_value( + context, args[i + kFirstVariadicArgIndex]); + FromJSValue(context, + variadic_argument_value, + kNoConversionFlags, + &exception_state, + &strings[i]); + if (exception_state.is_exception_set()) { + return false; + } + } + } + switch (num_set_arguments) { + case 0: + { + impl->VariadicStringArgumentsAfterOptionalArgument(); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); + } + break; + case 2: + { + impl->VariadicStringArgumentsAfterOptionalArgument(optional_arg, strings); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); + } + break; + default: + NOTREACHED(); + return false; + } +} + +JSBool fcn_voidFunctionLongArg( + JSContext* context, uint32_t argc, JS::Value *vp) { + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + // Compute the 'this' value. + JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); + // 'this' should be an object. + JS::RootedObject object(context); + if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) { + NOTREACHED(); + return false; + } + if (!JS_ValueToObject(context, this_value, object.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + OperationsTestInterface* impl = + wrapper_private->wrappable<OperationsTestInterface>().get(); const size_t kMinArguments = 1; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } - TypeTraits<std::vector<int32_t> >::ConversionType bools; + // Non-optional arguments + TypeTraits<int32_t >::ConversionType arg; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &bools); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg); + if (exception_state.is_exception_set()) { return false; } - OperationsTestInterface* impl = - WrapperPrivate::GetWrappable<OperationsTestInterface>(object); - impl->VariadicPrimitiveArguments(bools); - result_value.set(JS::UndefinedHandleValue); - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + impl->VoidFunctionLongArg(arg); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); } -JSBool fcn_variadicStringArgumentsAfterOptionalArgument( +JSBool fcn_voidFunctionNoArgs( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -510,196 +1120,217 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + OperationsTestInterface* impl = + wrapper_private->wrappable<OperationsTestInterface>().get(); + + impl->VoidFunctionNoArgs(); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +JSBool fcn_voidFunctionObjectArg( + JSContext* context, uint32_t argc, JS::Value *vp) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + // Compute the 'this' value. + JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); + // 'this' should be an object. + JS::RootedObject object(context); + if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) { + NOTREACHED(); + return false; + } + if (!JS_ValueToObject(context, this_value, object.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + OperationsTestInterface* impl = + wrapper_private->wrappable<OperationsTestInterface>().get(); + const size_t kMinArguments = 1; + if (args.length() < kMinArguments) { + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Not enough arguments."); + return false; + } + // Non-optional arguments + TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType arg; + + DCHECK_LT(0, args.length()); + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg); + if (exception_state.is_exception_set()) { + return false; + } + + impl->VoidFunctionObjectArg(arg); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +JSBool fcn_voidFunctionStringArg( + JSContext* context, uint32_t argc, JS::Value *vp) { + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + // Compute the 'this' value. + JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); + // 'this' should be an object. + JS::RootedObject object(context); + if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) { + NOTREACHED(); + return false; + } + if (!JS_ValueToObject(context, this_value, object.address())) { + NOTREACHED(); + return false; + } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + OperationsTestInterface* impl = + wrapper_private->wrappable<OperationsTestInterface>().get(); + const size_t kMinArguments = 1; + if (args.length() < kMinArguments) { + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Not enough arguments."); + return false; + } + // Non-optional arguments + TypeTraits<std::string >::ConversionType arg; + + DCHECK_LT(0, args.length()); + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg); + if (exception_state.is_exception_set()) { + return false; + } + + impl->VoidFunctionStringArg(arg); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +JSBool staticfcn_overloadedFunction1( + JSContext* context, uint32_t argc, JS::Value *vp) { + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + const size_t kMinArguments = 1; + if (args.length() < kMinArguments) { + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Not enough arguments."); + return false; + } + // Non-optional arguments + TypeTraits<double >::ConversionType arg; + + DCHECK_LT(0, args.length()); + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + (kConversionFlagRestricted), + &exception_state, &arg); + if (exception_state.is_exception_set()) { + return false; + } + + OperationsTestInterface::OverloadedFunction(arg); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +JSBool staticfcn_overloadedFunction2( + JSContext* context, uint32_t argc, JS::Value *vp) { + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + const size_t kMinArguments = 2; if (args.length() < kMinArguments) { exception_state.SetSimpleException( script::ExceptionState::kTypeError, "Not enough arguments."); return false; } - TypeTraits<bool >::ConversionType optional_arg; + // Non-optional arguments + TypeTraits<double >::ConversionType arg1; + TypeTraits<double >::ConversionType arg2; + DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &optional_arg); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + (kConversionFlagRestricted), + &exception_state, &arg1); + if (exception_state.is_exception_set()) { return false; } - TypeTraits<std::vector<std::string> >::ConversionType strings; + DCHECK_LT(1, args.length()); - FromJSValue(context, args.handleAt(1), - kNoConversionFlags, &exception_state, &strings); - if (exception_state.IsExceptionSet()) { + JS::RootedValue non_optional_value1( + context, args[1]); + FromJSValue(context, + non_optional_value1, + (kConversionFlagRestricted), + &exception_state, &arg2); + if (exception_state.is_exception_set()) { return false; } - OperationsTestInterface* impl = - WrapperPrivate::GetWrappable<OperationsTestInterface>(object); - impl->VariadicStringArgumentsAfterOptionalArgument(optional_arg, strings); - result_value.set(JS::UndefinedHandleValue); - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + OperationsTestInterface::OverloadedFunction(arg1, arg2); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); } -JSBool fcn_voidFunctionLongArg( +JSBool staticfcn_overloadedFunction( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - - // Compute the 'this' value. - JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); - // 'this' should be an object. - JS::RootedObject object(context); - if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) { - NOTREACHED(); - return false; - } - if (!JS_ValueToObject(context, this_value, object.address())) { - NOTREACHED(); - return false; - } - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); - const size_t kMinArguments = 1; - if (args.length() < kMinArguments) { - exception_state.SetSimpleException( - script::ExceptionState::kTypeError, "Not enough arguments."); - return false; + switch(argc) { + case(1): { + // Overload resolution algorithm details found here: + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + if (true) { + return staticfcn_overloadedFunction1( + context, argc, vp); + } + break; + } + case(2): { + // Overload resolution algorithm details found here: + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + if (true) { + return staticfcn_overloadedFunction2( + context, argc, vp); + } + break; + } } - TypeTraits<int32_t >::ConversionType arg; - DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &arg); - if (exception_state.IsExceptionSet()) { - return false; - } - OperationsTestInterface* impl = - WrapperPrivate::GetWrappable<OperationsTestInterface>(object); - impl->VoidFunctionLongArg(arg); - result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); -} - -JSBool fcn_voidFunctionNoArgs( - JSContext* context, uint32_t argc, JS::Value *vp) { + // Invalid number of args + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + // 4. If S is empty, then throw a TypeError. MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - - // Compute the 'this' value. - JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); - // 'this' should be an object. - JS::RootedObject object(context); - if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) { - NOTREACHED(); - return false; - } - if (!JS_ValueToObject(context, this_value, object.address())) { - NOTREACHED(); - return false; - } - - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); - OperationsTestInterface* impl = - WrapperPrivate::GetWrappable<OperationsTestInterface>(object); - impl->VoidFunctionNoArgs(); - result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); -} - -JSBool fcn_voidFunctionObjectArg( - JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - - // Compute the 'this' value. - JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); - // 'this' should be an object. - JS::RootedObject object(context); - if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) { - NOTREACHED(); - return false; - } - if (!JS_ValueToObject(context, this_value, object.address())) { - NOTREACHED(); - return false; - } - - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); - const size_t kMinArguments = 1; - if (args.length() < kMinArguments) { - exception_state.SetSimpleException( - script::ExceptionState::kTypeError, "Not enough arguments."); - return false; - } - TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType arg; - DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &arg); - if (exception_state.IsExceptionSet()) { - return false; - } - OperationsTestInterface* impl = - WrapperPrivate::GetWrappable<OperationsTestInterface>(object); - impl->VoidFunctionObjectArg(arg); - result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); -} - -JSBool fcn_voidFunctionStringArg( - JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - - // Compute the 'this' value. - JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); - // 'this' should be an object. - JS::RootedObject object(context); - if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) { - NOTREACHED(); - return false; - } - if (!JS_ValueToObject(context, this_value, object.address())) { - NOTREACHED(); - return false; - } - - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); - const size_t kMinArguments = 1; - if (args.length() < kMinArguments) { - exception_state.SetSimpleException( - script::ExceptionState::kTypeError, "Not enough arguments."); - return false; - } - TypeTraits<std::string >::ConversionType arg; - DCHECK_LT(0, args.length()); - FromJSValue(context, args.handleAt(0), - kNoConversionFlags, &exception_state, &arg); - if (exception_state.IsExceptionSet()) { - return false; - } - OperationsTestInterface* impl = - WrapperPrivate::GetWrappable<OperationsTestInterface>(object); - impl->VoidFunctionStringArg(arg); - result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Invalid number of arguments."); + return false; } @@ -813,6 +1444,17 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + { + "overloadedFunction", + JSOP_WRAPPER(&staticfcn_overloadedFunction), + 1, + JSPROP_ENUMERATE, + NULL, + }, + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -832,7 +1474,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -852,8 +1495,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "OperationsTestInterface"; - name_value.setString(JS_NewStringCopyZ(context, "OperationsTestInterface")); + const char name[] = + "OperationsTestInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -862,8 +1506,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -895,7 +1544,7 @@ } // namespace // static -JSObject* MozjsOperationsTestInterface::CreateInstance( +JSObject* MozjsOperationsTestInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -903,8 +1552,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsOperationsTestInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.h index 7358b5a..d0e54e1 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.h
@@ -38,8 +38,9 @@ class MozjsOperationsTestInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.cc index 5e84fd6..b977879 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.cc
@@ -30,14 +30,20 @@ #include "cobalt/bindings/testing/arbitrary_interface.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -55,6 +61,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -65,7 +72,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -79,6 +88,37 @@ namespace { +class MozjsPutForwardsInterfaceHandler : public ProxyHandler { + public: + MozjsPutForwardsInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsPutForwardsInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsPutForwardsInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsPutForwardsInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -115,7 +155,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "PutForwardsInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -133,18 +174,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - PutForwardsInterface* impl = - WrapperPrivate::GetWrappable<PutForwardsInterface>(object); - TypeTraits<scoped_refptr<ArbitraryInterface> >::ReturnType value = - impl->forwarding_attribute(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + PutForwardsInterface* impl = + wrapper_private->wrappable<PutForwardsInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->forwarding_attribute(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_forwardingAttribute( @@ -152,14 +196,78 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType value; + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + PutForwardsInterface* impl = + wrapper_private->wrappable<PutForwardsInterface>().get(); + { // Begin scope of scoped_refptr<ArbitraryInterface> forwarded_impl. + scoped_refptr<ArbitraryInterface> forwarded_impl = + impl->forwarding_attribute(); + if (!forwarded_impl) { + NOTREACHED(); + return false; + } + if (!exception_state.is_exception_set()) { + TypeTraits<std::string >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - NOTIMPLEMENTED(); - return !exception_state.IsExceptionSet(); + + forwarded_impl->set_arbitrary_property(value); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + return !exception_state.is_exception_set(); + } // End scope of scoped_refptr<ArbitraryInterface> forwarded_impl. +} + +JSBool staticget_staticForwardingAttribute( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JS::MutableHandleValue vp) { + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + PutForwardsInterface::static_forwarding_attribute(), + &result_value); + } + if (!exception_state.is_exception_set()) { + vp.set(result_value); + } + return !exception_state.is_exception_set(); +} + +JSBool staticset_staticForwardingAttribute( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JSBool strict, JS::MutableHandleValue vp) { + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + { // Begin scope of scoped_refptr<ArbitraryInterface> forwarded_impl. + scoped_refptr<ArbitraryInterface> forwarded_impl = + PutForwardsInterface::static_forwarding_attribute(); + if (!forwarded_impl) { + NOTREACHED(); + return false; + } + if (!exception_state.is_exception_set()) { + TypeTraits<std::string >::ConversionType value; + FromJSValue(context, vp, kNoConversionFlags, &exception_state, + &value); + if (exception_state.is_exception_set()) { + return false; + } + + forwarded_impl->set_arbitrary_property(value); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + return !exception_state.is_exception_set(); + } // End scope of scoped_refptr<ArbitraryInterface> forwarded_impl. } @@ -178,9 +286,19 @@ }; const JSPropertySpec interface_object_properties[] = { + { // Static read/write attribute. + "staticForwardingAttribute", 0, + JSPROP_SHARED | JSPROP_ENUMERATE, + JSOP_WRAPPER(&staticget_staticForwardingAttribute), + JSOP_WRAPPER(&staticset_staticForwardingAttribute), + }, JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -200,7 +318,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -220,8 +339,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "PutForwardsInterface"; - name_value.setString(JS_NewStringCopyZ(context, "PutForwardsInterface")); + const char name[] = + "PutForwardsInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -230,8 +350,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -263,7 +388,7 @@ } // namespace // static -JSObject* MozjsPutForwardsInterface::CreateInstance( +JSObject* MozjsPutForwardsInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -271,8 +396,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsPutForwardsInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.h index eb3d435..06a6435 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.h
@@ -38,8 +38,9 @@ class MozjsPutForwardsInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.cc index d968eb9..f07d2b5 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.cc
@@ -24,11 +24,79 @@ #include "MozjsArbitraryInterface.h" #include "cobalt/bindings/testing/arbitrary_interface.h" +#include "cobalt/script/logging_exception_state.h" +#include "cobalt/script/mozjs/conversion_helpers.h" +#include "cobalt/script/mozjs/mozjs_callback_interface.h" +#include "third_party/mozjs/js/src/jsapi.h" +#include "third_party/mozjs/js/src/jscntxt.h" + namespace { using cobalt::bindings::testing::SingleOperationInterface; using cobalt::bindings::testing::MozjsSingleOperationInterface; using cobalt::bindings::testing::ArbitraryInterface; using cobalt::bindings::testing::MozjsArbitraryInterface; + +using cobalt::script::LoggingExceptionState; +using cobalt::script::mozjs::FromJSValue; +using cobalt::script::mozjs::GetCallableForCallbackInterface; +using cobalt::script::mozjs::ToJSValue; } // namespace +namespace cobalt { +namespace bindings { +namespace testing { + +MozjsSingleOperationInterface::MozjsSingleOperationInterface( + JSContext* context, + JS::HandleObject implementing_object) + : context_(context), + implementing_object_(implementing_object) { } + +base::optional<int32_t > MozjsSingleOperationInterface::HandleCallback( + const scoped_refptr<script::Wrappable>& callback_this, + const scoped_refptr<ArbitraryInterface>& value, + bool* had_exception) const { + JSAutoRequest auto_request(context_); + JSAutoCompartment auto_compartment(context_, implementing_object_); + + bool success = false; + base::optional<int32_t > cobalt_return_value; + // Get callable object. + JS::RootedValue callable(context_); + if (GetCallableForCallbackInterface(context_, implementing_object_, + "handleCallback", &callable)) { + // Convert the callback_this to a JSValue. + JS::RootedValue this_value(context_); + ToJSValue(context_, callback_this, &this_value); + + // Convert arguments. + const int kNumArguments = 1; + JS::Value args[kNumArguments]; + js::SetValueRangeToNull(args, kNumArguments); + js::AutoValueArray auto_array_rooter(context_, args, kNumArguments); + ToJSValue(context_, value, + auto_array_rooter.handleAt(0)); + + // Call the function. + JS::RootedValue return_value(context_); + JSFunction* function = JS_ValueToFunction(context_, callable); + DCHECK(function); + success = JS::Call(context_, this_value, function, kNumArguments, args, + return_value.address()); + DLOG_IF(WARNING, !success) << "Exception in callback."; + if (success) { + LoggingExceptionState exception_state; + FromJSValue(context_, return_value, 0, &exception_state, + &cobalt_return_value); + success = !exception_state.is_exception_set(); + } + } + + *had_exception = !success; + return cobalt_return_value; +} + +} // namespace bindings +} // namespace testing +} // namespace cobalt
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.h index cd32f68..f2bb3be 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.h
@@ -26,11 +26,28 @@ // Headers for other bindings wrapper classes #include "cobalt/bindings/testing/single_operation_interface.h" +#include "third_party/mozjs/js/src/jsapi.h" + namespace cobalt { namespace bindings { namespace testing { -class MozjsSingleOperationInterface { }; +class MozjsSingleOperationInterface : public SingleOperationInterface { + public: + typedef SingleOperationInterface BaseType; + + MozjsSingleOperationInterface( + JSContext* context, JS::HandleObject implementing_object); + base::optional<int32_t > HandleCallback( + const scoped_refptr<script::Wrappable>& callback_this, + const scoped_refptr<ArbitraryInterface>& value, + bool* had_exception) const OVERRIDE; + JSObject* handle() const { return implementing_object_; } + + private: + JSContext* context_; + JS::Heap<JSObject*> implementing_object_; +}; } // namespace bindings } // namespace testing
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.cc index aaa8f00..210586c 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.cc
@@ -26,22 +26,32 @@ #include "cobalt/script/global_object_proxy.h" #include "cobalt/script/opaque_handle.h" #include "cobalt/script/script_object.h" +#include "MozjsArbitraryInterface.h" +#include "cobalt/bindings/testing/arbitrary_interface.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" namespace { using cobalt::bindings::testing::StaticPropertiesInterface; using cobalt::bindings::testing::MozjsStaticPropertiesInterface; +using cobalt::bindings::testing::ArbitraryInterface; +using cobalt::bindings::testing::MozjsArbitraryInterface; using cobalt::script::CallbackInterfaceTraits; using cobalt::script::GlobalObjectProxy; using cobalt::script::OpaqueHandle; @@ -51,6 +61,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +72,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -75,6 +88,37 @@ namespace { +class MozjsStaticPropertiesInterfaceHandler : public ProxyHandler { + public: + MozjsStaticPropertiesInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsStaticPropertiesInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsStaticPropertiesInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsStaticPropertiesInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -111,7 +155,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "StaticPropertiesInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -124,6 +169,288 @@ return interface_data; } +JSBool staticget_staticAttribute( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JS::MutableHandleValue vp) { + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + StaticPropertiesInterface::static_attribute(), + &result_value); + } + if (!exception_state.is_exception_set()) { + vp.set(result_value); + } + return !exception_state.is_exception_set(); +} + +JSBool staticset_staticAttribute( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JSBool strict, JS::MutableHandleValue vp) { + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + TypeTraits<std::string >::ConversionType value; + FromJSValue(context, vp, kNoConversionFlags, &exception_state, + &value); + if (exception_state.is_exception_set()) { + return false; + } + + StaticPropertiesInterface::set_static_attribute(value); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +JSBool staticfcn_staticFunction1( + JSContext* context, uint32_t argc, JS::Value *vp) { + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + + StaticPropertiesInterface::StaticFunction(); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +JSBool staticfcn_staticFunction2( + JSContext* context, uint32_t argc, JS::Value *vp) { + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + const size_t kMinArguments = 1; + if (args.length() < kMinArguments) { + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Not enough arguments."); + return false; + } + // Non-optional arguments + TypeTraits<int32_t >::ConversionType arg; + + DCHECK_LT(0, args.length()); + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg); + if (exception_state.is_exception_set()) { + return false; + } + + StaticPropertiesInterface::StaticFunction(arg); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +JSBool staticfcn_staticFunction3( + JSContext* context, uint32_t argc, JS::Value *vp) { + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + const size_t kMinArguments = 1; + if (args.length() < kMinArguments) { + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Not enough arguments."); + return false; + } + // Non-optional arguments + TypeTraits<std::string >::ConversionType arg; + + DCHECK_LT(0, args.length()); + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg); + if (exception_state.is_exception_set()) { + return false; + } + + StaticPropertiesInterface::StaticFunction(arg); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +JSBool staticfcn_staticFunction4( + JSContext* context, uint32_t argc, JS::Value *vp) { + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + const size_t kMinArguments = 3; + if (args.length() < kMinArguments) { + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Not enough arguments."); + return false; + } + // Non-optional arguments + TypeTraits<int32_t >::ConversionType arg1; + TypeTraits<int32_t >::ConversionType arg2; + TypeTraits<int32_t >::ConversionType arg3; + + DCHECK_LT(0, args.length()); + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg1); + if (exception_state.is_exception_set()) { + return false; + } + + DCHECK_LT(1, args.length()); + JS::RootedValue non_optional_value1( + context, args[1]); + FromJSValue(context, + non_optional_value1, + kNoConversionFlags, + &exception_state, &arg2); + if (exception_state.is_exception_set()) { + return false; + } + + DCHECK_LT(2, args.length()); + JS::RootedValue non_optional_value2( + context, args[2]); + FromJSValue(context, + non_optional_value2, + kNoConversionFlags, + &exception_state, &arg3); + if (exception_state.is_exception_set()) { + return false; + } + + StaticPropertiesInterface::StaticFunction(arg1, arg2, arg3); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +JSBool staticfcn_staticFunction5( + JSContext* context, uint32_t argc, JS::Value *vp) { + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + const size_t kMinArguments = 3; + if (args.length() < kMinArguments) { + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Not enough arguments."); + return false; + } + // Non-optional arguments + TypeTraits<int32_t >::ConversionType arg1; + TypeTraits<int32_t >::ConversionType arg2; + TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType arg3; + + DCHECK_LT(0, args.length()); + JS::RootedValue non_optional_value0( + context, args[0]); + FromJSValue(context, + non_optional_value0, + kNoConversionFlags, + &exception_state, &arg1); + if (exception_state.is_exception_set()) { + return false; + } + + DCHECK_LT(1, args.length()); + JS::RootedValue non_optional_value1( + context, args[1]); + FromJSValue(context, + non_optional_value1, + kNoConversionFlags, + &exception_state, &arg2); + if (exception_state.is_exception_set()) { + return false; + } + + DCHECK_LT(2, args.length()); + JS::RootedValue non_optional_value2( + context, args[2]); + FromJSValue(context, + non_optional_value2, + kNoConversionFlags, + &exception_state, &arg3); + if (exception_state.is_exception_set()) { + return false; + } + + StaticPropertiesInterface::StaticFunction(arg1, arg2, arg3); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} + +JSBool staticfcn_staticFunction( + JSContext* context, uint32_t argc, JS::Value *vp) { + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + switch(argc) { + case(0): { + // Overload resolution algorithm details found here: + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + if (true) { + return staticfcn_staticFunction1( + context, argc, vp); + } + break; + } + case(1): { + // Overload resolution algorithm details found here: + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + JS::RootedValue arg(context, args[0]); + MozjsGlobalObjectProxy* global_object_proxy = + static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_object_proxy->wrapper_factory(); + if (arg.isNumber()) { + return staticfcn_staticFunction2( + context, argc, vp); + } + if (true) { + return staticfcn_staticFunction3( + context, argc, vp); + } + if (true) { + return staticfcn_staticFunction2( + context, argc, vp); + } + break; + } + case(3): { + // Overload resolution algorithm details found here: + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + JS::RootedValue arg(context, args[2]); + MozjsGlobalObjectProxy* global_object_proxy = + static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_object_proxy->wrapper_factory(); + if (arg.isObject() ? wrapper_factory->DoesObjectImplementInterface( + JSVAL_TO_OBJECT(arg), base::GetTypeId<ArbitraryInterface>()) : + false) { + return staticfcn_staticFunction5( + context, argc, vp); + } + if (true) { + return staticfcn_staticFunction4( + context, argc, vp); + } + break; + } + } + // Invalid number of args + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + // 4. If S is empty, then throw a TypeError. + MozjsExceptionState exception_state(context); + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Invalid number of arguments."); + return false; +} + const JSPropertySpec prototype_properties[] = { JS_PS_END @@ -134,9 +461,26 @@ }; const JSPropertySpec interface_object_properties[] = { + { // Static read/write attribute. + "staticAttribute", 0, + JSPROP_SHARED | JSPROP_ENUMERATE, + JSOP_WRAPPER(&staticget_staticAttribute), + JSOP_WRAPPER(&staticset_staticAttribute), + }, JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + { + "staticFunction", + JSOP_WRAPPER(&staticfcn_staticFunction), + 0, + JSPROP_ENUMERATE, + NULL, + }, + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -156,7 +500,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -176,8 +521,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "StaticPropertiesInterface"; - name_value.setString(JS_NewStringCopyZ(context, "StaticPropertiesInterface")); + const char name[] = + "StaticPropertiesInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -186,8 +532,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -219,7 +570,7 @@ } // namespace // static -JSObject* MozjsStaticPropertiesInterface::CreateInstance( +JSObject* MozjsStaticPropertiesInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -227,8 +578,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsStaticPropertiesInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.h index 7e7d06a..db46890 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.h
@@ -38,8 +38,9 @@ class MozjsStaticPropertiesInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.cc index 8a5500a..d77b60e 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -75,6 +84,37 @@ namespace { +class MozjsStringifierAnonymousOperationInterfaceHandler : public ProxyHandler { + public: + MozjsStringifierAnonymousOperationInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsStringifierAnonymousOperationInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsStringifierAnonymousOperationInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsStringifierAnonymousOperationInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -111,7 +151,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "StringifierAnonymousOperationInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -125,11 +166,50 @@ } +JSBool Stringifier(JSContext* context, unsigned argc, JS::Value *vp) { + MozjsExceptionState exception_state(context); + // Compute the 'this' value. + JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); + // 'this' should be an object. + JS::RootedObject object(context); + if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) { + NOTREACHED(); + return false; + } + if (!JS_ValueToObject(context, this_value, object.address())) { + NOTREACHED(); + return false; + } + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + StringifierAnonymousOperationInterface* impl = + wrapper_private->wrappable<StringifierAnonymousOperationInterface>().get(); + if (!impl) { + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Stringifier problem."); + NOTREACHED(); + return false; + } + std::string stringified = impl->AnonymousStringifier(); + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + JS::RootedString rooted_string(context, + JS_NewStringCopyN(context, stringified.c_str(), stringified.length())); + args.rval().set(JS::StringValue(rooted_string)); + return true; +} + const JSPropertySpec prototype_properties[] = { JS_PS_END }; const JSFunctionSpec prototype_functions[] = { + { + "toString", + JSOP_WRAPPER(&Stringifier), + 0, + JSPROP_PERMANENT, + NULL, + }, JS_FS_END }; @@ -137,6 +217,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -156,7 +240,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -176,8 +261,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "StringifierAnonymousOperationInterface"; - name_value.setString(JS_NewStringCopyZ(context, "StringifierAnonymousOperationInterface")); + const char name[] = + "StringifierAnonymousOperationInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -186,8 +272,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -219,7 +310,7 @@ } // namespace // static -JSObject* MozjsStringifierAnonymousOperationInterface::CreateInstance( +JSObject* MozjsStringifierAnonymousOperationInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -227,8 +318,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsStringifierAnonymousOperationInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.h index d2c4c8a..0115c6a 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.h
@@ -38,8 +38,9 @@ class MozjsStringifierAnonymousOperationInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.cc index 8d75bef..d652475 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -75,6 +84,37 @@ namespace { +class MozjsStringifierAttributeInterfaceHandler : public ProxyHandler { + public: + MozjsStringifierAttributeInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsStringifierAttributeInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsStringifierAttributeInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsStringifierAttributeInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -111,7 +151,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "StringifierAttributeInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -129,18 +170,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - StringifierAttributeInterface* impl = - WrapperPrivate::GetWrappable<StringifierAttributeInterface>(object); - TypeTraits<std::string >::ReturnType value = - impl->the_stringifier_attribute(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + StringifierAttributeInterface* impl = + wrapper_private->wrappable<StringifierAttributeInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->the_stringifier_attribute(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_theStringifierAttribute( @@ -148,21 +192,56 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + StringifierAttributeInterface* impl = + wrapper_private->wrappable<StringifierAttributeInterface>().get(); TypeTraits<std::string >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - StringifierAttributeInterface* impl = - WrapperPrivate::GetWrappable<StringifierAttributeInterface>(object); + impl->set_the_stringifier_attribute(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } +JSBool Stringifier(JSContext* context, unsigned argc, JS::Value *vp) { + MozjsExceptionState exception_state(context); + // Compute the 'this' value. + JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); + // 'this' should be an object. + JS::RootedObject object(context); + if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) { + NOTREACHED(); + return false; + } + if (!JS_ValueToObject(context, this_value, object.address())) { + NOTREACHED(); + return false; + } + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + StringifierAttributeInterface* impl = + wrapper_private->wrappable<StringifierAttributeInterface>().get(); + if (!impl) { + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Stringifier problem."); + NOTREACHED(); + return false; + } + std::string stringified = impl->the_stringifier_attribute(); + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + JS::RootedString rooted_string(context, + JS_NewStringCopyN(context, stringified.c_str(), stringified.length())); + args.rval().set(JS::StringValue(rooted_string)); + return true; +} + const JSPropertySpec prototype_properties[] = { { // Read/Write property "theStringifierAttribute", 0, @@ -174,6 +253,13 @@ }; const JSFunctionSpec prototype_functions[] = { + { + "toString", + JSOP_WRAPPER(&Stringifier), + 0, + JSPROP_PERMANENT, + NULL, + }, JS_FS_END }; @@ -181,6 +267,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -200,7 +290,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -220,8 +311,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "StringifierAttributeInterface"; - name_value.setString(JS_NewStringCopyZ(context, "StringifierAttributeInterface")); + const char name[] = + "StringifierAttributeInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -230,8 +322,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -263,7 +360,7 @@ } // namespace // static -JSObject* MozjsStringifierAttributeInterface::CreateInstance( +JSObject* MozjsStringifierAttributeInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -271,8 +368,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsStringifierAttributeInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.h index 8574e32..813ec74 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.h
@@ -38,8 +38,9 @@ class MozjsStringifierAttributeInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.cc index 0f81b4e..30a5d06 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -75,6 +84,37 @@ namespace { +class MozjsStringifierOperationInterfaceHandler : public ProxyHandler { + public: + MozjsStringifierOperationInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsStringifierOperationInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsStringifierOperationInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsStringifierOperationInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -111,7 +151,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "StringifierOperationInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -126,9 +167,7 @@ JSBool fcn_theStringifierOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -141,29 +180,71 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); StringifierOperationInterface* impl = - WrapperPrivate::GetWrappable<StringifierOperationInterface>(object); - TypeTraits<std::string >::ReturnType value = - impl->TheStringifierOperation(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } + wrapper_private->wrappable<StringifierOperationInterface>().get(); - if (!exception_state.IsExceptionSet()) { + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->TheStringifierOperation(), + &result_value); + } + if (!exception_state.is_exception_set()) { args.rval().set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } +JSBool Stringifier(JSContext* context, unsigned argc, JS::Value *vp) { + MozjsExceptionState exception_state(context); + // Compute the 'this' value. + JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); + // 'this' should be an object. + JS::RootedObject object(context); + if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) { + NOTREACHED(); + return false; + } + if (!JS_ValueToObject(context, this_value, object.address())) { + NOTREACHED(); + return false; + } + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + StringifierOperationInterface* impl = + wrapper_private->wrappable<StringifierOperationInterface>().get(); + if (!impl) { + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Stringifier problem."); + NOTREACHED(); + return false; + } + std::string stringified = impl->TheStringifierOperation(); + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + JS::RootedString rooted_string(context, + JS_NewStringCopyN(context, stringified.c_str(), stringified.length())); + args.rval().set(JS::StringValue(rooted_string)); + return true; +} + const JSPropertySpec prototype_properties[] = { JS_PS_END }; const JSFunctionSpec prototype_functions[] = { { + "toString", + JSOP_WRAPPER(&Stringifier), + 0, + JSPROP_PERMANENT, + NULL, + }, + { "theStringifierOperation", JSOP_WRAPPER(&fcn_theStringifierOperation), 0, @@ -177,6 +258,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -196,7 +281,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -216,8 +302,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "StringifierOperationInterface"; - name_value.setString(JS_NewStringCopyZ(context, "StringifierOperationInterface")); + const char name[] = + "StringifierOperationInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -226,8 +313,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -259,7 +351,7 @@ } // namespace // static -JSObject* MozjsStringifierOperationInterface::CreateInstance( +JSObject* MozjsStringifierOperationInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -267,8 +359,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsStringifierOperationInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.h index ce7ac6a..135e07a 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.h
@@ -38,8 +38,9 @@ class MozjsStringifierOperationInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.cc index 011ebc7..b7d73d0 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.cc
@@ -28,14 +28,20 @@ #include "cobalt/script/script_object.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -51,6 +57,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -61,7 +68,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -75,6 +84,37 @@ namespace { +class MozjsTargetInterfaceHandler : public ProxyHandler { + public: + MozjsTargetInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsTargetInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsTargetInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsTargetInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -111,7 +151,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "TargetInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -126,9 +167,7 @@ JSBool fcn_implementedInterfaceFunction( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -141,24 +180,22 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); TargetInterface* impl = - WrapperPrivate::GetWrappable<TargetInterface>(object); + wrapper_private->wrappable<TargetInterface>().get(); + impl->ImplementedInterfaceFunction(); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_partialInterfaceFunction( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -171,17 +208,17 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); TargetInterface* impl = - WrapperPrivate::GetWrappable<TargetInterface>(object); + wrapper_private->wrappable<TargetInterface>().get(); + impl->PartialInterfaceFunction(); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -211,6 +248,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -230,7 +271,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -250,8 +292,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "TargetInterface"; - name_value.setString(JS_NewStringCopyZ(context, "TargetInterface")); + const char name[] = + "TargetInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -260,8 +303,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -293,7 +341,7 @@ } // namespace // static -JSObject* MozjsTargetInterface::CreateInstance( +JSObject* MozjsTargetInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -301,8 +349,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsTargetInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.h index 63f4056..71f1e20 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.h
@@ -38,8 +38,9 @@ class MozjsTargetInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.cc index 1aa4ef7..8d181ac 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.cc
@@ -27,17 +27,25 @@ #include "cobalt/script/opaque_handle.h" #include "cobalt/script/script_object.h" #include "MozjsArbitraryInterface.h" +#include "MozjsBaseInterface.h" #include "cobalt/bindings/testing/arbitrary_interface.h" +#include "cobalt/bindings/testing/base_interface.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -45,7 +53,9 @@ using cobalt::bindings::testing::UnionTypesInterface; using cobalt::bindings::testing::MozjsUnionTypesInterface; using cobalt::bindings::testing::ArbitraryInterface; +using cobalt::bindings::testing::BaseInterface; using cobalt::bindings::testing::MozjsArbitraryInterface; +using cobalt::bindings::testing::MozjsBaseInterface; using cobalt::script::CallbackInterfaceTraits; using cobalt::script::GlobalObjectProxy; using cobalt::script::OpaqueHandle; @@ -55,6 +65,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -65,7 +76,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -79,6 +92,37 @@ namespace { +class MozjsUnionTypesInterfaceHandler : public ProxyHandler { + public: + MozjsUnionTypesInterfaceHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsUnionTypesInterfaceHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsUnionTypesInterfaceHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsUnionTypesInterfaceHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -115,7 +159,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "UnionTypesInterfaceConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -133,18 +178,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - UnionTypesInterface* impl = - WrapperPrivate::GetWrappable<UnionTypesInterface>(object); - TypeTraits<script::UnionType4<std::string, bool, scoped_refptr<ArbitraryInterface>, int32_t > >::ReturnType value = - impl->union_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + UnionTypesInterface* impl = + wrapper_private->wrappable<UnionTypesInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->union_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_unionProperty( @@ -152,18 +200,21 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + UnionTypesInterface* impl = + wrapper_private->wrappable<UnionTypesInterface>().get(); TypeTraits<script::UnionType4<std::string, bool, scoped_refptr<ArbitraryInterface>, int32_t > >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - UnionTypesInterface* impl = - WrapperPrivate::GetWrappable<UnionTypesInterface>(object); + impl->set_union_property(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool get_unionWithNullableMemberProperty( @@ -171,18 +222,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - UnionTypesInterface* impl = - WrapperPrivate::GetWrappable<UnionTypesInterface>(object); - TypeTraits<base::optional<script::UnionType2<double, std::string > > >::ReturnType value = - impl->union_with_nullable_member_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + UnionTypesInterface* impl = + wrapper_private->wrappable<UnionTypesInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->union_with_nullable_member_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_unionWithNullableMemberProperty( @@ -190,18 +244,21 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + UnionTypesInterface* impl = + wrapper_private->wrappable<UnionTypesInterface>().get(); TypeTraits<base::optional<script::UnionType2<double, std::string > > >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - UnionTypesInterface* impl = - WrapperPrivate::GetWrappable<UnionTypesInterface>(object); + impl->set_union_with_nullable_member_property(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool get_nullableUnionProperty( @@ -209,18 +266,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - UnionTypesInterface* impl = - WrapperPrivate::GetWrappable<UnionTypesInterface>(object); - TypeTraits<base::optional<script::UnionType2<double, std::string > > >::ReturnType value = - impl->nullable_union_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + UnionTypesInterface* impl = + wrapper_private->wrappable<UnionTypesInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->nullable_union_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_nullableUnionProperty( @@ -228,18 +288,65 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + UnionTypesInterface* impl = + wrapper_private->wrappable<UnionTypesInterface>().get(); TypeTraits<base::optional<script::UnionType2<double, std::string > > >::ConversionType value; FromJSValue(context, vp, (kConversionFlagNullable), &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - UnionTypesInterface* impl = - WrapperPrivate::GetWrappable<UnionTypesInterface>(object); + impl->set_nullable_union_property(value); result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); +} - return !exception_state.IsExceptionSet(); +JSBool get_unionBaseProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JS::MutableHandleValue vp) { + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + UnionTypesInterface* impl = + wrapper_private->wrappable<UnionTypesInterface>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->union_base_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { + vp.set(result_value); + } + return !exception_state.is_exception_set(); +} + +JSBool set_unionBaseProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JSBool strict, JS::MutableHandleValue vp) { + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + UnionTypesInterface* impl = + wrapper_private->wrappable<UnionTypesInterface>().get(); + TypeTraits<script::UnionType2<scoped_refptr<BaseInterface>, std::string > >::ConversionType value; + FromJSValue(context, vp, kNoConversionFlags, &exception_state, + &value); + if (exception_state.is_exception_set()) { + return false; + } + + impl->set_union_base_property(value); + result_value.set(JS::UndefinedHandleValue); + return !exception_state.is_exception_set(); } @@ -262,6 +369,12 @@ JSOP_WRAPPER(&get_nullableUnionProperty), JSOP_WRAPPER(&set_nullableUnionProperty), }, + { // Read/Write property + "unionBaseProperty", 0, + JSPROP_SHARED | JSPROP_ENUMERATE, + JSOP_WRAPPER(&get_unionBaseProperty), + JSOP_WRAPPER(&set_unionBaseProperty), + }, JS_PS_END }; @@ -273,6 +386,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -292,7 +409,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -312,8 +430,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "UnionTypesInterface"; - name_value.setString(JS_NewStringCopyZ(context, "UnionTypesInterface")); + const char name[] = + "UnionTypesInterface"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -322,8 +441,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -355,7 +479,7 @@ } // namespace // static -JSObject* MozjsUnionTypesInterface::CreateInstance( +JSObject* MozjsUnionTypesInterface::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -363,8 +487,19 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} + +//static +const JSClass* MozjsUnionTypesInterface::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.h index 1465336..eba6b2f 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.h
@@ -38,8 +38,9 @@ class MozjsUnionTypesInterface { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.cc index f0e09c3..b626b88 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.cc
@@ -116,14 +116,20 @@ #include "cobalt/bindings/testing/window.h" #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" @@ -235,6 +241,7 @@ using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -245,7 +252,9 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; @@ -259,6 +268,37 @@ namespace { +class MozjsWindowHandler : public ProxyHandler { + public: + MozjsWindowHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +MozjsWindowHandler::named_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; +ProxyHandler::IndexedPropertyHooks +MozjsWindowHandler::indexed_property_hooks = { + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +static base::LazyInstance<MozjsWindowHandler> + proxy_handler; + + InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); memset(&interface_data->instance_class_definition, 0, @@ -295,7 +335,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "WindowConstructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -313,18 +354,21 @@ JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - Window* impl = - WrapperPrivate::GetWrappable<Window>(object); - TypeTraits<std::string >::ReturnType value = - impl->window_property(); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); - } - if (!exception_state.IsExceptionSet()) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + Window* impl = + wrapper_private->wrappable<Window>().get(); + + if (!exception_state.is_exception_set()) { + ToJSValue(context, + impl->window_property(), + &result_value); + } + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool set_windowProperty( @@ -332,25 +376,26 @@ JSBool strict, JS::MutableHandleValue vp) { MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); + + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + Window* impl = + wrapper_private->wrappable<Window>().get(); TypeTraits<std::string >::ConversionType value; FromJSValue(context, vp, kNoConversionFlags, &exception_state, &value); - if (exception_state.IsExceptionSet()) { + if (exception_state.is_exception_set()) { return false; } - Window* impl = - WrapperPrivate::GetWrappable<Window>(object); + impl->set_window_property(value); result_value.set(JS::UndefinedHandleValue); - - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } JSBool fcn_windowOperation( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -363,17 +408,17 @@ NOTREACHED(); return false; } + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); Window* impl = - WrapperPrivate::GetWrappable<Window>(object); + wrapper_private->wrappable<Window>().get(); + impl->WindowOperation(); result_value.set(JS::UndefinedHandleValue); - - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } @@ -402,6 +447,10 @@ JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { + JS_FS_END +}; + const JSPropertySpec own_properties[] = { JS_PS_END }; @@ -421,7 +470,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -441,8 +491,9 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "Window"; - name_value.setString(JS_NewStringCopyZ(context, "Window")); + const char name[] = + "Window"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, @@ -451,8 +502,13 @@ // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -483,7 +539,7 @@ } // namespace -JSObject* MozjsWindow::CreateInstance( +JSObject* MozjsWindow::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject global_object( @@ -514,9 +570,19 @@ success = JS_DefineProperties(context, global_object, own_properties); DCHECK(success); - WrapperPrivate::AddPrivateData(global_object, wrappable); + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, global_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; +} - return global_object; +//static +const JSClass* MozjsWindow::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; } // static @@ -559,141 +625,183 @@ JSContext* context = mozjs_global_object_proxy->context(); JSAutoRequest auto_request(context); - MozjsWindow::CreateInstance( + MozjsWindow::CreateProxy( context, global_interface); mozjs_global_object_proxy->SetEnvironmentSettings(environment_settings); WrapperFactory* wrapper_factory = mozjs_global_object_proxy->wrapper_factory(); wrapper_factory->RegisterWrappableType( AnonymousIndexedGetterInterface::AnonymousIndexedGetterInterfaceWrappableType(), - base::Bind(MozjsAnonymousIndexedGetterInterface::CreateInstance)); + base::Bind(MozjsAnonymousIndexedGetterInterface::CreateProxy), + base::Bind(MozjsAnonymousIndexedGetterInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( AnonymousNamedGetterInterface::AnonymousNamedGetterInterfaceWrappableType(), - base::Bind(MozjsAnonymousNamedGetterInterface::CreateInstance)); + base::Bind(MozjsAnonymousNamedGetterInterface::CreateProxy), + base::Bind(MozjsAnonymousNamedGetterInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( AnonymousNamedIndexedGetterInterface::AnonymousNamedIndexedGetterInterfaceWrappableType(), - base::Bind(MozjsAnonymousNamedIndexedGetterInterface::CreateInstance)); + base::Bind(MozjsAnonymousNamedIndexedGetterInterface::CreateProxy), + base::Bind(MozjsAnonymousNamedIndexedGetterInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( ArbitraryInterface::ArbitraryInterfaceWrappableType(), - base::Bind(MozjsArbitraryInterface::CreateInstance)); + base::Bind(MozjsArbitraryInterface::CreateProxy), + base::Bind(MozjsArbitraryInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( BaseInterface::BaseInterfaceWrappableType(), - base::Bind(MozjsBaseInterface::CreateInstance)); + base::Bind(MozjsBaseInterface::CreateProxy), + base::Bind(MozjsBaseInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( BooleanTypeTestInterface::BooleanTypeTestInterfaceWrappableType(), - base::Bind(MozjsBooleanTypeTestInterface::CreateInstance)); + base::Bind(MozjsBooleanTypeTestInterface::CreateProxy), + base::Bind(MozjsBooleanTypeTestInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( CallbackFunctionInterface::CallbackFunctionInterfaceWrappableType(), - base::Bind(MozjsCallbackFunctionInterface::CreateInstance)); + base::Bind(MozjsCallbackFunctionInterface::CreateProxy), + base::Bind(MozjsCallbackFunctionInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( CallbackInterfaceInterface::CallbackInterfaceInterfaceWrappableType(), - base::Bind(MozjsCallbackInterfaceInterface::CreateInstance)); + base::Bind(MozjsCallbackInterfaceInterface::CreateProxy), + base::Bind(MozjsCallbackInterfaceInterface::PrototypeClass)); #if defined(ENABLE_CONDITIONAL_INTERFACE) wrapper_factory->RegisterWrappableType( ConditionalInterface::ConditionalInterfaceWrappableType(), - base::Bind(MozjsConditionalInterface::CreateInstance)); + base::Bind(MozjsConditionalInterface::CreateProxy), + base::Bind(MozjsConditionalInterface::PrototypeClass)); #endif // defined(ENABLE_CONDITIONAL_INTERFACE) wrapper_factory->RegisterWrappableType( ConstantsInterface::ConstantsInterfaceWrappableType(), - base::Bind(MozjsConstantsInterface::CreateInstance)); + base::Bind(MozjsConstantsInterface::CreateProxy), + base::Bind(MozjsConstantsInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( ConstructorInterface::ConstructorInterfaceWrappableType(), - base::Bind(MozjsConstructorInterface::CreateInstance)); + base::Bind(MozjsConstructorInterface::CreateProxy), + base::Bind(MozjsConstructorInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( ConstructorWithArgumentsInterface::ConstructorWithArgumentsInterfaceWrappableType(), - base::Bind(MozjsConstructorWithArgumentsInterface::CreateInstance)); + base::Bind(MozjsConstructorWithArgumentsInterface::CreateProxy), + base::Bind(MozjsConstructorWithArgumentsInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( DOMStringTestInterface::DOMStringTestInterfaceWrappableType(), - base::Bind(MozjsDOMStringTestInterface::CreateInstance)); + base::Bind(MozjsDOMStringTestInterface::CreateProxy), + base::Bind(MozjsDOMStringTestInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( DerivedGetterSetterInterface::DerivedGetterSetterInterfaceWrappableType(), - base::Bind(MozjsDerivedGetterSetterInterface::CreateInstance)); + base::Bind(MozjsDerivedGetterSetterInterface::CreateProxy), + base::Bind(MozjsDerivedGetterSetterInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( DerivedInterface::DerivedInterfaceWrappableType(), - base::Bind(MozjsDerivedInterface::CreateInstance)); + base::Bind(MozjsDerivedInterface::CreateProxy), + base::Bind(MozjsDerivedInterface::PrototypeClass)); #if defined(NO_ENABLE_CONDITIONAL_INTERFACE) wrapper_factory->RegisterWrappableType( DisabledInterface::DisabledInterfaceWrappableType(), - base::Bind(MozjsDisabledInterface::CreateInstance)); + base::Bind(MozjsDisabledInterface::CreateProxy), + base::Bind(MozjsDisabledInterface::PrototypeClass)); #endif // defined(NO_ENABLE_CONDITIONAL_INTERFACE) wrapper_factory->RegisterWrappableType( EnumerationInterface::EnumerationInterfaceWrappableType(), - base::Bind(MozjsEnumerationInterface::CreateInstance)); + base::Bind(MozjsEnumerationInterface::CreateProxy), + base::Bind(MozjsEnumerationInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( ExceptionObjectInterface::ExceptionObjectInterfaceWrappableType(), - base::Bind(MozjsExceptionObjectInterface::CreateInstance)); + base::Bind(MozjsExceptionObjectInterface::CreateProxy), + base::Bind(MozjsExceptionObjectInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( ExceptionsInterface::ExceptionsInterfaceWrappableType(), - base::Bind(MozjsExceptionsInterface::CreateInstance)); + base::Bind(MozjsExceptionsInterface::CreateProxy), + base::Bind(MozjsExceptionsInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( ExtendedIDLAttributesInterface::ExtendedIDLAttributesInterfaceWrappableType(), - base::Bind(MozjsExtendedIDLAttributesInterface::CreateInstance)); + base::Bind(MozjsExtendedIDLAttributesInterface::CreateProxy), + base::Bind(MozjsExtendedIDLAttributesInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( GetOpaqueRootInterface::GetOpaqueRootInterfaceWrappableType(), - base::Bind(MozjsGetOpaqueRootInterface::CreateInstance)); + base::Bind(MozjsGetOpaqueRootInterface::CreateProxy), + base::Bind(MozjsGetOpaqueRootInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( GlobalInterfaceParent::GlobalInterfaceParentWrappableType(), - base::Bind(MozjsGlobalInterfaceParent::CreateInstance)); + base::Bind(MozjsGlobalInterfaceParent::CreateProxy), + base::Bind(MozjsGlobalInterfaceParent::PrototypeClass)); wrapper_factory->RegisterWrappableType( ImplementedInterface::ImplementedInterfaceWrappableType(), - base::Bind(MozjsImplementedInterface::CreateInstance)); + base::Bind(MozjsImplementedInterface::CreateProxy), + base::Bind(MozjsImplementedInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( IndexedGetterInterface::IndexedGetterInterfaceWrappableType(), - base::Bind(MozjsIndexedGetterInterface::CreateInstance)); + base::Bind(MozjsIndexedGetterInterface::CreateProxy), + base::Bind(MozjsIndexedGetterInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( InterfaceWithUnsupportedProperties::InterfaceWithUnsupportedPropertiesWrappableType(), - base::Bind(MozjsInterfaceWithUnsupportedProperties::CreateInstance)); + base::Bind(MozjsInterfaceWithUnsupportedProperties::CreateProxy), + base::Bind(MozjsInterfaceWithUnsupportedProperties::PrototypeClass)); wrapper_factory->RegisterWrappableType( NamedConstructorInterface::NamedConstructorInterfaceWrappableType(), - base::Bind(MozjsNamedConstructorInterface::CreateInstance)); + base::Bind(MozjsNamedConstructorInterface::CreateProxy), + base::Bind(MozjsNamedConstructorInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( NamedGetterInterface::NamedGetterInterfaceWrappableType(), - base::Bind(MozjsNamedGetterInterface::CreateInstance)); + base::Bind(MozjsNamedGetterInterface::CreateProxy), + base::Bind(MozjsNamedGetterInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( NamedIndexedGetterInterface::NamedIndexedGetterInterfaceWrappableType(), - base::Bind(MozjsNamedIndexedGetterInterface::CreateInstance)); + base::Bind(MozjsNamedIndexedGetterInterface::CreateProxy), + base::Bind(MozjsNamedIndexedGetterInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( NestedPutForwardsInterface::NestedPutForwardsInterfaceWrappableType(), - base::Bind(MozjsNestedPutForwardsInterface::CreateInstance)); + base::Bind(MozjsNestedPutForwardsInterface::CreateProxy), + base::Bind(MozjsNestedPutForwardsInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( NoConstructorInterface::NoConstructorInterfaceWrappableType(), - base::Bind(MozjsNoConstructorInterface::CreateInstance)); + base::Bind(MozjsNoConstructorInterface::CreateProxy), + base::Bind(MozjsNoConstructorInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( NoInterfaceObjectInterface::NoInterfaceObjectInterfaceWrappableType(), - base::Bind(MozjsNoInterfaceObjectInterface::CreateInstance)); + base::Bind(MozjsNoInterfaceObjectInterface::CreateProxy), + base::Bind(MozjsNoInterfaceObjectInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( NullableTypesTestInterface::NullableTypesTestInterfaceWrappableType(), - base::Bind(MozjsNullableTypesTestInterface::CreateInstance)); + base::Bind(MozjsNullableTypesTestInterface::CreateProxy), + base::Bind(MozjsNullableTypesTestInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( NumericTypesTestInterface::NumericTypesTestInterfaceWrappableType(), - base::Bind(MozjsNumericTypesTestInterface::CreateInstance)); + base::Bind(MozjsNumericTypesTestInterface::CreateProxy), + base::Bind(MozjsNumericTypesTestInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( ObjectTypeBindingsInterface::ObjectTypeBindingsInterfaceWrappableType(), - base::Bind(MozjsObjectTypeBindingsInterface::CreateInstance)); + base::Bind(MozjsObjectTypeBindingsInterface::CreateProxy), + base::Bind(MozjsObjectTypeBindingsInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( OperationsTestInterface::OperationsTestInterfaceWrappableType(), - base::Bind(MozjsOperationsTestInterface::CreateInstance)); + base::Bind(MozjsOperationsTestInterface::CreateProxy), + base::Bind(MozjsOperationsTestInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( PutForwardsInterface::PutForwardsInterfaceWrappableType(), - base::Bind(MozjsPutForwardsInterface::CreateInstance)); + base::Bind(MozjsPutForwardsInterface::CreateProxy), + base::Bind(MozjsPutForwardsInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( StaticPropertiesInterface::StaticPropertiesInterfaceWrappableType(), - base::Bind(MozjsStaticPropertiesInterface::CreateInstance)); + base::Bind(MozjsStaticPropertiesInterface::CreateProxy), + base::Bind(MozjsStaticPropertiesInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( StringifierAnonymousOperationInterface::StringifierAnonymousOperationInterfaceWrappableType(), - base::Bind(MozjsStringifierAnonymousOperationInterface::CreateInstance)); + base::Bind(MozjsStringifierAnonymousOperationInterface::CreateProxy), + base::Bind(MozjsStringifierAnonymousOperationInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( StringifierAttributeInterface::StringifierAttributeInterfaceWrappableType(), - base::Bind(MozjsStringifierAttributeInterface::CreateInstance)); + base::Bind(MozjsStringifierAttributeInterface::CreateProxy), + base::Bind(MozjsStringifierAttributeInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( StringifierOperationInterface::StringifierOperationInterfaceWrappableType(), - base::Bind(MozjsStringifierOperationInterface::CreateInstance)); + base::Bind(MozjsStringifierOperationInterface::CreateProxy), + base::Bind(MozjsStringifierOperationInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( TargetInterface::TargetInterfaceWrappableType(), - base::Bind(MozjsTargetInterface::CreateInstance)); + base::Bind(MozjsTargetInterface::CreateProxy), + base::Bind(MozjsTargetInterface::PrototypeClass)); wrapper_factory->RegisterWrappableType( UnionTypesInterface::UnionTypesInterfaceWrappableType(), - base::Bind(MozjsUnionTypesInterface::CreateInstance)); + base::Bind(MozjsUnionTypesInterface::CreateProxy), + base::Bind(MozjsUnionTypesInterface::PrototypeClass)); }
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.h index 3052819..c7e508c 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.h +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.h
@@ -39,8 +39,9 @@ class MozjsWindow { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); static JSObject* GetInterfaceObject(JSContext* context); };
diff --git a/src/cobalt/bindings/mozjs/code_generator.py b/src/cobalt/bindings/mozjs/code_generator.py index 806357d..12ac5fb 100644 --- a/src/cobalt/bindings/mozjs/code_generator.py +++ b/src/cobalt/bindings/mozjs/code_generator.py
@@ -34,16 +34,19 @@ """Implementation of ExpressionGenerator for JavaScriptCore.""" def is_undefined(self, arg): - return 'false' + return '%s.isUndefined()' % arg def is_undefined_or_null(self, arg): - return 'false' + return '%s.isNullOrUndefined()' % arg def inherits_interface(self, interface_name, arg): - return 'false' + return ('%s.isObject() ?' + ' wrapper_factory->DoesObjectImplementInterface(\n' + ' JSVAL_TO_OBJECT(%s), base::GetTypeId<%s>()) :\n' + ' false') % (arg, arg, interface_name) def is_number(self, arg): - return 'false' + return '%s.isNumber()' % arg class CodeGeneratorMozjs(CodeGeneratorCobalt):
diff --git a/src/cobalt/bindings/mozjs/templates/callback-interface.cc.template b/src/cobalt/bindings/mozjs/templates/callback-interface.cc.template index ebbf9f6..421cddb 100644 --- a/src/cobalt/bindings/mozjs/templates/callback-interface.cc.template +++ b/src/cobalt/bindings/mozjs/templates/callback-interface.cc.template
@@ -14,3 +14,96 @@ # limitations under the License. #} {% extends "callback-interface-base.cc.template" %} + +{% block includes %} +{{ super() }} +#include "cobalt/script/logging_exception_state.h" +#include "cobalt/script/mozjs/conversion_helpers.h" +#include "cobalt/script/mozjs/mozjs_callback_interface.h" +#include "third_party/mozjs/js/src/jsapi.h" +#include "third_party/mozjs/js/src/jscntxt.h" +{% endblock includes %} + +{% block using_directives %} +{{ super() }} +using cobalt::script::LoggingExceptionState; +using cobalt::script::mozjs::FromJSValue; +using cobalt::script::mozjs::GetCallableForCallbackInterface; +using cobalt::script::mozjs::ToJSValue; +{% endblock using_directives %} + +{% block implementation %} +namespace cobalt { +{% for component in components %} +namespace {{component}} { +{% endfor %} + +{{binding_class}}::{{binding_class}}( + JSContext* context, + JS::HandleObject implementing_object) + : context_(context), + implementing_object_(implementing_object) { } + +{% for operation in operations %} +{% for overload in operation.overloads %} +{{overload.type}} {{binding_class}}::{{overload.name}}( + const scoped_refptr<script::Wrappable>& callback_this, + {% for arg in overload.arguments %} + {{arg.arg_type}} {{arg.name}}, + {% endfor %} + bool* had_exception) const { + JSAutoRequest auto_request(context_); + JSAutoCompartment auto_compartment(context_, implementing_object_); + + bool success = false; +{% if overload.type != 'void' %} + {{overload.type}} cobalt_return_value; +{% endif %} + // Get callable object. + JS::RootedValue callable(context_); + if (GetCallableForCallbackInterface(context_, implementing_object_, + "{{overload.idl_name}}", &callable)) { + // Convert the callback_this to a JSValue. + JS::RootedValue this_value(context_); + ToJSValue(context_, callback_this, &this_value); + + // Convert arguments. + const int kNumArguments = {{overload.arguments|length}}; + JS::Value args[kNumArguments]; + js::SetValueRangeToNull(args, kNumArguments); + js::AutoValueArray auto_array_rooter(context_, args, kNumArguments); + {% for arg in overload.arguments %} + ToJSValue(context_, {{arg.name}}, + auto_array_rooter.handleAt({{loop.index0}})); + {% endfor %} + + // Call the function. + JS::RootedValue return_value(context_); + JSFunction* function = JS_ValueToFunction(context_, callable); + DCHECK(function); + success = JS::Call(context_, this_value, function, kNumArguments, args, + return_value.address()); + DLOG_IF(WARNING, !success) << "Exception in callback."; +{% if overload.type != 'void' %} + if (success) { + LoggingExceptionState exception_state; + FromJSValue(context_, return_value, 0, &exception_state, + &cobalt_return_value); + success = !exception_state.is_exception_set(); + } +{% endif %} + } + + *had_exception = !success; +{% if overload.type != 'void' %} + return cobalt_return_value; +{% endif %} +} +{% endfor %} +{% endfor %} + +{% for component in components %} +} // namespace {{component}} +{% endfor %} +} // namespace cobalt +{% endblock implementation %}
diff --git a/src/cobalt/bindings/mozjs/templates/callback-interface.h.template b/src/cobalt/bindings/mozjs/templates/callback-interface.h.template index 8718b2e..1cfeb00 100644 --- a/src/cobalt/bindings/mozjs/templates/callback-interface.h.template +++ b/src/cobalt/bindings/mozjs/templates/callback-interface.h.template
@@ -15,13 +15,39 @@ #} {% extends "callback-interface-base.h.template" %} +{% block includes %} +{{ super() }} +#include "third_party/mozjs/js/src/jsapi.h" +{% endblock includes %} + {% block implementation %} namespace cobalt { {% for component in components %} namespace {{component}} { {% endfor %} -class {{binding_class}} { }; +class {{binding_class}} : public {{impl_class}} { + public: + typedef {{impl_class}} BaseType; + + {{binding_class}}( + JSContext* context, JS::HandleObject implementing_object); +{% for operation in operations %} +{% for overload in operation.overloads %} + {{overload.type}} {{overload.name}}( + const scoped_refptr<script::Wrappable>& callback_this, + {% for arg in overload.arguments %} + {{arg.arg_type}} {{arg.name}}, + {% endfor %} + bool* had_exception) const OVERRIDE; +{% endfor %} +{% endfor %} + JSObject* handle() const { return implementing_object_; } + + private: + JSContext* context_; + JS::Heap<JSObject*> implementing_object_; +}; {% for component in components %} } // namespace {{component}}
diff --git a/src/cobalt/bindings/mozjs/templates/interface.cc.template b/src/cobalt/bindings/mozjs/templates/interface.cc.template index d74a60d..ad65ba4 100644 --- a/src/cobalt/bindings/mozjs/templates/interface.cc.template +++ b/src/cobalt/bindings/mozjs/templates/interface.cc.template
@@ -13,19 +13,33 @@ # See the License for the specific language governing permissions and # limitations under the License. #} +{% from 'macros.cc.template' import add_extra_arguments %} {% from 'macros.cc.template' import call_cobalt_function %} +{% from 'macros.cc.template' import constructor_implementation with context %} +{% from 'macros.cc.template' import function_implementation with context %} +{% from 'macros.cc.template' import get_impl_class_instance %} +{% from 'macros.cc.template' import nonstatic_function_prologue %} +{% from 'macros.cc.template' import overload_resolution_implementation with context %} +{% from 'macros.cc.template' import set_attribute_implementation with context %} +{% from 'macros.cc.template' import static_function_prologue %} {% extends "interface-base.cc.template" %} {% block includes %} {{ super() }} #include "base/lazy_instance.h" +#include "cobalt/script/mozjs/callback_function_conversion.h" +#include "cobalt/script/exception_state.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_callback_function.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/proxy_handler.h" #include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/property_enumerator.h" #include "third_party/mozjs/js/src/jsapi.h" #include "third_party/mozjs/js/src/jsfriendapi.h" {% endblock includes %} @@ -33,6 +47,7 @@ {{ super() }} using cobalt::script::CallbackFunction; using cobalt::script::CallbackInterfaceTraits; +using cobalt::script::ExceptionState; using cobalt::script::mozjs::FromJSValue; using cobalt::script::mozjs::kConversionFlagNullable; using cobalt::script::mozjs::kConversionFlagRestricted; @@ -43,16 +58,243 @@ using cobalt::script::mozjs::MozjsCallbackFunction; using cobalt::script::mozjs::MozjsExceptionState; using cobalt::script::mozjs::MozjsGlobalObjectProxy; -using cobalt::script::mozjs::MozjsObjectHandleHolder; +using cobalt::script::mozjs::MozjsUserObjectHolder; +using cobalt::script::mozjs::MozjsPropertyEnumerator; +using cobalt::script::mozjs::ProxyHandler; using cobalt::script::mozjs::ToJSValue; using cobalt::script::mozjs::TypeTraits; using cobalt::script::mozjs::WrapperPrivate; using cobalt::script::mozjs::WrapperFactory; using cobalt::script::Wrappable; {% endblock using_directives %} +{% block enumeration_declarations %} +{% if enumerations|length %} +// Declare and define these in the same namespace that the other overloads +// were brought into with the using declaration. +{% for enumeration in enumerations %} +void ToJSValue( + JSContext* context, + {{impl_class}}::{{enumeration.name}} in_enum, + JS::MutableHandleValue out_value); +void FromJSValue(JSContext* context, JS::HandleValue value, + int conversion_flags, ExceptionState* exception_state, + {{impl_class}}::{{enumeration.name}}* out_enum); +{% endfor %} +{% endif %} +{% endblock enumeration_declarations %} {% block implementation %} namespace { + +{% if named_property_getter %} +bool IsSupportedNamedProperty(JSContext* context, JS::HandleObject object, + const std::string& property_name) { +{{ get_impl_class_instance(impl_class) }} + return impl->CanQueryNamedProperty(property_name); +} + +void EnumerateSupportedNames(JSContext* context, JS::HandleObject object, + JS::AutoIdVector* properties) { +{{ get_impl_class_instance(impl_class) }} + MozjsPropertyEnumerator enumerator(context, properties); + impl->EnumerateNamedProperties(&enumerator); +} + +JSBool GetNamedProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JS::MutableHandleValue vp) { + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } +{{ nonstatic_function_prologue(impl_class) }} + std::string property_name; + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, + &property_name); + if(exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } +{{ call_cobalt_function(impl_class, named_property_getter.type, + named_property_getter.name, ["property_name"], + named_property_getter.raises_exception, + named_property_getter.call_with) }} + if (!exception_state.is_exception_set()) { + vp.set(result_value); + } + return !exception_state.is_exception_set(); +} + +{% endif %} +{% if named_property_setter %} +JSBool SetNamedProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JSBool strict, JS::MutableHandleValue vp) { + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } +{{ nonstatic_function_prologue(impl_class) }} + std::string property_name; + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, + &property_name); + if(exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } + TypeTraits<{{named_property_setter.type}} >::ConversionType value; + FromJSValue(context, vp, {{named_property_setter.conversion_flags}}, + &exception_state, &value); + if (exception_state.is_exception_set()) { + return false; + } +{{ call_cobalt_function(impl_class, "void", + named_property_setter.name, ["property_name", "value"], + named_property_setter.raises_exception, + named_property_setter.call_with) }} + return !exception_state.is_exception_set(); +} + +{% endif %} +{% if named_property_deleter %} +bool DeleteNamedProperty(JSContext* context, JS::HandleObject object, + const std::string& property_name) { +{{ nonstatic_function_prologue(impl_class) }} +{{ call_cobalt_function(impl_class, "void", + named_property_deleter.name, ["property_name"], + named_property_deleter.raises_exception, + named_property_deleter.call_with) }} + return !exception_state.is_exception_set(); +} + +{% endif %} +{% if indexed_property_getter %} +bool IsSupportedIndexProperty(JSContext* context, JS::HandleObject object, + uint32_t index) { +{{ get_impl_class_instance(impl_class) }} + return index < impl->length(); +} + +void EnumerateSupportedIndexes(JSContext* context, JS::HandleObject object, + JS::AutoIdVector* properties) { +{{ get_impl_class_instance(impl_class) }} + const uint32_t kNumIndexedProperties = impl->length(); + for (uint32_t i = 0; i < kNumIndexedProperties; ++i) { + properties->append(INT_TO_JSID(i)); + } +} + +JSBool GetIndexedProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JS::MutableHandleValue vp) { + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } +{{ nonstatic_function_prologue(impl_class) }} + uint32_t index; + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, &index); + if(exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } +{{ call_cobalt_function(impl_class, indexed_property_getter.type, + indexed_property_getter.name, ["index"], + indexed_property_getter.raises_exception, + indexed_property_getter.call_with) }} + if (!exception_state.is_exception_set()) { + vp.set(result_value); + } + return !exception_state.is_exception_set(); +} + +{% endif %} +{% if indexed_property_setter %} +JSBool SetIndexedProperty( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JSBool strict, JS::MutableHandleValue vp) { + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } +{{ nonstatic_function_prologue(impl_class) }} + uint32_t index; + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, &index); + if(exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } + TypeTraits<{{indexed_property_setter.type}} >::ConversionType value; + FromJSValue(context, vp, {{indexed_property_setter.conversion_flags}}, + &exception_state, &value); + if (exception_state.is_exception_set()) { + return false; + } +{{ call_cobalt_function(impl_class, "void", + indexed_property_setter.name, ["index", "value"], + indexed_property_setter.raises_exception, + indexed_property_setter.call_with) }} + return !exception_state.is_exception_set(); +} + +{% endif %} +{% if indexed_property_deleter %} +bool DeleteIndexedProperty( + JSContext* context, JS::HandleObject object, uint32_t index) { +{{ nonstatic_function_prologue(impl_class) }} +{{ call_cobalt_function(impl_class, "void", + indexed_property_deleter.name, ["index"], + indexed_property_deleter.raises_exception, + indexed_property_deleter.call_with) }} + return !exception_state.is_exception_set(); +} + +{% endif %} +class {{binding_class}}Handler : public ProxyHandler { + public: + {{binding_class}}Handler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks +{{binding_class}}Handler::named_property_hooks = { + {{ "IsSupportedNamedProperty" if named_property_getter else "NULL" }}, + {{ "EnumerateSupportedNames" if named_property_getter else "NULL" }}, + {{ "GetNamedProperty" if named_property_getter else "NULL" }}, + {{ "SetNamedProperty" if named_property_setter else "NULL" }}, + {{ "DeleteNamedProperty" if named_property_deleter else "NULL" }}, +}; +ProxyHandler::IndexedPropertyHooks +{{binding_class}}Handler::indexed_property_hooks = { + {{ "IsSupportedIndexProperty" if indexed_property_getter else "NULL" }}, + {{ "EnumerateSupportedIndexes" if indexed_property_getter else "NULL" }}, + {{ "GetIndexedProperty" if indexed_property_getter else "NULL" }}, + {{ "SetIndexedProperty" if indexed_property_setter else "NULL" }}, + {{ "DeleteIndexedProperty" if indexed_property_deleter else "NULL" }}, +}; + +static base::LazyInstance<{{binding_class}}Handler> + proxy_handler; + +{% if constructor %} +JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp); +{% endif %} {% for constant in constants %} JSBool get_{{constant.idl_name}}( JSContext* context, JS::HandleObject object, JS::HandleId id, @@ -67,17 +309,14 @@ {% endif %} MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); - ToJSValue(context, {{constant.value}}, &exception_state, &result_value); - if (!exception_state.IsExceptionSet()) { - vp.set(result_value); + ToJSValue(context, {{constant.value}}, &result_value); + if (!exception_state.is_exception_set()) { + vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } {% endfor %} -{% if constructor %} -JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args); -{% endif %} InterfaceData* CreateCachedInterfaceData() { InterfaceData* interface_data = new InterfaceData(); @@ -89,7 +328,8 @@ sizeof(interface_data->interface_object_class_definition)); JSClass* instance_class = &interface_data->instance_class_definition; - const int kGlobalFlags = {{"JSCLASS_GLOBAL_FLAGS" if is_global_interface else 0 }}; + const int kGlobalFlags = {{ + "JSCLASS_GLOBAL_FLAGS" if is_global_interface else 0 }}; instance_class->name = "{{interface_name}}"; instance_class->flags = kGlobalFlags | JSCLASS_HAS_PRIVATE; instance_class->addProperty = JS_PropertyStub; @@ -115,7 +355,8 @@ prototype_class->resolve = JS_ResolveStub; prototype_class->convert = JS_ConvertStub; - JSClass* interface_object_class = &interface_data->interface_object_class_definition; + JSClass* interface_object_class = + &interface_data->interface_object_class_definition; interface_object_class->name = "{{interface_name}}Constructor"; interface_object_class->flags = 0; interface_object_class->addProperty = JS_PropertyStub; @@ -131,7 +372,7 @@ return interface_data; } -{% for attribute in attributes %} +{% for attribute in attributes + static_attributes %} {% if attribute.conditional %} #if defined({{attribute.conditional}}) {% endif %} @@ -146,57 +387,78 @@ } {% else %} +{% if attribute.is_static %} +JSBool staticget_{{attribute.idl_name}}( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JS::MutableHandleValue vp) { +{{ static_function_prologue() -}} +{% else %} JSBool get_{{attribute.idl_name}}( JSContext* context, JS::HandleObject object, JS::HandleId id, JS::MutableHandleValue vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); +{{ nonstatic_function_prologue(impl_class) }} +{% endif %} {{ call_cobalt_function(impl_class, attribute.type, attribute.getter_function_name, [], - attribute.raises_exception, attribute.call_with) }} - if (!exception_state.IsExceptionSet()) { + attribute.raises_exception, attribute.call_with, + attribute.is_static) }} + if (!exception_state.is_exception_set()) { vp.set(result_value); } - return !exception_state.IsExceptionSet(); + return !exception_state.is_exception_set(); } {% if attribute.has_setter %} +{% if attribute.is_static %} +JSBool staticset_{{attribute.idl_name}}( + JSContext* context, JS::HandleObject object, JS::HandleId id, + JSBool strict, JS::MutableHandleValue vp) { +{{ static_function_prologue() }} +{% else %} JSBool set_{{attribute.idl_name}}( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); - TypeTraits<{{attribute.type}} >::ConversionType value; - FromJSValue(context, vp, {{attribute.conversion_flags}}, &exception_state, - &value); - if (exception_state.IsExceptionSet()) { - return false; - } -{% if attribute.put_forwards %} - NOTIMPLEMENTED(); -{% else %} -{{ call_cobalt_function(impl_class, "void", attribute.setter_function_name, - ["value"], attribute.raises_exception, attribute.call_with) }} -{% endif %} - return !exception_state.IsExceptionSet(); +{{ nonstatic_function_prologue(impl_class)}} +{% endif %} {#- attribute.is_static #} +{{ set_attribute_implementation(attribute, impl_class) -}} } -{% endif %} +{% endif %} {#- attribute.has_setter #} {% endif %} {% if attribute.conditional %} #endif // {{attribute.conditional}} -{% endif %} +{% endif %} {#- attribute.is_constructor_attribute #} {% endfor %} - -{%- for operation in operations %} +{%- for operation in operations + static_operations %} {% if operation.conditional %} #if defined({{operation.conditional}}) {% endif %} -JSBool fcn_{{operation.idl_name}}( +{% set boundFunctionPrefix = "staticfcn_" if operation.is_static else "fcn_" %} +{% for overload in operation.overloads if operation.overloads|length > 1 %} +JSBool {{boundFunctionPrefix}}{{operation.idl_name}}{{overload.overload_index}}( JSContext* context, uint32_t argc, JS::Value *vp) { - MozjsExceptionState exception_state(context); - JS::RootedValue result_value(context); +{{ function_implementation(overload) -}} +} +{% endfor %} +JSBool {{boundFunctionPrefix}}{{operation.idl_name}}( + JSContext* context, uint32_t argc, JS::Value *vp) { +{% if operation.overloads|length == 1 %} +{{ function_implementation(operation.overloads[0]) -}} +{% else %} +{{ overload_resolution_implementation( + operation, boundFunctionPrefix + operation.idl_name) }} +{% endif %} +} + +{% if operation.conditional %} +#endif // {{operation.conditional}} +{% endif %} +{% endfor %} + +{% if stringifier %} +JSBool Stringifier(JSContext* context, unsigned argc, JS::Value *vp) { + MozjsExceptionState exception_state(context); // Compute the 'this' value. JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); // 'this' should be an object. @@ -209,51 +471,25 @@ NOTREACHED(); return false; } - - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); -{# TODO: Overload resolution. Just use first overload for now. #} -{% set overload = operation.overloads[0] %} -{# TODO: Optional and variadic arguments. #} -{% if overload.arguments|selectattr('is_optional')|selectattr('is_variadic')|list|length == 0 %} -{% if overload.arguments|length > 0 %} - const size_t kMinArguments = {{overload.arguments|length}}; - if (args.length() < kMinArguments) { + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + {{impl_class}}* impl = + wrapper_private->wrappable<{{impl_class}}>().get(); + if (!impl) { exception_state.SetSimpleException( - script::ExceptionState::kTypeError, "Not enough arguments."); + script::ExceptionState::kTypeError, "Stringifier problem."); + NOTREACHED(); return false; } -{% endif %} -{% for argument in overload.arguments %} - TypeTraits<{{argument.type}} >::ConversionType {{argument.name}}; - DCHECK_LT({{loop.index0}}, args.length()); - FromJSValue(context, args.handleAt({{loop.index0}}), - {{argument.conversion_flags}}, &exception_state, &{{argument.name}}); - if (exception_state.IsExceptionSet()) { - return false; - } -{% endfor %} -{% set arguments = overload.arguments|map(attribute="name")|list %} -{{ call_cobalt_function(impl_class, overload.type, - overload.name, arguments, - overload.raises_exception, - overload.call_with) }} -{% if operation.type != 'void' %} - if (!exception_state.IsExceptionSet()) { - args.rval().set(result_value); - } -{% endif %} - return !exception_state.IsExceptionSet(); -{% else %} - NOTIMPLEMENTED(); - return false; -{% endif %} + std::string stringified = impl->{{stringifier.name}}(); + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + JS::RootedString rooted_string(context, + JS_NewStringCopyN(context, stringified.c_str(), stringified.length())); + args.rval().set(JS::StringValue(rooted_string)); + return true; } -{% if operation.conditional %} -#endif // {{operation.conditional}} {% endif %} -{% endfor %} - const JSPropertySpec prototype_properties[] = { {% for constant in constants %} { @@ -290,6 +526,15 @@ }; const JSFunctionSpec prototype_functions[] = { +{% if stringifier %} + { + "toString", + JSOP_WRAPPER(&Stringifier), + 0, + JSPROP_PERMANENT, + NULL, + }, +{% endif %} {% for operation in operations %} {% if operation.conditional %} #if defined({{operation.conditional}}) @@ -317,9 +562,51 @@ JSOP_NULLWRAPPER, }, {% endfor %} +{% for attribute in static_attributes %} +{% if attribute.conditional %} +#if defined({{attribute.conditional}}) +{% endif %} +{% if attribute.has_setter %} + { // Static read/write attribute. + "{{attribute.idl_name}}", 0, + JSPROP_SHARED | JSPROP_ENUMERATE, + JSOP_WRAPPER(&staticget_{{attribute.idl_name}}), + JSOP_WRAPPER(&staticset_{{attribute.idl_name}}), + }, +{% else %} + { // Static readonly attribute. + "{{attribute.idl_name}}", 0, + JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_READONLY, + JSOP_WRAPPER(&staticget_{{attribute.idl_name}}), + JSOP_NULLWRAPPER, + }, +{% endif %} +{% if attribute.conditional %} +#endif // {{attribute.conditional}} +{% endif %} +{% endfor %} JS_PS_END }; +const JSFunctionSpec interface_object_functions[] = { +{% for operation in static_operations %} +{% if operation.conditional %} +#if defined({{operation.conditional}}) +{% endif %} + { + "{{ operation.idl_name }}", + JSOP_WRAPPER(&staticfcn_{{operation.idl_name}}), + {{ operation.length }}, + JSPROP_ENUMERATE, + NULL, + }, +{% if operation.conditional %} +#endif // {{operation.conditional}} +{% endif %} +{% endfor %} + JS_FS_END +}; + const JSPropertySpec own_properties[] = { {% for attribute in attributes if attribute.is_constructor_attribute %} {% if attribute.conditional %} @@ -358,7 +645,8 @@ // Create the Prototype object. interface_data->prototype = JS_NewObjectWithGivenProto( - context, &interface_data->prototype_class_definition, parent_prototype, NULL); + context, &interface_data->prototype_class_definition, parent_prototype, + NULL); bool success = JS_DefineProperties( context, interface_data->prototype, prototype_properties); DCHECK(success); @@ -379,18 +667,36 @@ JS::RootedObject rooted_interface_object( context, interface_data->interface_object); JS::RootedValue name_value(context); - const char name[] = "{{ named_constructor if named_constructor else interface.name }}"; - name_value.setString(JS_NewStringCopyZ(context, "{{interface.name}}")); + const char name[] = + "{{ named_constructor if named_constructor else interface.name }}"; + name_value.setString(JS_NewStringCopyZ(context, name)); success = JS_DefineProperty(context, rooted_interface_object, "name", name_value, JS_PropertyStub, JS_StrictPropertyStub, JSPROP_READONLY); DCHECK(success); +{% if constructor %} + + // Add the InterfaceObject.length property. It is set to the length of the + // shortest argument list of all overload constructors. + JS::RootedValue length_value(context); + length_value.setInt32({{constructor.length}}); + success = + JS_DefineProperty(context, rooted_interface_object, "length", + length_value, JS_PropertyStub, JS_StrictPropertyStub, + JSPROP_READONLY); + DCHECK(success); +{% endif %} // Define interface object properties (including constants). success = JS_DefineProperties(context, rooted_interface_object, - interface_object_properties); + interface_object_properties); DCHECK(success); + // Define interface object functions (static). + success = JS_DefineFunctions(context, rooted_interface_object, + interface_object_functions); + DCHECK(success); + // Set the Prototype.constructor and Constructor.prototype properties. DCHECK(interface_data->interface_object); @@ -423,7 +729,7 @@ } // namespace {% if is_global_interface %} -JSObject* {{binding_class}}::CreateInstance( +JSObject* {{binding_class}}::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject global_object( @@ -454,14 +760,16 @@ success = JS_DefineProperties(context, global_object, own_properties); DCHECK(success); - WrapperPrivate::AddPrivateData(global_object, wrappable); - - return global_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, global_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; } {% else %} // static -JSObject* {{binding_class}}::CreateInstance( +JSObject* {{binding_class}}::CreateProxy( JSContext* context, const scoped_refptr<Wrappable>& wrappable) { InterfaceData* interface_data = GetInterfaceData(context); JS::RootedObject prototype(context, GetPrototype(context)); @@ -469,11 +777,22 @@ JS::RootedObject new_object(context, JS_NewObjectWithGivenProto( context, &interface_data->instance_class_definition, prototype, NULL)); DCHECK(new_object); - WrapperPrivate::AddPrivateData(new_object, wrappable); - return new_object; + JS::RootedObject proxy(context, + ProxyHandler::NewProxy(context, new_object, prototype, NULL, + proxy_handler.Pointer())); + WrapperPrivate::AddPrivateData(proxy, wrappable); + return proxy; } {% endif %} +//static +const JSClass* {{binding_class}}::PrototypeClass( + JSContext* context) { + JS::RootedObject prototype(context, GetPrototype(context)); + JSClass* proto_class = JS_GetClass(*prototype.address()); + return proto_class; +} + // static JSObject* {{binding_class}}::GetPrototype(JSContext* context) { InterfaceData* interface_data = GetInterfaceData(context); @@ -496,14 +815,23 @@ return interface_data->interface_object; } -{% endif %} +{% endif %} {#- has_interface_object #} namespace { {% if constructor %} -JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args) { - // TODO: Implement support for constructors. - NOTIMPLEMENTED(); - return true; +{% for overload in constructor.overloads if constructor.overloads|length > 1 %} +JSBool Constructor{{overload.overload_index}}( + JSContext* context, unsigned int argc, JS::Value* vp) { +{{ constructor_implementation(overload) -}} +} + +{% endfor %} +JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp) { +{% if constructor.overloads|length == 1 %} +{{ constructor_implementation(constructor.overloads[0]) -}} +{% else %} +{{ overload_resolution_implementation(constructor, "Constructor")}} +{% endif %} } {% endif %} } // namespace @@ -515,7 +843,7 @@ JSContext* context = mozjs_global_object_proxy->context(); JSAutoRequest auto_request(context); - {{binding_class}}::CreateInstance( + {{binding_class}}::CreateProxy( context, global_interface); mozjs_global_object_proxy->SetEnvironmentSettings(environment_settings); @@ -529,7 +857,8 @@ {% if interface.name != impl_class %} wrapper_factory->RegisterWrappableType( {{interface.name}}::{{interface.name}}WrappableType(), - base::Bind(Mozjs{{interface.name}}::CreateInstance)); + base::Bind(Mozjs{{interface.name}}::CreateProxy), + base::Bind(Mozjs{{interface.name}}::PrototypeClass)); {% endif %} {% if interface.conditional %} #endif // defined({{interface.conditional}}) @@ -537,3 +866,48 @@ {% endfor %} {% endblock create_global_object_impl %} + +{% block enumeration_definitions %} +{% for enumeration in enumerations %} + +inline void ToJSValue( + JSContext* context, + {{impl_class}}::{{enumeration.name}} in_enum, + JS::MutableHandleValue out_value) { + + switch (in_enum) { +{% for value, idl_value in enumeration.value_pairs %} + case {{impl_class}}::{{value}}: + ToJSValue(context, std::string("{{idl_value}}"), out_value); + return; +{% endfor %} + } +} + + +inline void FromJSValue(JSContext* context, JS::HandleValue value, + int conversion_flags, ExceptionState* exception_state, + {{impl_class}}::{{enumeration.name}}* out_enum) { + DCHECK_EQ(0, conversion_flags) << "Unexpected conversion flags."; + // JSValue -> IDL enum algorithm described here: + // http://heycam.github.io/webidl/#es-enumeration + // 1. Let S be the result of calling ToString(V). + JS::RootedString rooted_string(context, JS_ValueToString(context, value)); + + JSBool match = JS_FALSE; +// 3. Return the enumeration value of type E that is equal to S. +{% for value, idl_value in enumeration.value_pairs %} + {{-" else " if not loop.first}}if (JS_StringEqualsAscii( + context, rooted_string, "{{idl_value}}", &match) + && match) { + *out_enum = {{impl_class}}::{{value}}; + }{% endfor %} else { + // 2. If S is not one of E's enumeration values, then throw a TypeError. + exception_state-> + SetSimpleException(ExceptionState::kTypeError, + "Cannot convert JavaScript value to Enum."); + return; + } +} +{% endfor %} +{% endblock enumeration_definitions %}
diff --git a/src/cobalt/bindings/mozjs/templates/interface.h.template b/src/cobalt/bindings/mozjs/templates/interface.h.template index 9c30315..f7ca8b6 100644 --- a/src/cobalt/bindings/mozjs/templates/interface.h.template +++ b/src/cobalt/bindings/mozjs/templates/interface.h.template
@@ -21,8 +21,9 @@ {% block implementation %} class {{binding_class}} { public: - static JSObject* CreateInstance(JSContext* context, + static JSObject* CreateProxy(JSContext* context, const scoped_refptr<script::Wrappable>& wrappable); + static const JSClass* PrototypeClass(JSContext* context); static JSObject* GetPrototype(JSContext* context); {% if has_interface_object %} static JSObject* GetInterfaceObject(JSContext* context);
diff --git a/src/cobalt/bindings/mozjs/templates/macros.cc.template b/src/cobalt/bindings/mozjs/templates/macros.cc.template index bc3174b..36770e2 100644 --- a/src/cobalt/bindings/mozjs/templates/macros.cc.template +++ b/src/cobalt/bindings/mozjs/templates/macros.cc.template
@@ -14,31 +14,375 @@ # limitations under the License. #} -{% macro call_nonvoid_function(return_type, function_name, arguments) %} - TypeTraits<{{return_type}} >::ReturnType value = - impl->{{function_name}}({{arguments|join(", ")}}); - if (!exception_state.IsExceptionSet()) { - ToJSValue(context, value, &exception_state, &result_value); +{# + # Function body for operation bindings. + # Parameters: + # operation: The operation context object + #} +{% macro function_implementation(operation) %} + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); +{% if operation.is_static %} +{{ static_function_prologue() }} +{% else %} + // Compute the 'this' value. + JS::RootedValue this_value(context, JS_ComputeThis(context, vp)); + // 'this' should be an object. + JS::RootedObject object(context); + if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) { + NOTREACHED(); + return false; } + if (!JS_ValueToObject(context, this_value, object.address())) { + NOTREACHED(); + return false; + } +{{ nonstatic_function_prologue(impl_class) }} +{% endif %} +{% call(arguments_list) extract_arguments(operation) %} +{{ call_cobalt_function(impl_class, operation.type, operation.name, + arguments_list, operation.raises_exception, + operation.call_with, operation.is_static) }} +{% if operation.type != 'void' %} + if (!exception_state.is_exception_set()) { + args.rval().set(result_value); + } +{% endif %} + return !exception_state.is_exception_set(); +{%- endcall %} {%- endmacro %} -{% macro call_void_function(function_name, arguments) %} - impl->{{function_name}}({{arguments|join(", ")}}); - result_value.set(JS::UndefinedHandleValue); +{# + # Function body for setting an attribute value. + # Parameters: + # attribute: The attribute context object. + # impl_class: Cobalt class name of the Cobalt implementation of the + # interface on which the attribute is a member. + # cobalt_impl_prefix: Variable name prefix of a pointer to a Cobalt + # implementation of the interface on which the attribute is a member. + #} +{% macro set_attribute_implementation(attribute, impl_class, + cobalt_impl_prefix="") %} +{% if attribute.put_forwards %} + { // Begin scope of {{attribute.type}} forwarded_{{cobalt_impl_prefix}}impl. + {{attribute.type}} forwarded_{{cobalt_impl_prefix}}impl = +{% if not attribute.is_static %} + {{cobalt_impl_prefix}}impl->{{attribute.getter_function_name}}(); +{% else %} + {{impl_class}}::{{attribute.getter_function_name}}(); +{% endif %} + if (!forwarded_{{cobalt_impl_prefix}}impl) { + NOTREACHED(); + return false; + } + if (!exception_state.is_exception_set()) { +{{ set_attribute_implementation(attribute.put_forwards, attribute.type, + "forwarded_" + cobalt_impl_prefix) -}} + } + return !exception_state.is_exception_set(); + } // End scope of {{attribute.type}} forwarded_{{cobalt_impl_prefix}}impl. +{% else %} + TypeTraits<{{attribute.type}} >::ConversionType value; + FromJSValue(context, vp, {{attribute.conversion_flags}}, &exception_state, + &value); + if (exception_state.is_exception_set()) { + return false; + } +{{ call_cobalt_function(impl_class, "void", + attribute.setter_function_name, + ["value"], attribute.raises_exception, + attribute.call_with, attribute.is_static, + cobalt_impl_prefix) }} + return !exception_state.is_exception_set(); +{% endif %} {#- attribute.put_forwards #} {%- endmacro %} -{% macro call_cobalt_function(impl_class, cobalt_type, function_name, arguments, raises_exception, call_with) %} +{# + # Extract and marshal arguments that will be passed to a function-like call. + # Parameters: + # operation: An IdlOperation object + # Passed to caller: + # A string that can be used as the parameters for a function call. It will + # be either empty, or a comma-separated list of variable names. + #} +{% macro extract_arguments(operation) %} +{% set non_optional_arguments = operation.non_optional_arguments %} +{% set optional_arguments = operation.optional_arguments %} +{% set num_default_arguments = operation.num_default_arguments %} +{% set variadic_argument = operation.variadic_argument %} +{% set has_non_default_optional_arguments = + operation.has_non_default_optional_arguments %} + +{%- if non_optional_arguments|length > 0 %} + const size_t kMinArguments = {{non_optional_arguments|length}}; + if (args.length() < kMinArguments) { + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Not enough arguments."); + return false; + } +{% endif -%} + +{# Declare variables for all arguments #} +{% for argument in non_optional_arguments %} +{% if loop.first %} + // Non-optional arguments +{% endif %} + TypeTraits<{{argument.type}} >::ConversionType {{argument.name}}; +{% endfor %} +{% for argument in optional_arguments if argument.default_value %} +{% if loop.first %} + // Optional arguments with default values +{% endif %} + TypeTraits<{{argument.type}} >::ConversionType {{argument.name}} = + {{argument.default_value}}; +{% endfor %} +{% for argument in optional_arguments if not argument.default_value %} +{% if loop.first %} + // Optional arguments +{% endif %} + TypeTraits<{{argument.type}} >::ConversionType {{argument.name}}; +{% endfor %} +{% if variadic_argument %} + // Variadic argument + TypeTraits<{{variadic_argument.type}} >::ConversionType {{ + variadic_argument.name}}; +{% endif -%} + +{% for argument in non_optional_arguments %} + + DCHECK_LT({{loop.index0}}, args.length()); + JS::RootedValue non_optional_value{{loop.index0}}( + context, args[{{loop.index0}}]); + FromJSValue(context, + non_optional_value{{loop.index0}}, + {{argument.conversion_flags}}, + &exception_state, &{{argument.name}}); + if (exception_state.is_exception_set()) { + return false; + } +{% endfor -%} +{% for argument in optional_arguments %} +{% if loop.first %} + size_t num_set_arguments = {{ + non_optional_arguments|length + num_default_arguments}}; +{% endif %} + if (args.length() > {{loop.index0 + non_optional_arguments|length}}) { + JS::RootedValue optional_value{{loop.index0}}( + context, args[{{loop.index0 + non_optional_arguments|length}}]); + FromJSValue(context, + optional_value{{loop.index0}}, + {{argument.conversion_flags}}, + &exception_state, + &{{argument.name}}); + if (exception_state.is_exception_set()) { + return false; + } +{% if not argument.default_value %} + ++num_set_arguments; +{% endif %} + } +{% endfor %} +{% if variadic_argument %} + + // Get variadic arguments. +{% if optional_arguments|length %} + const size_t kLastOptionalArgIndex = {{ + non_optional_arguments|length + optional_arguments|length}}; + if (num_set_arguments == kLastOptionalArgIndex) { + // If the last optional argument has been set, we will call the overload + // that takes the variadic argument, possibly with an empty vector in the + // case that there are no more arguments left. + ++num_set_arguments; + } +{% endif %} + const size_t kFirstVariadicArgIndex = {{operation.arguments|length - 1}}; + if (args.length() > kFirstVariadicArgIndex) { + {{variadic_argument.name}}.resize(args.length() - kFirstVariadicArgIndex); + for (int i = 0; i + kFirstVariadicArgIndex < args.length(); ++i) { + JS::RootedValue variadic_argument_value{{i}}( + context, args[i + kFirstVariadicArgIndex]); + FromJSValue(context, + variadic_argument_value{{i}}, + {{variadic_argument.conversion_flags}}, + &exception_state, + &{{variadic_argument.name}}[i]); + if (exception_state.is_exception_set()) { + return false; + } + } + } +{% endif -%} + +{# Call the implementation function, based on the number of set arguments. #} +{% if has_non_default_optional_arguments %} + switch (num_set_arguments) { +{% for num_arguments in range( + non_optional_arguments|length + num_default_arguments, + operation.arguments|length + 1) %} +{# If no variadic arguments have been set, we still call the function with + signature that has the variadic argument and pass an empty vector. There is + no such function signature that takes the optional parameter immediately + preceeding the variadic argument but does not take the variadic arguments. #} +{% if loop.last or not operation.arguments[num_arguments].is_variadic %} +{% set function_arguments = + operation.arguments[0:num_arguments]|map(attribute='name')|list %} + case {{num_arguments}}: + { + {{- caller(function_arguments)|indent(8, false) }} + } + break; +{% endif %} +{% endfor %} + default: + NOTREACHED(); + return false; + } +{% else %} {#- has_non_default_optional_arguments #} +{% set function_arguments = operation.arguments|map(attribute='name')|list %} + {# whitespace control block #} + {{-caller(function_arguments)}} +{% endif %} +{% endmacro %} + +{# + # Append extra arguments that should be passed to a cobalt function. + # Specifically, this will prepend parameters specified on IDLs using the + # [CallWith=] extended attribute. + # Parameters: + # arguments_list: A list of C++ expressions that represent a sequence of + # arguments that will be passed to a function. + # context: An IDL object that may have the extended attribute that + # we are interested in. + # Passed to caller: + # arguments_list, possibly with extra arguments prepended and appended. + #} +{% macro add_extra_arguments(arguments_list, raises_exception, call_with) %} {% if call_with %} MozjsGlobalObjectProxy* global_object_proxy = static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context)); +{% do arguments_list.insert(0, + 'global_object_proxy->Get%s()'|format(call_with)) %} {% endif %} - {{impl_class}}* impl = - WrapperPrivate::GetWrappable<{{impl_class}}>(object); -{% do arguments.append("&exception_state") if raises_exception %} -{% do arguments.append("global_object_proxy->Get%s()"|format(call_with)) if call_with %} -{% if cobalt_type == "void" %} -{{ call_void_function(function_name, arguments) }} +{% do arguments_list.append('&exception_state') if raises_exception %} +{%- endmacro %} + +{% macro call_nonvoid_function(return_type, function_name, arguments, + impl_class, is_static) %} + if (!exception_state.is_exception_set()) { +{% if not is_static %} + ToJSValue(context, + impl->{{function_name}}({{arguments|join(", ")}}), + &result_value); {% else %} -{{ call_nonvoid_function(cobalt_type, function_name, arguments) }} + ToJSValue(context, + {{impl_class}}::{{function_name}}({{arguments|join(', ')}}), + &result_value); +{% endif %} + } +{%- endmacro %} + +{% macro call_void_function(function_name, arguments, impl_class, is_static, + cobalt_impl_prefix) %} +{% if not is_static %} + {{cobalt_impl_prefix}}impl->{{function_name}}({{arguments|join(", ")}}); +{% else %} + {{impl_class}}::{{function_name}}({{arguments|join(', ')}}); +{% endif %} + result_value.set(JS::UndefinedHandleValue); +{%- endmacro %} + +{% macro get_impl_class_instance(impl_class) %} + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromObject(context, object); + {{impl_class}}* impl = + wrapper_private->wrappable<{{impl_class}}>().get(); +{%- endmacro %} + +{% macro static_function_prologue() %} + MozjsExceptionState exception_state(context); + JS::RootedValue result_value(context); +{% endmacro %} + +{% macro nonstatic_function_prologue(impl_class) %} +{{ static_function_prologue() }} +{{ get_impl_class_instance(impl_class) }} +{%- endmacro %} + +{# + # Call a function on an instance of a Cobalt platform object. + #} +{% macro call_cobalt_function(impl_class, cobalt_type, function_name, arguments, + raises_exception, call_with, is_static, + cobalt_impl_prefix) %} +{{ add_extra_arguments(arguments, raises_exception, call_with) }} +{% if cobalt_type == "void" %} +{{ call_void_function(function_name, arguments, impl_class, is_static, + cobalt_impl_prefix) -}} +{% else %} +{{ call_nonvoid_function(cobalt_type, function_name, arguments, impl_class, + is_static) -}} {% endif %} {% endmacro %} + +{# + # Function body for constructor bindings. + # Parameters: + # constructor: The constructor context object + #} +{% macro constructor_implementation(constructor) %} + MozjsExceptionState exception_state(context); + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); +{% call(arguments_list) extract_arguments(constructor) %} +{{ add_extra_arguments(arguments_list, constructor.raises_exception, + constructor.call_with) }} + scoped_refptr<{{impl_class}}> new_object = + new {{impl_class}}({{arguments_list|join(', ')}}); + JS::RootedValue result_value(context); + ToJSValue(context, new_object, &result_value); + DCHECK(result_value.isObject()); + JS::RootedObject result_object(context, JSVAL_TO_OBJECT(result_value)); + args.rval().setObject(*result_object); + return true; +{%- endcall %} +{%- endmacro %} + +{# + # Function body for overload resolution function. + # Parameters: + # overload_context: The overload context object. + # bound_function_prefix: The prefix of the function to be called on + # resolution. The overload index will be appended to this. + #} +{% macro overload_resolution_implementation( + overload_context, bound_function_prefix) %} + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + switch(argc) { +{% for length, distinguishing_argument_index, resolution_tests in + overload_context.overload_resolution_by_length %} + case({{length}}): { + // Overload resolution algorithm details found here: + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm +{# In the case there is only one resolution condition, we don't need the arg. #} +{% if resolution_tests|length > 1 %} + JS::RootedValue arg(context, args[{{distinguishing_argument_index}}]); + MozjsGlobalObjectProxy* global_object_proxy = + static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_object_proxy->wrapper_factory(); +{% endif %} +{% for test, overload in resolution_tests %} + if ({{test("arg")}}) { + return {{bound_function_prefix}}{{overload.overload_index}}( + context, argc, vp); + } +{% endfor %} + break; + } +{% endfor %} + } + // Invalid number of args + // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + // 4. If S is empty, then throw a TypeError. + MozjsExceptionState exception_state(context); + exception_state.SetSimpleException( + script::ExceptionState::kTypeError, "Invalid number of arguments."); + return false; +{%- endmacro %}
diff --git a/src/cobalt/bindings/run_cobalt_bindings_tests.bat b/src/cobalt/bindings/run_cobalt_bindings_tests.bat new file mode 100644 index 0000000..e26fc8d --- /dev/null +++ b/src/cobalt/bindings/run_cobalt_bindings_tests.bat
@@ -0,0 +1,18 @@ +@rem +@rem Copyright 2016 Google Inc. All Rights Reserved. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem http://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@python run_cobalt_bindings_tests.py jsc %* +@python run_cobalt_bindings_tests.py mozjs %*
diff --git a/src/cobalt/bindings/testing/DOMStringTestInterface.idl b/src/cobalt/bindings/testing/DOMStringTestInterface.idl index 1c03de6..40667eb 100644 --- a/src/cobalt/bindings/testing/DOMStringTestInterface.idl +++ b/src/cobalt/bindings/testing/DOMStringTestInterface.idl
@@ -17,6 +17,7 @@ interface DOMStringTestInterface { attribute DOMString property; readonly attribute DOMString readOnlyProperty; + readonly attribute DOMString readOnlyTokenProperty; [TreatNullAs=EmptyString] attribute DOMString nullIsEmptyProperty; [TreatUndefinedAs=EmptyString] attribute DOMString undefinedIsEmptyProperty; [TreatUndefinedAs=EmptyString] attribute DOMString? nullableUndefinedIsEmptyProperty;
diff --git a/src/cobalt/bindings/testing/DerivedInterface.idl b/src/cobalt/bindings/testing/DerivedInterface.idl index 45127a9..810d333 100644 --- a/src/cobalt/bindings/testing/DerivedInterface.idl +++ b/src/cobalt/bindings/testing/DerivedInterface.idl
@@ -14,6 +14,7 @@ * limitations under the License. */ +[Constructor] interface DerivedInterface : BaseInterface { readonly attribute DOMString derivedAttribute; void derivedOperation();
diff --git a/src/cobalt/bindings/testing/IndexedGetterInterface.idl b/src/cobalt/bindings/testing/IndexedGetterInterface.idl index c8c1f8a..bd0cc05 100644 --- a/src/cobalt/bindings/testing/IndexedGetterInterface.idl +++ b/src/cobalt/bindings/testing/IndexedGetterInterface.idl
@@ -18,4 +18,5 @@ readonly attribute unsigned long length; getter unsigned long indexedGetter(unsigned long index); setter void indexedSetter(unsigned long index, unsigned long value); + deleter void indexedDeleter(unsigned long index); };
diff --git a/src/cobalt/bindings/testing/NumericTypesTestInterface.idl b/src/cobalt/bindings/testing/NumericTypesTestInterface.idl index 320d6b9..96d9bd6 100644 --- a/src/cobalt/bindings/testing/NumericTypesTestInterface.idl +++ b/src/cobalt/bindings/testing/NumericTypesTestInterface.idl
@@ -39,6 +39,14 @@ void unsignedLongArgumentOperation(unsigned long arg1); attribute unsigned long unsignedLongProperty; + long long longLongReturnOperation(); + void longLongArgumentOperation(long long arg1); + attribute long long longLongProperty; + + unsigned long long unsignedLongLongReturnOperation(); + void unsignedLongLongArgumentOperation(unsigned long long arg1); + attribute unsigned long long unsignedLongLongProperty; + double doubleReturnOperation(); void doubleArgumentOperation(double arg1); attribute double doubleProperty;
diff --git a/src/cobalt/bindings/testing/OperationsTestInterface.idl b/src/cobalt/bindings/testing/OperationsTestInterface.idl index 3dc3507..264f39e 100644 --- a/src/cobalt/bindings/testing/OperationsTestInterface.idl +++ b/src/cobalt/bindings/testing/OperationsTestInterface.idl
@@ -41,6 +41,7 @@ // double and long are not distinguishable, but because this is a static // function it is part of the same overload set as the one that takes long. static void overloadedFunction(double arg); + static void overloadedFunction(double arg1, double arg2); void overloadedNullable(long arg); void overloadedNullable(boolean? arg);
diff --git a/src/cobalt/bindings/testing/PutForwardsInterface.idl b/src/cobalt/bindings/testing/PutForwardsInterface.idl index e488252..d8bf8ab 100644 --- a/src/cobalt/bindings/testing/PutForwardsInterface.idl +++ b/src/cobalt/bindings/testing/PutForwardsInterface.idl
@@ -16,4 +16,6 @@ interface PutForwardsInterface { [PutForwards=arbitraryProperty] readonly attribute ArbitraryInterface forwardingAttribute; + [PutForwards=arbitraryProperty] + static readonly attribute ArbitraryInterface staticForwardingAttribute; };
diff --git a/src/cobalt/bindings/testing/StaticPropertiesInterface.idl b/src/cobalt/bindings/testing/StaticPropertiesInterface.idl index e0a8fb2..2a73da8 100644 --- a/src/cobalt/bindings/testing/StaticPropertiesInterface.idl +++ b/src/cobalt/bindings/testing/StaticPropertiesInterface.idl
@@ -15,5 +15,9 @@ */ interface StaticPropertiesInterface { static void staticFunction(); + static void staticFunction(long arg); + static void staticFunction(DOMString arg); + static void staticFunction(long arg1, long arg2, long arg3); + static void staticFunction(long arg1, long arg2, ArbitraryInterface arg3); static attribute DOMString staticAttribute; };
diff --git a/src/cobalt/bindings/testing/UnionTypesInterface.idl b/src/cobalt/bindings/testing/UnionTypesInterface.idl index 33f9854..e53b034 100644 --- a/src/cobalt/bindings/testing/UnionTypesInterface.idl +++ b/src/cobalt/bindings/testing/UnionTypesInterface.idl
@@ -18,4 +18,5 @@ attribute (DOMString or boolean or ArbitraryInterface or long) unionProperty; attribute (double or DOMString?) unionWithNullableMemberProperty; attribute (double or DOMString)? nullableUnionProperty; + attribute (BaseInterface or DOMString) unionBaseProperty; };
diff --git a/src/cobalt/bindings/testing/dom_string_bindings_test.cc b/src/cobalt/bindings/testing/dom_string_bindings_test.cc index f8614dc..06a9595 100644 --- a/src/cobalt/bindings/testing/dom_string_bindings_test.cc +++ b/src/cobalt/bindings/testing/dom_string_bindings_test.cc
@@ -58,6 +58,15 @@ EXPECT_TRUE(EvaluateScript("test.readOnlyProperty = \"foo\";", NULL)); } +TEST_F(DOMStringBindingsTest, GetReadOnlyTokenProperty) { + EXPECT_CALL(test_mock(), read_only_token_property()) + .WillOnce(Return(base::Token("mock_value"))); + + std::string result; + EXPECT_TRUE(EvaluateScript("test.readOnlyTokenProperty;", &result)); + EXPECT_STREQ("mock_value", result.c_str()); +} + TEST_F(DOMStringBindingsTest, SetNull) { EXPECT_CALL(test_mock(), set_property("null"));
diff --git a/src/cobalt/bindings/testing/dom_string_test_interface.h b/src/cobalt/bindings/testing/dom_string_test_interface.h index f257d2f..7bcd05d 100644 --- a/src/cobalt/bindings/testing/dom_string_test_interface.h +++ b/src/cobalt/bindings/testing/dom_string_test_interface.h
@@ -20,6 +20,7 @@ #include <string> #include "base/optional.h" +#include "cobalt/base/token.h" #include "cobalt/script/wrappable.h" #include "testing/gmock/include/gmock/gmock.h" @@ -36,6 +37,9 @@ // readonly attribute DOMString readOnlyProperty MOCK_CONST_METHOD0(read_only_property, std::string()); + // readonly attribute DOMString readOnlyTokenProperty + MOCK_CONST_METHOD0(read_only_token_property, base::Token()); + MOCK_CONST_METHOD0(null_is_empty_property, std::string()); MOCK_METHOD1(set_null_is_empty_property, void(const std::string&));
diff --git a/src/cobalt/bindings/testing/getter_setter_test.cc b/src/cobalt/bindings/testing/getter_setter_test.cc index 265f28e..24654d5 100644 --- a/src/cobalt/bindings/testing/getter_setter_test.cc +++ b/src/cobalt/bindings/testing/getter_setter_test.cc
@@ -37,17 +37,34 @@ namespace testing { namespace { -typedef InterfaceBindingsTest<AnonymousIndexedGetterInterface> +// Use this fixture to create a new MockT object with a BaseClass wrapper, and +// bind the wrapper to the javascript variable "test". +template <class MockT> +class GetterSetterBindingsTestBase : public BindingsTestBase { + public: + GetterSetterBindingsTestBase() + : test_mock_(new ::testing::NiceMock<MockT>()) { + global_object_proxy_->Bind("test", make_scoped_refptr<MockT>((test_mock_))); + } + + MockT& test_mock() { return *test_mock_.get(); } + + const scoped_refptr<MockT> test_mock_; +}; + +typedef GetterSetterBindingsTestBase<AnonymousIndexedGetterInterface> AnonymousIndexedGetterBindingsTest; -typedef InterfaceBindingsTest<AnonymousNamedIndexedGetterInterface> +typedef GetterSetterBindingsTestBase<AnonymousNamedIndexedGetterInterface> AnonymousNamedIndexedGetterBindingsTest; -typedef InterfaceBindingsTest<AnonymousNamedGetterInterface> +typedef GetterSetterBindingsTestBase<AnonymousNamedGetterInterface> AnonymousNamedGetterBindingsTest; -typedef InterfaceBindingsTest<DerivedGetterSetterInterface> +typedef GetterSetterBindingsTestBase<DerivedGetterSetterInterface> DerivedGetterSetterBindingsTest; -typedef InterfaceBindingsTest<IndexedGetterInterface> IndexedGetterBindingsTest; -typedef InterfaceBindingsTest<NamedGetterInterface> NamedGetterBindingsTest; -typedef InterfaceBindingsTest<NamedIndexedGetterInterface> +typedef GetterSetterBindingsTestBase<IndexedGetterInterface> + IndexedGetterBindingsTest; +typedef GetterSetterBindingsTestBase<NamedGetterInterface> + NamedGetterBindingsTest; +typedef GetterSetterBindingsTestBase<NamedIndexedGetterInterface> NamedIndexedGetterBindingsTest; class NamedPropertiesEnumerator { @@ -67,134 +84,149 @@ } // namespace TEST_F(IndexedGetterBindingsTest, IndexedGetter) { + ON_CALL(test_mock(), length()).WillByDefault(Return(10)); + ON_CALL(test_mock(), IndexedGetter(_)).WillByDefault(ReturnArg<0>()); InSequence dummy; std::string result; - EXPECT_CALL(test_mock(), length()).WillOnce(Return(10)); - EXPECT_CALL(test_mock(), IndexedGetter(_)).WillOnce(ReturnArg<0>()); + EXPECT_CALL(test_mock(), IndexedGetter(4)).Times(1); EXPECT_TRUE(EvaluateScript("test[4];", &result)); EXPECT_STREQ("4", result.c_str()); - EXPECT_CALL(test_mock(), IndexedGetter(_)).WillOnce(ReturnArg<0>()); + EXPECT_CALL(test_mock(), IndexedGetter(6)).Times(1); EXPECT_TRUE(EvaluateScript("test.indexedGetter(6);", &result)); EXPECT_STREQ("6", result.c_str()); } TEST_F(IndexedGetterBindingsTest, IndexedGetterOutOfRange) { + ON_CALL(test_mock(), length()).WillByDefault(Return(10)); + ON_CALL(test_mock(), IndexedGetter(_)).WillByDefault(ReturnArg<0>()); InSequence dummy; std::string result; - EXPECT_CALL(test_mock(), length()).WillOnce(Return(10)); + EXPECT_CALL(test_mock(), IndexedGetter(_)).Times(0); EXPECT_TRUE(EvaluateScript("test[20];", &result)); EXPECT_STREQ("undefined", result.c_str()); - EXPECT_CALL(test_mock(), IndexedGetter(_)).WillOnce(ReturnArg<0>()); + EXPECT_CALL(test_mock(), IndexedGetter(20)).Times(1); EXPECT_TRUE(EvaluateScript("test.indexedGetter(20);", &result)); EXPECT_STREQ("20", result.c_str()); } TEST_F(IndexedGetterBindingsTest, IndexedSetter) { + ON_CALL(test_mock(), length()).WillByDefault(Return(10)); InSequence dummy; - EXPECT_CALL(test_mock(), length()).WillOnce(Return(10)); - EXPECT_CALL(test_mock(), IndexedSetter(4, 100)); + EXPECT_CALL(test_mock(), IndexedSetter(4, 100)).Times(1); EXPECT_TRUE(EvaluateScript("test[4] = 100;", NULL)); - EXPECT_CALL(test_mock(), IndexedSetter(4, 100)); + EXPECT_CALL(test_mock(), IndexedSetter(4, 100)).Times(1); EXPECT_TRUE(EvaluateScript("test.indexedSetter(4, 100);", NULL)); } +#if defined(ENGINE_SUPPORTS_INDEXED_DELETERS) TEST_F(IndexedGetterBindingsTest, IndexedDeleter) { - EXPECT_CALL(test_mock(), length()).WillOnce(Return(10)); + ON_CALL(test_mock(), length()).WillByDefault(Return(10)); + EXPECT_CALL(test_mock(), IndexedDeleter(4)).Times(1); EXPECT_TRUE(EvaluateScript("delete test[4];", NULL)); } TEST_F(IndexedGetterBindingsTest, IndexedDeleterOutOfRange) { - EXPECT_CALL(test_mock(), length()).WillOnce(Return(1)); + ON_CALL(test_mock(), length()).WillByDefault(Return(1)); + EXPECT_CALL(test_mock(), IndexedDeleter(_)).Times(0); EXPECT_TRUE(EvaluateScript("delete test[4];", NULL)); } +#endif TEST_F(IndexedGetterBindingsTest, IndexedSetterOutOfRange) { - InSequence dummy; + ON_CALL(test_mock(), length()).WillByDefault(Return(1)); - EXPECT_CALL(test_mock(), length()).WillOnce(Return(1)); + InSequence dummy; EXPECT_CALL(test_mock(), IndexedSetter(_, _)).Times(0); EXPECT_TRUE(EvaluateScript("test[4] = 100;", NULL)); - EXPECT_CALL(test_mock(), IndexedSetter(4, 100)); + EXPECT_CALL(test_mock(), IndexedSetter(4, 100)).Times(1); EXPECT_TRUE(EvaluateScript("test.indexedSetter(4, 100);", NULL)); } TEST_F(NamedGetterBindingsTest, NamedGetter) { + ON_CALL(test_mock(), CanQueryNamedProperty(std::string("foo"))) + .WillByDefault(Return(true)); + ON_CALL(test_mock(), NamedGetter(std::string("foo"))) + .WillByDefault(Return(std::string("bar"))); + ON_CALL(test_mock(), NamedGetter(std::string("bar"))) + .WillByDefault(Return(std::string("foo"))); InSequence dummy; std::string result; - EXPECT_CALL(test_mock(), CanQueryNamedProperty(std::string("foo"))) - .WillOnce(Return(true)); - EXPECT_CALL(test_mock(), NamedGetter(std::string("foo"))) - .WillOnce(Return(std::string("bar"))); + EXPECT_CALL(test_mock(), NamedGetter(std::string("foo"))).Times(1); EXPECT_TRUE(EvaluateScript("test[\"foo\"];", &result)); EXPECT_STREQ("bar", result.c_str()); - EXPECT_CALL(test_mock(), NamedGetter(std::string("bar"))) - .WillOnce(Return(std::string("foo"))); + EXPECT_CALL(test_mock(), NamedGetter(std::string("bar"))).Times(1); EXPECT_TRUE(EvaluateScript("test.namedGetter(\"bar\");", &result)); EXPECT_STREQ("foo", result.c_str()); } TEST_F(NamedGetterBindingsTest, NamedGetterUnsupportedName) { + ON_CALL(test_mock(), CanQueryNamedProperty(_)).WillByDefault(Return(false)); InSequence dummy; std::string result; - EXPECT_CALL(test_mock(), CanQueryNamedProperty(std::string("foo"))) - .WillOnce(Return(false)); + EXPECT_CALL(test_mock(), NamedGetter(_)).Times(0); EXPECT_TRUE(EvaluateScript("test[\"foo\"];", &result)); EXPECT_STREQ("undefined", result.c_str()); } TEST_F(NamedGetterBindingsTest, NamedSetter) { + ON_CALL(test_mock(), CanQueryNamedProperty(std::string("foo"))) + .WillByDefault(Return(true)); InSequence dummy; - EXPECT_CALL(test_mock(), NamedSetter(std::string("foo"), std::string("bar"))); + EXPECT_CALL(test_mock(), NamedSetter(std::string("foo"), std::string("bar"))) + .Times(1); EXPECT_TRUE(EvaluateScript("test[\"foo\"] = \"bar\";", NULL)); - EXPECT_CALL(test_mock(), NamedSetter(std::string("foo"), std::string("bar"))); + EXPECT_CALL(test_mock(), NamedSetter(std::string("foo"), std::string("bar"))) + .Times(1); EXPECT_TRUE(EvaluateScript("test.namedSetter(\"foo\", \"bar\");", NULL)); } TEST_F(NamedGetterBindingsTest, NamedDeleter) { + ON_CALL(test_mock(), CanQueryNamedProperty(std::string("foo"))) + .WillByDefault(Return(true)); InSequence dummy; - EXPECT_CALL(test_mock(), CanQueryNamedProperty(std::string("foo"))) - .WillOnce(Return(true)); - EXPECT_CALL(test_mock(), NamedDeleter(std::string("foo"))); + EXPECT_CALL(test_mock(), NamedDeleter(std::string("foo"))).Times(1); EXPECT_TRUE(EvaluateScript("delete test.foo;", NULL)); - EXPECT_CALL(test_mock(), NamedDeleter(std::string("bar"))); + EXPECT_CALL(test_mock(), NamedDeleter(std::string("bar"))).Times(1); EXPECT_TRUE(EvaluateScript("test.namedDeleter(\"bar\");", NULL)); } TEST_F(NamedGetterBindingsTest, NamedDeleterUnsupportedName) { + ON_CALL(test_mock(), CanQueryNamedProperty(_)).WillByDefault(Return(false)); InSequence dummy; - EXPECT_CALL(test_mock(), CanQueryNamedProperty(std::string("foo"))) - .WillOnce(Return(false)); + EXPECT_CALL(test_mock(), NamedDeleter(_)).Times(0); EXPECT_TRUE(EvaluateScript("delete test.foo;", NULL)); - EXPECT_CALL(test_mock(), NamedDeleter(std::string("bar"))); + EXPECT_CALL(test_mock(), NamedDeleter(std::string("bar"))).Times(1); EXPECT_TRUE(EvaluateScript("test.namedDeleter(\"bar\");", NULL)); } TEST_F(NamedGetterBindingsTest, NamedDeleterIndexProperty) { + ON_CALL(test_mock(), CanQueryNamedProperty(std::string("1"))) + .WillByDefault(Return(true)); InSequence dummy; - EXPECT_CALL(test_mock(), CanQueryNamedProperty(std::string("1"))) - .WillOnce(Return(true)); - EXPECT_CALL(test_mock(), NamedDeleter(std::string("1"))); + EXPECT_CALL(test_mock(), NamedDeleter(std::string("1"))).Times(1); EXPECT_TRUE(EvaluateScript("delete test[1];", NULL)); } TEST_F(NamedGetterBindingsTest, IndexConvertsToNamedProperty) { + ON_CALL(test_mock(), CanQueryNamedProperty(std::string("5"))) + .WillByDefault(Return(true)); InSequence dummy; EXPECT_CALL(test_mock(), NamedSetter(std::string("5"), std::string("bar"))); @@ -213,79 +245,106 @@ InSequence dummy; std::string result; + EXPECT_CALL(test_mock(), NamedGetter(_)).Times(0); EXPECT_TRUE(EvaluateScript("test[\"toString\"]();", &result)); EXPECT_STREQ("[object NamedIndexedGetterInterface]", result.c_str()); } TEST_F(AnonymousNamedIndexedGetterBindingsTest, EnumeratedPropertiesOrdering) { NamedPropertiesEnumerator enumerator(2); + ON_CALL(test_mock(), length()).WillByDefault(Return(2)); + ON_CALL(test_mock(), EnumerateNamedProperties(_)) + .WillByDefault(Invoke( + &enumerator, &NamedPropertiesEnumerator::EnumerateNamedProperties)); std::string result; - EXPECT_CALL(test_mock(), length()).Times(3).WillRepeatedly(Return(2)); - EXPECT_CALL(test_mock(), EnumerateNamedProperties(_)) - .WillOnce(Invoke(&enumerator, - &NamedPropertiesEnumerator::EnumerateNamedProperties)); EXPECT_TRUE( EvaluateScript("var properties = [];" "for (p in test) { properties.push(p); }" "properties;", &result)); - // Indexed properties should come first, then named properties, and then // other "regular" properties that are defined on the interface; - EXPECT_STREQ("0,1,property_a,property_b,length", result.c_str()); + EXPECT_TRUE(EvaluateScript("properties.length;", &result)); + EXPECT_STREQ("5", result.c_str()); + EXPECT_TRUE(EvaluateScript("properties[0];", &result)); + EXPECT_STREQ("0", result.c_str()); + EXPECT_TRUE(EvaluateScript("properties[1];", &result)); + EXPECT_STREQ("1", result.c_str()); + EXPECT_TRUE(EvaluateScript("properties[2];", &result)); + EXPECT_STREQ("property_a", result.c_str()); + EXPECT_TRUE(EvaluateScript("properties[3];", &result)); + EXPECT_STREQ("property_b", result.c_str()); + EXPECT_TRUE(EvaluateScript("properties[4];", &result)); + EXPECT_STREQ("length", result.c_str()); } TEST_F(AnonymousIndexedGetterBindingsTest, EnumerateIndexedProperties) { + ON_CALL(test_mock(), length()).WillByDefault(Return(4)); std::string result; - EXPECT_CALL(test_mock(), length()).Times(5).WillRepeatedly(Return(4)); EXPECT_TRUE( EvaluateScript("var properties = [];" "for (p in test) { properties.push(p); }" "properties;", &result)); - EXPECT_STREQ("0,1,2,3,length", result.c_str()); + EXPECT_TRUE(EvaluateScript("properties.length;", &result)); + EXPECT_STREQ("5", result.c_str()); + EXPECT_TRUE(EvaluateScript("properties[0];", &result)); + EXPECT_STREQ("0", result.c_str()); + EXPECT_TRUE(EvaluateScript("properties[1];", &result)); + EXPECT_STREQ("1", result.c_str()); + EXPECT_TRUE(EvaluateScript("properties[2];", &result)); + EXPECT_STREQ("2", result.c_str()); + EXPECT_TRUE(EvaluateScript("properties[3];", &result)); + EXPECT_STREQ("3", result.c_str()); + EXPECT_TRUE(EvaluateScript("properties[4];", &result)); + EXPECT_STREQ("length", result.c_str()); } TEST_F(AnonymousNamedGetterBindingsTest, EnumerateNamedProperties) { NamedPropertiesEnumerator enumerator(4); + ON_CALL(test_mock(), EnumerateNamedProperties(_)) + .WillByDefault(Invoke( + &enumerator, &NamedPropertiesEnumerator::EnumerateNamedProperties)); std::string result; - EXPECT_CALL(test_mock(), EnumerateNamedProperties(_)) - .WillOnce(Invoke(&enumerator, - &NamedPropertiesEnumerator::EnumerateNamedProperties)); EXPECT_TRUE( EvaluateScript("var properties = [];" - "for (p in test) { properties.push(p); }" - "properties;", - &result)); + "for (p in test) { properties.push(p); }")); - EXPECT_STREQ("property_a,property_b,property_c,property_d", result.c_str()); + EXPECT_TRUE(EvaluateScript("properties.length;", &result)); + EXPECT_STREQ("4", result.c_str()); + EXPECT_TRUE(EvaluateScript("properties[0];", &result)); + EXPECT_STREQ("property_a", result.c_str()); + EXPECT_TRUE(EvaluateScript("properties[1];", &result)); + EXPECT_STREQ("property_b", result.c_str()); + EXPECT_TRUE(EvaluateScript("properties[2];", &result)); + EXPECT_STREQ("property_c", result.c_str()); + EXPECT_TRUE(EvaluateScript("properties[3];", &result)); + EXPECT_STREQ("property_d", result.c_str()); } TEST_F(AnonymousIndexedGetterBindingsTest, IndexedGetter) { + ON_CALL(test_mock(), length()).WillByDefault(Return(10)); + ON_CALL(test_mock(), AnonymousIndexedGetter(_)).WillByDefault(ReturnArg<0>()); InSequence dummy; std::string result; - EXPECT_CALL(test_mock(), length()).WillOnce(Return(10)); - EXPECT_CALL(test_mock(), AnonymousIndexedGetter(_)).WillOnce(ReturnArg<0>()); EXPECT_TRUE(EvaluateScript("test[4];", &result)); EXPECT_STREQ("4", result.c_str()); - EXPECT_CALL(test_mock(), length()).WillOnce(Return(10)); - EXPECT_CALL(test_mock(), AnonymousIndexedGetter(_)).Times(0); EXPECT_TRUE(EvaluateScript("test[10];", NULL)); } TEST_F(AnonymousIndexedGetterBindingsTest, IndexedSetter) { + ON_CALL(test_mock(), length()).WillByDefault(Return(10)); + InSequence dummy; - EXPECT_CALL(test_mock(), length()).WillOnce(Return(10)); EXPECT_CALL(test_mock(), AnonymousIndexedSetter(4, 100)); EXPECT_TRUE(EvaluateScript("test[4] = 100;", NULL)); - EXPECT_CALL(test_mock(), length()).WillOnce(Return(10)); EXPECT_CALL(test_mock(), AnonymousIndexedSetter(_, _)).Times(0); EXPECT_TRUE(EvaluateScript("test[10] = 100;", NULL)); } @@ -313,6 +372,8 @@ } TEST_F(AnonymousNamedGetterBindingsTest, NamedSetter) { + ON_CALL(test_mock(), CanQueryNamedProperty(std::string("foo"))) + .WillByDefault(Return(true)); InSequence dummy; EXPECT_CALL(test_mock(), @@ -321,16 +382,15 @@ } TEST_F(DerivedGetterSetterBindingsTest, OverridesGetterAndSetter) { + ON_CALL(test_mock(), length()).WillByDefault(Return(10)); InSequence dummy; std::string result; - EXPECT_CALL(test_mock(), length()).WillOnce(Return(10)); EXPECT_CALL(test_mock(), DerivedIndexedGetter(4)).WillOnce(Return(100)); EXPECT_CALL(test_mock(), IndexedGetter(_)).Times(0); EXPECT_TRUE(EvaluateScript("test[4] == 100;", &result)); EXPECT_STREQ("true", result.c_str()); - EXPECT_CALL(test_mock(), length()).WillOnce(Return(10)); EXPECT_CALL(test_mock(), DerivedIndexedSetter(4, 100)); EXPECT_CALL(test_mock(), IndexedSetter(_, _)).Times(0); EXPECT_TRUE(EvaluateScript("test[4] = 100;", NULL)); @@ -356,6 +416,8 @@ } TEST_F(DerivedGetterSetterBindingsTest, NamedSetterDoesNotShadowProperties) { + EXPECT_CALL(test_mock(), CanQueryNamedProperty(_)) + .Times(::testing::AtLeast(0)); InSequence dummy; std::string result;
diff --git a/src/cobalt/bindings/testing/indexed_getter_interface.h b/src/cobalt/bindings/testing/indexed_getter_interface.h index 2b70e54..5979e8f 100644 --- a/src/cobalt/bindings/testing/indexed_getter_interface.h +++ b/src/cobalt/bindings/testing/indexed_getter_interface.h
@@ -29,6 +29,7 @@ MOCK_METHOD0(length, uint32_t()); MOCK_METHOD1(IndexedGetter, uint32_t(uint32_t)); MOCK_METHOD2(IndexedSetter, void(uint32_t, uint32_t)); + MOCK_METHOD1(IndexedDeleter, void(uint32_t)); DEFINE_WRAPPABLE_TYPE(IndexedGetterInterface); };
diff --git a/src/cobalt/bindings/testing/numeric_type_bindings_test.cc b/src/cobalt/bindings/testing/numeric_type_bindings_test.cc index d246155..88e92d0 100644 --- a/src/cobalt/bindings/testing/numeric_type_bindings_test.cc +++ b/src/cobalt/bindings/testing/numeric_type_bindings_test.cc
@@ -45,12 +45,30 @@ template <typename T> class FloatingPointTypeBindingsTest : public NumericTypeBindingsTest<T> {}; +#if defined(ENGINE_SUPPORTS_INT64) +template <typename T> +class LargeIntegerTypeBindingsTest : public NumericTypeBindingsTest<T> {}; + +typedef ::testing::Types<ByteTypeTest, OctetTypeTest, ShortTypeTest, + UnsignedShortTypeTest, LongTypeTest, + UnsignedLongTypeTest, LongLongTypeTest, + UnsignedLongLongTypeTest, DoubleTypeTest> NumericTypes; + +typedef ::testing::Types<LongLongTypeTest, UnsignedLongLongTypeTest> + LargeIntegerTypes; + +TYPED_TEST_CASE(LargeIntegerTypeBindingsTest, LargeIntegerTypes); +#else typedef ::testing::Types<ByteTypeTest, OctetTypeTest, ShortTypeTest, UnsignedShortTypeTest, LongTypeTest, UnsignedLongTypeTest, DoubleTypeTest> NumericTypes; +#endif // ENGINE_SUPPORTS_INT64 +// Not including long longs in IntegerTypes, due to different casting +// behaviours. typedef ::testing::Types<ByteTypeTest, OctetTypeTest, ShortTypeTest, UnsignedShortTypeTest, LongTypeTest, UnsignedLongTypeTest> IntegerTypes; + typedef ::testing::Types<DoubleTypeTest, UnrestrictedDoubleTypeTest> FloatingPointTypes; TYPED_TEST_CASE(NumericTypeBindingsTest, NumericTypes); @@ -141,7 +159,6 @@ EXPECT_CALL(this->test_mock(), mock_set_property(0)); EXPECT_TRUE(this->EvaluateScript( StringPrintf("test.%sProperty = 0;", TypeParam::type_string()), NULL)); - EXPECT_CALL(this->test_mock(), mock_set_property(TypeParam::min_value())); EXPECT_TRUE(this->EvaluateScript( StringPrintf("test.%sProperty = %s;", TypeParam::type_string(), @@ -210,6 +227,196 @@ NULL)); } +#if defined(ENGINE_SUPPORTS_INT64) +TYPED_TEST(LargeIntegerTypeBindingsTest, PropertyValueRange) { + InSequence in_sequence_dummy; + + std::string result; + std::string script = + StringPrintf("test.%sProperty;", TypeParam::type_string()); + + EXPECT_CALL(this->test_mock(), mock_get_property()).WillOnce(Return(0)); + EXPECT_TRUE(this->EvaluateScript(script, &result)); + EXPECT_STREQ("0", result.c_str()); + + EXPECT_CALL(this->test_mock(), mock_get_property()) + .WillOnce(Return(TypeParam::min_value())); + EXPECT_TRUE(this->EvaluateScript(script, &result)); + EXPECT_STREQ(TypeParam::min_value_string(), result.c_str()); + + EXPECT_CALL(this->test_mock(), mock_get_property()) + .WillOnce(Return(TypeParam::max_value())); + EXPECT_TRUE(this->EvaluateScript(script, &result)); + EXPECT_STREQ(TypeParam::max_value_string(), result.c_str()); +} + +// These tests require converting LargeIntegers (e.g. long long) to +// JSValues using the IDL spec: +// https://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-long-long +// This preserves exactly the range (-(2^53 - 1), 2^53 -1) and +// approximately outside that range (see the spec for details). +TYPED_TEST(LargeIntegerTypeBindingsTest, ReturnValueRange) { + InSequence in_sequence_dummy; + + // Exactly preserve 0. + std::string result; + std::string script = + StringPrintf("test.%sReturnOperation();", TypeParam::type_string()); + EXPECT_CALL(this->test_mock(), MockReturnValueOperation()) + .WillOnce(Return(0)); + EXPECT_TRUE(this->EvaluateScript(script, &result)); + EXPECT_STREQ("0", result.c_str()); + + // Approximately preserve int64_t/uint64_t min. + EXPECT_CALL(this->test_mock(), MockReturnValueOperation()) + .WillOnce(Return(TypeParam::min_value())); + EXPECT_TRUE(this->EvaluateScript(script, &result)); + EXPECT_STREQ(TypeParam::min_value_string(), result.c_str()); + + // Approximately preserve int64_t/uint64_t max. + EXPECT_CALL(this->test_mock(), MockReturnValueOperation()) + .WillOnce(Return(TypeParam::max_value())); + EXPECT_TRUE(this->EvaluateScript(script, &result)); + EXPECT_STREQ(TypeParam::max_value_string(), result.c_str()); + + // Exactly preserve 2^53 - 1. + const uint64_t kRangeBound = (1ll << 53) - 1; + std::string expected_result = StringPrintf("%" PRIu64 "", kRangeBound); + EXPECT_CALL(this->test_mock(), MockReturnValueOperation()) + .WillOnce(Return(kRangeBound)); + EXPECT_TRUE(this->EvaluateScript(script, &result)); + EXPECT_STREQ(expected_result.c_str(), result.c_str()); + + // Signed : exactly preserve -(2^53 - 1). + if (TypeParam::min_value() < 0) { + expected_result = StringPrintf("-%" PRIu64 "", kRangeBound); + EXPECT_CALL(this->test_mock(), MockReturnValueOperation()) + .WillOnce(Return(-kRangeBound)); + EXPECT_TRUE(this->EvaluateScript(script, &result)); + EXPECT_STREQ(expected_result.c_str(), result.c_str()); + } + + // Exactly preserve 9223372036854775000 (between 2^53 and int64_t max). + expected_result = "9223372036854775000"; + EXPECT_CALL(this->test_mock(), MockReturnValueOperation()) + .WillOnce(Return(9223372036854775000ll)); + EXPECT_TRUE(this->EvaluateScript(script, &result)); + EXPECT_STREQ(expected_result.c_str(), result.c_str()); + + // Unsigned : exactly preserve 18446744073709550000 (between 2^53 + // and uint64_t max). + if (TypeParam::min_value() >= 0) { + expected_result = "18446744073709550000"; + EXPECT_CALL(this->test_mock(), MockReturnValueOperation()) + .WillOnce(Return(18446744073709550000l)); + EXPECT_TRUE(this->EvaluateScript(script, &result)); + EXPECT_STREQ(expected_result.c_str(), result.c_str()); + } +} + +// These tests require converting JSValues to LargeIntegers (e.g. long long) +// using the IDL spec: +// https://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-long-long +// This preserves exactly the range (-(2^53 - 1), 2^53 -1), +// and for all other values does the following: +// For input value V. +// x = ToNumber(V) +// If x is Nan, +inf, -inf return 0 +// ...Handle extended_attribute special cases... +// 5. x = sign(x) * floor(abs(x)) +// 6. x = x mod 2^64 +// 7. If x >= 2^63, x = x - 2^64 (for signed only) +// 8. Return the IDL long long value that represents the same numeric +// value as x. +TYPED_TEST(LargeIntegerTypeBindingsTest, SetPropertyRange) { + InSequence in_sequence_dummy; + + // Exactly preserve 0. + EXPECT_CALL(this->test_mock(), mock_set_property(0)); + EXPECT_TRUE(this->EvaluateScript( + StringPrintf("test.%sProperty = 0;", TypeParam::type_string()), NULL)); + + // Exactly preserve 2^53 - 1. + EXPECT_CALL(this->test_mock(), mock_set_property((1ll << 53) - 1)); + EXPECT_TRUE( + this->EvaluateScript(StringPrintf("test.%sProperty = 9007199254740991;", + TypeParam::type_string()), + NULL)); + + // Signed : exactly preserve -(2^53 - 1). + if (TypeParam::min_value() < 0) { + EXPECT_CALL(this->test_mock(), mock_set_property(-((1ll << 53) - 1))); + EXPECT_TRUE(this->EvaluateScript( + StringPrintf("test.%sProperty = -9007199254740991;", + TypeParam::type_string()), + NULL)); + } + + // Send 9223372036854775000 (between 2^53 and int64_t max) to + // 9223372036854774784. + EXPECT_CALL(this->test_mock(), mock_set_property(9223372036854774784)); + EXPECT_TRUE(this->EvaluateScript( + StringPrintf("test.%sProperty = 9223372036854775000;", + TypeParam::type_string()), + NULL)); + + // Unsigned : send 18446744073709550000 (between 2^53 + // and uint64_t max) to 18446744073709549568. + if (TypeParam::min_value() >= 0) { + EXPECT_CALL(this->test_mock(), mock_set_property(18446744073709549568)); + EXPECT_TRUE(this->EvaluateScript( + StringPrintf("test.%sProperty = 18446744073709550000;", + TypeParam::type_string()), + NULL)); + } +} + +// These tests also rely on FromJSValue (similar to above). +TYPED_TEST(LargeIntegerTypeBindingsTest, ArgumentOperationRange) { + InSequence in_sequence_dummy; + + // Exactly preserve 0. + EXPECT_CALL(this->test_mock(), MockArgumentOperation(0)); + EXPECT_TRUE(this->EvaluateScript( + StringPrintf("test.%sArgumentOperation(0);", TypeParam::type_string()), + NULL)); + + // Exactly preserve 2^53 - 1. + EXPECT_CALL(this->test_mock(), MockArgumentOperation((1ll << 53) - 1)); + EXPECT_TRUE(this->EvaluateScript( + StringPrintf("test.%sArgumentOperation(9007199254740991);", + TypeParam::type_string()), + NULL)); + + // Signed : exactly preserve -(2^53 - 1). + if (TypeParam::min_value() < 0) { + EXPECT_CALL(this->test_mock(), MockArgumentOperation(-((1ll << 53) - 1))); + EXPECT_TRUE(this->EvaluateScript( + StringPrintf("test.%sArgumentOperation(-9007199254740991);", + TypeParam::type_string()), + NULL)); + } + + // Send 9223372036854775000 (between 2^53 and int64_t max) to + // 9223372036854774784. + EXPECT_CALL(this->test_mock(), MockArgumentOperation(9223372036854774784)); + EXPECT_TRUE(this->EvaluateScript( + StringPrintf("test.%sArgumentOperation(9223372036854775000);", + TypeParam::type_string()), + NULL)); + + // Unsigned : send 18446744073709550000 (between 2^53 + // and uint64_t max) to 18446744073709549568. + if (TypeParam::min_value() >= 0) { + EXPECT_CALL(this->test_mock(), MockArgumentOperation(18446744073709549568)); + EXPECT_TRUE(this->EvaluateScript( + StringPrintf("test.%sArgumentOperation(18446744073709550000);", + TypeParam::type_string()), + NULL)); + } +} +#endif // ENGINE_SUPPORTS_INT64 + TYPED_TEST(FloatingPointTypeBindingsTest, NonFiniteValues) { InSequence in_sequence_dummy; if (TypeParam::is_restricted()) {
diff --git a/src/cobalt/bindings/testing/numeric_types_test_interface.h b/src/cobalt/bindings/testing/numeric_types_test_interface.h index 6d752f5..713dea5 100644 --- a/src/cobalt/bindings/testing/numeric_types_test_interface.h +++ b/src/cobalt/bindings/testing/numeric_types_test_interface.h
@@ -17,6 +17,8 @@ #ifndef COBALT_BINDINGS_TESTING_NUMERIC_TYPES_TEST_INTERFACE_H_ #define COBALT_BINDINGS_TESTING_NUMERIC_TYPES_TEST_INTERFACE_H_ +#include <limits> + #include "cobalt/script/wrappable.h" #include "testing/gmock/include/gmock/gmock.h" @@ -56,6 +58,16 @@ virtual uint32_t unsigned_long_property() { return 0; } virtual void set_unsigned_long_property(uint32_t value) {} + virtual int64_t LongLongReturnOperation() { return 0; } + virtual void LongLongArgumentOperation(int64_t value) {} + virtual int64_t long_long_property() { return 0; } + virtual void set_long_long_property(int64_t value) {} + + virtual uint64_t UnsignedLongLongReturnOperation() { return 0; } + virtual void UnsignedLongLongArgumentOperation(uint64_t value) {} + virtual uint64_t unsigned_long_long_property() { return 0; } + virtual void set_unsigned_long_long_property(uint64_t value) {} + virtual double DoubleReturnOperation() { return 0; } virtual void DoubleArgumentOperation(double value) {} virtual double double_property() { return 0; } @@ -195,6 +207,53 @@ static const char* min_value_string() { return "0"; } }; +#if defined(ENGINE_SUPPORTS_INT64) +class LongLongTypeTest : public NumericTypesTestInterfaceT<int64_t> { + public: + int64_t LongLongReturnOperation() OVERRIDE { + return MockReturnValueOperation(); + } + void LongLongArgumentOperation(int64_t value) OVERRIDE { + MockArgumentOperation(value); + } + int64_t long_long_property() OVERRIDE { return mock_get_property(); } + void set_long_long_property(int64_t value) OVERRIDE { + mock_set_property(value); + } + + static const char* type_string() { return "longLong"; } + static int64_t max_value() { return 9223372036854775807ll; } + static int64_t min_value() { return -9223372036854775807ll - 1; } + // This is what 9223372036854775807 maps to in javascript. + static const char* max_value_string() { return "9223372036854776000"; } + static const char* min_value_string() { return "-9223372036854776000"; } +}; + +class UnsignedLongLongTypeTest : public NumericTypesTestInterfaceT<uint64_t> { + public: + uint64_t UnsignedLongLongReturnOperation() OVERRIDE { + return MockReturnValueOperation(); + } + void UnsignedLongLongArgumentOperation(uint64_t value) OVERRIDE { + MockArgumentOperation(value); + } + uint64_t unsigned_long_long_property() OVERRIDE { + return mock_get_property(); + } + void set_unsigned_long_long_property(uint64_t value) OVERRIDE { + mock_set_property(value); + } + + static const char* type_string() { return "unsignedLongLong"; } + + static uint64_t max_value() { return 18446744073709551615; } + static uint64_t min_value() { return 0; } + // This is what the value 18446744073709551615 maps to in javascript. + static const char* max_value_string() { return "18446744073709552000"; } + static const char* min_value_string() { return "0"; } +}; +#endif // ENGINE_SUPPORTS_INT64 + class DoubleTypeTest : public NumericTypesTestInterfaceT<double> { public: double DoubleReturnOperation() OVERRIDE { return MockReturnValueOperation(); }
diff --git a/src/cobalt/bindings/testing/object_type_bindings_test.cc b/src/cobalt/bindings/testing/object_type_bindings_test.cc index 618dd5f..3747719 100644 --- a/src/cobalt/bindings/testing/object_type_bindings_test.cc +++ b/src/cobalt/bindings/testing/object_type_bindings_test.cc
@@ -85,6 +85,7 @@ EXPECT_STREQ("[object ArbitraryInterfacePrototype]", result.c_str()); } +#if defined(ENGINE_DEFINES_ATTRIBUTES_ON_OBJECT) TEST_F(PlatformObjectBindingsTest, PropertyIsOwnProperty) { EXPECT_CALL(test_mock(), arbitrary_object()); @@ -93,6 +94,18 @@ "test.arbitraryObject.hasOwnProperty(\"arbitraryProperty\");", &result)); EXPECT_STREQ("true", result.c_str()); } +#else +TEST_F(PlatformObjectBindingsTest, PropertyIsDefinedOnPrototype) { + EXPECT_CALL(test_mock(), arbitrary_object()); + + std::string result; + EXPECT_TRUE(EvaluateScript( + "Object.getPrototypeOf(test.arbitraryObject).hasOwnProperty(" + "\"arbitraryProperty\");", + &result)); + EXPECT_STREQ("true", result.c_str()); +} +#endif // defined(ENGINE_DEFINES_ATTRIBUTES_ON_OBJECT) TEST_F(PlatformObjectBindingsTest, MemberFunctionIsPrototypeProperty) { EXPECT_CALL(test_mock(), arbitrary_object()).Times(3);
diff --git a/src/cobalt/bindings/testing/operations_bindings_test.cc b/src/cobalt/bindings/testing/operations_bindings_test.cc index a6f7288..a875c45 100644 --- a/src/cobalt/bindings/testing/operations_bindings_test.cc +++ b/src/cobalt/bindings/testing/operations_bindings_test.cc
@@ -168,10 +168,17 @@ } TEST_F(OperationsBindingsTest, StaticMethodNotPartOfOverloadSet) { + InSequence in_sequence_dummy; + EXPECT_CALL(OperationsTestInterface::static_methods_mock.Get(), OverloadedFunction(_)); EXPECT_TRUE( EvaluateScript("OperationsTestInterface.overloadedFunction(6.1);", NULL)); + + EXPECT_CALL(OperationsTestInterface::static_methods_mock.Get(), + OverloadedFunction(_, _)); + EXPECT_TRUE(EvaluateScript( + "OperationsTestInterface.overloadedFunction(4, 8);", NULL)); } TEST_F(OperationsBindingsTest, OverloadedOperationByOptionality) {
diff --git a/src/cobalt/bindings/testing/operations_test_interface.h b/src/cobalt/bindings/testing/operations_test_interface.h index 7294491..05b4e7e 100644 --- a/src/cobalt/bindings/testing/operations_test_interface.h +++ b/src/cobalt/bindings/testing/operations_test_interface.h
@@ -35,6 +35,7 @@ class StaticMethodsMock { public: MOCK_METHOD1(OverloadedFunction, void(double)); + MOCK_METHOD2(OverloadedFunction, void(double, double)); }; MOCK_METHOD0(VoidFunctionNoArgs, void()); @@ -73,6 +74,10 @@ static_methods_mock.Get().OverloadedFunction(arg); } + static void OverloadedFunction(double arg1, double arg2) { + static_methods_mock.Get().OverloadedFunction(arg1, arg2); + } + MOCK_METHOD1(OverloadedNullable, void(int32_t)); MOCK_METHOD1(OverloadedNullable, void(base::optional<bool>));
diff --git a/src/cobalt/bindings/testing/put_forwards_interface.cc b/src/cobalt/bindings/testing/put_forwards_interface.cc new file mode 100644 index 0000000..cfe82b1 --- /dev/null +++ b/src/cobalt/bindings/testing/put_forwards_interface.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 "cobalt/bindings/testing/put_forwards_interface.h" + +namespace cobalt { +namespace bindings { +namespace testing { + +base::LazyInstance< + ::testing::StrictMock<PutForwardsInterface::StaticMethodsMock> > + PutForwardsInterface::static_methods_mock = LAZY_INSTANCE_INITIALIZER; + +} // namespace testing +} // namespace bindings +} // namespace cobalt
diff --git a/src/cobalt/bindings/testing/put_forwards_interface.h b/src/cobalt/bindings/testing/put_forwards_interface.h index baa7b60..a91ef19 100644 --- a/src/cobalt/bindings/testing/put_forwards_interface.h +++ b/src/cobalt/bindings/testing/put_forwards_interface.h
@@ -17,6 +17,7 @@ #ifndef COBALT_BINDINGS_TESTING_PUT_FORWARDS_INTERFACE_H_ #define COBALT_BINDINGS_TESTING_PUT_FORWARDS_INTERFACE_H_ +#include "base/lazy_instance.h" #include "cobalt/bindings/testing/arbitrary_interface.h" #include "cobalt/script/wrappable.h" #include "testing/gmock/include/gmock/gmock.h" @@ -27,9 +28,22 @@ class PutForwardsInterface : public script::Wrappable { public: + class StaticMethodsMock { + public: + MOCK_METHOD0(static_forwarding_attribute, + scoped_refptr<ArbitraryInterface>(void)); + }; + MOCK_METHOD0(forwarding_attribute, scoped_refptr<ArbitraryInterface>()); + static scoped_refptr<ArbitraryInterface> static_forwarding_attribute() { + return static_methods_mock.Get().static_forwarding_attribute(); + } + DEFINE_WRAPPABLE_TYPE(PutForwardsInterface); + + static base::LazyInstance< ::testing::StrictMock<StaticMethodsMock> > + static_methods_mock; }; } // namespace testing
diff --git a/src/cobalt/bindings/testing/put_forwards_test.cc b/src/cobalt/bindings/testing/put_forwards_test.cc index ab7aa18..c9d1359 100644 --- a/src/cobalt/bindings/testing/put_forwards_test.cc +++ b/src/cobalt/bindings/testing/put_forwards_test.cc
@@ -43,6 +43,17 @@ EXPECT_TRUE(EvaluateScript("test.forwardingAttribute = 'apple';", NULL)); } +TEST_F(PutForwardsTest, StaticForwardsToInterface) { + scoped_refptr<StrictMock<ArbitraryInterface> > arbitrary_interface_mock( + new StrictMock<ArbitraryInterface>()); + EXPECT_CALL(PutForwardsInterface::static_methods_mock.Get(), + static_forwarding_attribute()) + .WillOnce(Return(arbitrary_interface_mock)); + EXPECT_CALL(*arbitrary_interface_mock, set_arbitrary_property("orange")); + EXPECT_TRUE(EvaluateScript( + "PutForwardsInterface.staticForwardingAttribute = 'orange';", NULL)); +} + TEST_F(NestedPutForwardsTest, ForwardsToNestedInterface) { scoped_refptr<StrictMock<PutForwardsInterface> > puts_forward_interface_mock( new StrictMock<PutForwardsInterface>());
diff --git a/src/cobalt/bindings/testing/static_properties_bindings_test.cc b/src/cobalt/bindings/testing/static_properties_bindings_test.cc index ae66885..51fe181 100644 --- a/src/cobalt/bindings/testing/static_properties_bindings_test.cc +++ b/src/cobalt/bindings/testing/static_properties_bindings_test.cc
@@ -19,6 +19,9 @@ #include "testing/gtest/include/gtest/gtest.h" +using ::testing::_; +using ::testing::A; +using ::testing::InSequence; using ::testing::Return; namespace cobalt { @@ -38,6 +41,43 @@ EvaluateScript("StaticPropertiesInterface.staticFunction();", NULL)); } +TEST_F(StaticPropertiesBindingsTest, + StaticOverloadedOperationByNumberOfArguments) { + InSequence in_sequence_dummy; + + EXPECT_CALL(StaticPropertiesInterface::static_methods_mock.Get(), + StaticFunction()); + EXPECT_TRUE( + EvaluateScript("StaticPropertiesInterface.staticFunction();", NULL)); + + EXPECT_CALL(StaticPropertiesInterface::static_methods_mock.Get(), + StaticFunction(_, _, A<int32_t>())); + EXPECT_TRUE(EvaluateScript( + "StaticPropertiesInterface.staticFunction(6, 8, 9);", NULL)); + + EXPECT_CALL( + StaticPropertiesInterface::static_methods_mock.Get(), + StaticFunction(_, _, A<const scoped_refptr<ArbitraryInterface>&>())); + EXPECT_TRUE( + EvaluateScript("StaticPropertiesInterface.staticFunction(6, 8, new " + "ArbitraryInterface());", + NULL)); +} + +TEST_F(StaticPropertiesBindingsTest, StaticOverloadedOperationByType) { + InSequence in_sequence_dummy; + + EXPECT_CALL(StaticPropertiesInterface::static_methods_mock.Get(), + StaticFunction(A<int32_t>())); + EXPECT_TRUE( + EvaluateScript("StaticPropertiesInterface.staticFunction(4);", NULL)); + + EXPECT_CALL(StaticPropertiesInterface::static_methods_mock.Get(), + StaticFunction(A<const std::string&>())); + EXPECT_TRUE(EvaluateScript( + "StaticPropertiesInterface.staticFunction(\"foo\");", NULL)); +} + TEST_F(StaticPropertiesBindingsTest, GetStaticAttribute) { std::string result; EXPECT_CALL(StaticPropertiesInterface::static_methods_mock.Get(),
diff --git a/src/cobalt/bindings/testing/static_properties_interface.h b/src/cobalt/bindings/testing/static_properties_interface.h index 2c67a48..5abd47a 100644 --- a/src/cobalt/bindings/testing/static_properties_interface.h +++ b/src/cobalt/bindings/testing/static_properties_interface.h
@@ -17,7 +17,10 @@ #ifndef COBALT_BINDINGS_TESTING_STATIC_PROPERTIES_INTERFACE_H_ #define COBALT_BINDINGS_TESTING_STATIC_PROPERTIES_INTERFACE_H_ +#include <string> + #include "base/lazy_instance.h" +#include "cobalt/bindings/testing/arbitrary_interface.h" #include "cobalt/script/wrappable.h" #include "testing/gmock/include/gmock/gmock.h" @@ -30,10 +33,30 @@ class StaticMethodsMock { public: MOCK_METHOD0(StaticFunction, void()); + MOCK_METHOD1(StaticFunction, void(int32_t)); + MOCK_METHOD1(StaticFunction, void(const std::string&)); + MOCK_METHOD3(StaticFunction, void(int32_t, int32_t, int32_t)); + MOCK_METHOD3(StaticFunction, + void(int32_t, int32_t, + const scoped_refptr<ArbitraryInterface>&)); MOCK_METHOD0(static_attribute, std::string()); MOCK_METHOD1(set_static_attribute, void(const std::string&)); }; + static void StaticFunction() { static_methods_mock.Get().StaticFunction(); } + static void StaticFunction(int32_t arg) { + static_methods_mock.Get().StaticFunction(arg); + } + static void StaticFunction(const std::string& arg) { + static_methods_mock.Get().StaticFunction(arg); + } + static void StaticFunction(int32_t arg1, int32_t arg2, int32_t arg3) { + static_methods_mock.Get().StaticFunction(arg1, arg2, arg3); + } + static void StaticFunction(int32_t arg1, int32_t arg2, + const scoped_refptr<ArbitraryInterface>& arg3) { + static_methods_mock.Get().StaticFunction(arg1, arg2, arg3); + } static std::string static_attribute() { return static_methods_mock.Get().static_attribute(); }
diff --git a/src/cobalt/bindings/testing/testing.gyp b/src/cobalt/bindings/testing/testing.gyp index 3f1e0c2..49c20e4 100644 --- a/src/cobalt/bindings/testing/testing.gyp +++ b/src/cobalt/bindings/testing/testing.gyp
@@ -104,6 +104,7 @@ 'exceptions_interface.cc', 'named_constructor_interface.cc', 'operations_test_interface.cc', + 'put_forwards_interface.cc', 'static_properties_interface.cc', ], 'defines': [ '<@(bindings_defines)'], @@ -165,7 +166,7 @@ 'variables': { 'executable_name': 'bindings_test', }, - 'includes': [ '../../build/deploy.gypi' ], + 'includes': [ '../../../starboard/build/deploy.gypi' ], }, { @@ -192,7 +193,7 @@ 'variables': { 'executable_name': 'bindings_sandbox', }, - 'includes': [ '../../build/deploy.gypi' ], + 'includes': [ '../../../starboard/build/deploy.gypi' ], }, ], }
diff --git a/src/cobalt/bindings/testing/union_type_bindings_test.cc b/src/cobalt/bindings/testing/union_type_bindings_test.cc index 559678d..e4593a2 100644 --- a/src/cobalt/bindings/testing/union_type_bindings_test.cc +++ b/src/cobalt/bindings/testing/union_type_bindings_test.cc
@@ -94,6 +94,47 @@ EXPECT_TRUE(union_type.AsType<scoped_refptr<ArbitraryInterface> >()); } +TEST_F(UnionTypesBindingsTest, ConvertFromJSInvalid) { + InSequence dummy; + + UnionTypesInterface::UnionBasePropertyType union_base_type; + // Try to assign wrong interface type. + // First assign a valid value. + EXPECT_CALL(test_mock(), set_union_base_property(_)) + .WillOnce(SaveArg<0>(&union_base_type)); + EXPECT_TRUE( + EvaluateScript("test.unionBaseProperty = \"string type\";", NULL)); + ASSERT_TRUE(union_base_type.IsType<std::string>()); + EXPECT_EQ("string type", union_base_type.AsType<std::string>()); + // Attempt to assign invalid value. + EXPECT_FALSE(EvaluateScript( + "test.unionBaseProperty = new EnumerationInterface();", NULL)); + // Check the original value was preserved. + ASSERT_TRUE(union_base_type.IsType<std::string>()); + EXPECT_EQ("string type", union_base_type.AsType<std::string>()); +} + +TEST_F(UnionTypesBindingsTest, ConvertFromJSInherit) { + InSequence dummy; + + UnionTypesInterface::UnionBasePropertyType union_base_type; + // Assign with base. + EXPECT_CALL(test_mock(), set_union_base_property(_)) + .WillOnce(SaveArg<0>(&union_base_type)); + EXPECT_TRUE( + EvaluateScript("test.unionBaseProperty = new BaseInterface();", NULL)); + ASSERT_TRUE(union_base_type.IsType<scoped_refptr<BaseInterface> >()); + EXPECT_TRUE(union_base_type.AsType<scoped_refptr<BaseInterface> >()); + + // Assign with derived. + EXPECT_CALL(test_mock(), set_union_base_property(_)) + .WillOnce(SaveArg<0>(&union_base_type)); + EXPECT_TRUE( + EvaluateScript("test.unionBaseProperty = new DerivedInterface();", NULL)); + ASSERT_TRUE(union_base_type.IsType<scoped_refptr<BaseInterface> >()); + EXPECT_TRUE(union_base_type.AsType<scoped_refptr<BaseInterface> >()); +} + TEST_F(UnionTypesBindingsTest, SetNullableUnion) { InSequence dummy;
diff --git a/src/cobalt/bindings/testing/union_types_interface.h b/src/cobalt/bindings/testing/union_types_interface.h index c631d36..7d0f7c1 100644 --- a/src/cobalt/bindings/testing/union_types_interface.h +++ b/src/cobalt/bindings/testing/union_types_interface.h
@@ -17,7 +17,10 @@ #ifndef COBALT_BINDINGS_TESTING_UNION_TYPES_INTERFACE_H_ #define COBALT_BINDINGS_TESTING_UNION_TYPES_INTERFACE_H_ +#include <string> + #include "cobalt/bindings/testing/arbitrary_interface.h" +#include "cobalt/bindings/testing/base_interface.h" #include "cobalt/script/union_type.h" #include "cobalt/script/wrappable.h" #include "testing/gmock/include/gmock/gmock.h" @@ -33,6 +36,9 @@ int32_t> UnionPropertyType; typedef base::optional<script::UnionType2<double, std::string> > NullableUnionPropertyType; + typedef script::UnionType2<scoped_refptr<BaseInterface>, std::string> + UnionBasePropertyType; + MOCK_METHOD0(union_property, UnionPropertyType()); MOCK_METHOD1(set_union_property, void(const UnionPropertyType&)); @@ -45,6 +51,9 @@ MOCK_METHOD1(set_nullable_union_property, void(const NullableUnionPropertyType&)); + MOCK_METHOD0(union_base_property, UnionBasePropertyType()); + MOCK_METHOD1(set_union_base_property, void(const UnionBasePropertyType&)); + DEFINE_WRAPPABLE_TYPE(UnionTypesInterface); };
diff --git a/src/cobalt/browser/application.cc b/src/cobalt/browser/application.cc index 41ae68b..5ec73ec 100644 --- a/src/cobalt/browser/application.cc +++ b/src/cobalt/browser/application.cc
@@ -165,6 +165,31 @@ loader::image::ImageDecoder::UseStubImageDecoder(); } } + +void SetIntegerIfSwitchIsSet(const char* switch_name, int* output) { + if (CommandLine::ForCurrentProcess()->HasSwitch(switch_name)) { + int32 out; + if (base::StringToInt32( + CommandLine::ForCurrentProcess()->GetSwitchValueNative(switch_name), + &out)) { + LOG(INFO) << "Command line switch '" << switch_name << "': Modifying " + << *output << " -> " << out; + *output = out; + } else { + LOG(ERROR) << "Invalid value for command line setting: " << switch_name; + } + } +} + +void ApplyCommandLineSettingsToRendererOptions( + renderer::RendererModule::Options* options) { + SetIntegerIfSwitchIsSet(browser::switches::kSurfaceCacheSizeInBytes, + &options->surface_cache_size_in_bytes); + SetIntegerIfSwitchIsSet(browser::switches::kScratchSurfaceCacheSizeInBytes, + &options->scratch_surface_cache_size_in_bytes); + SetIntegerIfSwitchIsSet(browser::switches::kSkiaCacheSizeInBytes, + &options->skia_cache_size_in_bytes); +} #endif // ENABLE_COMMAND_LINE_SWITCHES // Restrict navigation to a couple of whitelisted URLs by default. @@ -264,6 +289,8 @@ options.network_module_options.preferred_language = language; #if defined(ENABLE_COMMAND_LINE_SWITCHES) + ApplyCommandLineSettingsToRendererOptions(&options.renderer_module_options); + if (CommandLine::ForCurrentProcess()->HasSwitch( browser::switches::kNullSavegame)) { options.storage_manager_options.savegame_options.factory = @@ -499,19 +526,25 @@ if (app_event->type() == system_window::ApplicationEvent::kQuit) { DLOG(INFO) << "Got quit event."; app_status_ = kWillQuitAppStatus; +#if !defined(OS_STARBOARD) browser_module_->SetWillQuit(); browser_module_->SetPaused(false); +#endif // !defined(OS_STARBOARD) Quit(); } else if (app_event->type() == system_window::ApplicationEvent::kSuspend) { DLOG(INFO) << "Got suspend event."; app_status_ = kPausedAppStatus; ++app_suspend_count_; +#if !defined(OS_STARBOARD) browser_module_->SetPaused(true); +#endif // !defined(OS_STARBOARD) } else if (app_event->type() == system_window::ApplicationEvent::kResume) { DLOG(INFO) << "Got resume event."; app_status_ = kRunningAppStatus; ++app_resume_count_; +#if !defined(OS_STARBOARD) browser_module_->SetPaused(false); +#endif // !defined(OS_STARBOARD) } }
diff --git a/src/cobalt/browser/browser_bindings.gyp b/src/cobalt/browser/browser_bindings.gyp index 2892de9..45d7061 100644 --- a/src/cobalt/browser/browser_bindings.gyp +++ b/src/cobalt/browser/browser_bindings.gyp
@@ -21,6 +21,10 @@ # be generated. 'bindings_output_dir': '<(SHARED_INTERMEDIATE_DIR)/bindings/browser', + 'bindings_dependencies': [ + '../h5vcc/h5vcc.gyp:h5vcc', + ], + # Bindings for the interfaces in this list will be generated, and there must # be an implementation declared in a header that lives in the same # directory of each IDL. @@ -144,6 +148,7 @@ '../h5vcc/dial/DialServer.idl', '../h5vcc/H5vcc.idl', '../h5vcc/H5vccAccountInfo.idl', + '../h5vcc/H5vccAccountManager.idl', '../h5vcc/H5vccAudioConfig.idl', '../h5vcc/H5vccAudioConfigArray.idl', '../h5vcc/H5vccCVal.idl',
diff --git a/src/cobalt/browser/cobalt.gyp b/src/cobalt/browser/cobalt.gyp index 46bad3a..4f73099 100644 --- a/src/cobalt/browser/cobalt.gyp +++ b/src/cobalt/browser/cobalt.gyp
@@ -57,7 +57,7 @@ 'variables': { 'executable_name': 'cobalt', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, { 'target_name': 'snapshot_app_stats', @@ -90,7 +90,7 @@ 'variables': { 'executable_name': 'snapshot_app_stats', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, ],
diff --git a/src/cobalt/browser/global_constructors_idls_idl_files_list.tmp b/src/cobalt/browser/global_constructors_idls_idl_files_list.tmp index cf004c2..b9f074d 100644 --- a/src/cobalt/browser/global_constructors_idls_idl_files_list.tmp +++ b/src/cobalt/browser/global_constructors_idls_idl_files_list.tmp
@@ -113,6 +113,7 @@ ../h5vcc/dial/DialServer.idl ../h5vcc/H5vcc.idl ../h5vcc/H5vccAccountInfo.idl +../h5vcc/H5vccAccountManager.idl ../h5vcc/H5vccAudioConfig.idl ../h5vcc/H5vccAudioConfigArray.idl ../h5vcc/H5vccCVal.idl
diff --git a/src/cobalt/browser/global_objects_idl_files_list.tmp b/src/cobalt/browser/global_objects_idl_files_list.tmp index cf004c2..b9f074d 100644 --- a/src/cobalt/browser/global_objects_idl_files_list.tmp +++ b/src/cobalt/browser/global_objects_idl_files_list.tmp
@@ -113,6 +113,7 @@ ../h5vcc/dial/DialServer.idl ../h5vcc/H5vcc.idl ../h5vcc/H5vccAccountInfo.idl +../h5vcc/H5vccAccountManager.idl ../h5vcc/H5vccAudioConfig.idl ../h5vcc/H5vccAudioConfigArray.idl ../h5vcc/H5vccCVal.idl
diff --git a/src/cobalt/browser/h5vcc_url_handler.cc b/src/cobalt/browser/h5vcc_url_handler.cc index d15a55e..18ba0c6 100644 --- a/src/cobalt/browser/h5vcc_url_handler.cc +++ b/src/cobalt/browser/h5vcc_url_handler.cc
@@ -19,7 +19,6 @@ #include <string> #include "base/bind.h" -#include "cobalt/base/localized_strings.h" #include "cobalt/browser/browser_module.h" namespace cobalt { @@ -78,15 +77,6 @@ const char kAgeRestricted[] = "age-restricted"; const char kRetryParam[] = "retry-url"; - -const char kNetworkFailureMessageId[] = "UNABLE_TO_CONTACT_YOUTUBE"; -const char kNetworkFailureMessageFallback[] = "Unable to contact YouTube"; -const char kSignedOutMessageId[] = "OFFLINE_MESSAGE_1"; -const char kSignedOutMessageFallback[] = - "You are signed out of PSN. To use YouTube, you need to sign in to PSN."; -const char kAgeRestrictedMessageId[] = "AGE_RESTRICTED"; -const char kAgeRestrictedMessageFallback[] = - "YouTube is not intended for use by children under 13."; } // namespace H5vccURLHandler::H5vccURLHandler(BrowserModule* browser_module, @@ -118,9 +108,8 @@ bool H5vccURLHandler::HandleNetworkFailure() { system_window::SystemWindow::DialogOptions dialog_options; - dialog_options.message = base::LocalizedStrings::GetInstance()->GetString( - kNetworkFailureMessageId, kNetworkFailureMessageFallback); - dialog_options.num_buttons = 1; + dialog_options.message_code = + system_window::SystemWindow::kDialogConnectionError; dialog_options.callback = base::Bind( &H5vccURLHandler::OnNetworkFailureDialogResponse, base::Unretained(this)); system_window_->ShowDialog(dialog_options); @@ -129,9 +118,8 @@ bool H5vccURLHandler::HandleSignedOut() { system_window::SystemWindow::DialogOptions dialog_options; - dialog_options.message = base::LocalizedStrings::GetInstance()->GetString( - kSignedOutMessageId, kSignedOutMessageFallback); - dialog_options.num_buttons = 1; + dialog_options.message_code = + system_window::SystemWindow::kDialogUserSignedOut; dialog_options.callback = base::Bind( &H5vccURLHandler::OnSignedOutDialogResponse, base::Unretained(this)); system_window_->ShowDialog(dialog_options); @@ -140,9 +128,8 @@ bool H5vccURLHandler::HandleAgeRestricted() { system_window::SystemWindow::DialogOptions dialog_options; - dialog_options.message = base::LocalizedStrings::GetInstance()->GetString( - kAgeRestrictedMessageId, kAgeRestrictedMessageFallback); - dialog_options.num_buttons = 0; + dialog_options.message_code = + system_window::SystemWindow::kDialogUserAgeRestricted; system_window_->ShowDialog(dialog_options); return true; }
diff --git a/src/cobalt/browser/interfaces_info_individual_static_idl_files_list.tmp b/src/cobalt/browser/interfaces_info_individual_static_idl_files_list.tmp index 2c03040..86c81b6 100644 --- a/src/cobalt/browser/interfaces_info_individual_static_idl_files_list.tmp +++ b/src/cobalt/browser/interfaces_info_individual_static_idl_files_list.tmp
@@ -113,6 +113,7 @@ ../h5vcc/dial/DialServer.idl ../h5vcc/H5vcc.idl ../h5vcc/H5vccAccountInfo.idl +../h5vcc/H5vccAccountManager.idl ../h5vcc/H5vccAudioConfig.idl ../h5vcc/H5vccAudioConfigArray.idl ../h5vcc/H5vccCVal.idl
diff --git a/src/cobalt/browser/main.cc b/src/cobalt/browser/main.cc index 9f25b03..ef98aff 100644 --- a/src/cobalt/browser/main.cc +++ b/src/cobalt/browser/main.cc
@@ -19,6 +19,7 @@ #include "cobalt/base/wrap_main.h" #include "cobalt/browser/application.h" #if defined(OS_STARBOARD) +#include "cobalt/browser/starboard/event_handler.h" #include "cobalt/system_window/starboard/system_window.h" #endif @@ -43,7 +44,7 @@ #if defined(OS_STARBOARD) COBALT_WRAP_EVENT_MAIN(StartApplication, - cobalt::system_window::HandleInputEvent, + cobalt::browser::EventHandler::HandleEvent, StopApplication); #else COBALT_WRAP_BASE_MAIN(StartApplication, StopApplication);
diff --git a/src/cobalt/browser/starboard/application.cc b/src/cobalt/browser/starboard/application.cc index dc50b6f..97bd985 100644 --- a/src/cobalt/browser/starboard/application.cc +++ b/src/cobalt/browser/starboard/application.cc
@@ -16,6 +16,8 @@ #include "cobalt/browser/application.h" +#include "base/memory/scoped_ptr.h" +#include "cobalt/browser/starboard/event_handler.h" #include "starboard/system.h" namespace cobalt { @@ -24,8 +26,13 @@ class ApplicationStarboard : public Application { public: explicit ApplicationStarboard(const base::Closure& quit_closure) - : Application(quit_closure) {} + : Application(quit_closure), event_handler_(&event_dispatcher_) {} ~ApplicationStarboard() OVERRIDE {} + + private: + // Event handler to receive Starboard events, convert to Cobalt events + // and dispatch to the rest of the system. + EventHandler event_handler_; }; scoped_ptr<Application> CreateApplication(const base::Closure& quit_closure) {
diff --git a/src/cobalt/browser/starboard/event_handler.cc b/src/cobalt/browser/starboard/event_handler.cc new file mode 100644 index 0000000..4ef7069 --- /dev/null +++ b/src/cobalt/browser/starboard/event_handler.cc
@@ -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. + */ + +#include "cobalt/browser/starboard/event_handler.h" + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "cobalt/system_window/application_event.h" +#include "cobalt/system_window/starboard/system_window.h" + +namespace cobalt { +namespace browser { + +namespace { +EventHandler* g_the_event_handler = NULL; +} // namespace + +EventHandler::EventHandler(base::EventDispatcher* event_dispatcher) + : event_dispatcher_(event_dispatcher) { + DCHECK(!g_the_event_handler) << "There should be only one event handler."; + g_the_event_handler = this; +} + +// static +void EventHandler::HandleEvent(const SbEvent* starboard_event) { + DCHECK(starboard_event); + + // Forward input events to |SystemWindow|. + if (starboard_event->type == kSbEventTypeInput) { + system_window::HandleInputEvent(starboard_event); + return; + } + + // Handle all other events internally. + DCHECK(g_the_event_handler); + g_the_event_handler->DispatchEvent(starboard_event); +} + +void EventHandler::DispatchEvent(const SbEvent* starboard_event) const { + // Create a Cobalt event from the Starboard event, if recognized. + scoped_ptr<base::Event> cobalt_event; + if (starboard_event->type == kSbEventTypeResume) { + cobalt_event.reset(new system_window::ApplicationEvent( + system_window::ApplicationEvent::kResume)); + } else if (starboard_event->type == kSbEventTypeSuspend) { + cobalt_event.reset(new system_window::ApplicationEvent( + system_window::ApplicationEvent::kSuspend)); + } + + // Dispatch the Cobalt event, if created. + if (cobalt_event) { + event_dispatcher_->DispatchEvent(cobalt_event.Pass()); + } else { + DLOG(WARNING) << "Unhandled Starboard event of type: " + << starboard_event->type; + } +} + +} // namespace browser +} // namespace cobalt
diff --git a/src/cobalt/browser/starboard/event_handler.h b/src/cobalt/browser/starboard/event_handler.h new file mode 100644 index 0000000..ed11064 --- /dev/null +++ b/src/cobalt/browser/starboard/event_handler.h
@@ -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. + */ + +#ifndef COBALT_BROWSER_STARBOARD_EVENT_HANDLER_H_ +#define COBALT_BROWSER_STARBOARD_EVENT_HANDLER_H_ + +#include "cobalt/base/event_dispatcher.h" +#include "starboard/event.h" + +namespace cobalt { +namespace browser { + +class EventHandler { + public: + explicit EventHandler(base::EventDispatcher* event_dispatcher); + + // Static event handler called by |SbEventHandle|. Forwards input events to + // |system_window::HandleInputEvent| and passes all other events to + // |DispatchEvent|. + static void HandleEvent(const SbEvent* event); + + private: + // Creates a Cobalt event from a Starboard event and dispatches to the rest + // of the system via |event_dispatcher_|. + void DispatchEvent(const SbEvent* event) const; + + // The event dispatcher that dispatches Cobalt events to the rest of the + // system. + base::EventDispatcher* event_dispatcher_; +}; + +} // namespace browser +} // namespace cobalt + +#endif // COBALT_BROWSER_STARBOARD_EVENT_HANDLER_H_
diff --git a/src/cobalt/browser/starboard/platform_browser.gyp b/src/cobalt/browser/starboard/platform_browser.gyp index cd002f7..a9ae70f 100644 --- a/src/cobalt/browser/starboard/platform_browser.gyp +++ b/src/cobalt/browser/starboard/platform_browser.gyp
@@ -19,6 +19,8 @@ 'type': 'static_library', 'sources': [ 'application.cc', + 'event_handler.cc', + 'event_handler.h', ], 'dependencies': [ '<(DEPTH)/cobalt/browser/browser.gyp:browser',
diff --git a/src/cobalt/browser/switches.cc b/src/cobalt/browser/switches.cc index e53e617..9258a4f 100644 --- a/src/cobalt/browser/switches.cc +++ b/src/cobalt/browser/switches.cc
@@ -71,13 +71,32 @@ // Creates a remote debugging server and listens on the specified port. const char kRemoteDebuggingPort[] = "remote_debugging_port"; +// Determines the capacity of the scratch surface cache. The scratch surface +// cache facilitates the reuse of temporary offscreen surfaces within a single +// frame. This setting is only relevant when using the hardware-accelerated +// Skia rasterizer. +const char kScratchSurfaceCacheSizeInBytes[] = + "scratch_surface_cache_size_in_bytes"; + // If this flag is set, Cobalt will automatically shutdown after the specified // number of seconds have passed. const char kShutdownAfter[] = "shutdown_after"; +// Determines the capacity of the skia cache. The Skia cache is maintained +// within Skia and is used to cache the results of complicated effects such as +// shadows, so that Skia draw calls that are used repeatedly across frames can +// be cached into surfaces. This setting is only relevant when using the +// hardware-accelerated Skia rasterizer. +const char kSkiaCacheSizeInBytes[] = "skia_cache_size_in_bytes"; + // Decode all images using StubImageDecoder. const char kStubImageDecoder[] = "stub_image_decoder"; +// Determines the capacity of the surface cache. The surface cache tracks which +// render tree nodes are being re-used across frames and stores the nodes that +// are most CPU-expensive to render into surfaces. +const char kSurfaceCacheSizeInBytes[] = "surface_cache_size_in_bytes"; + // If this is set, then a trace (see base/debug/trace_eventh.h) is started on // Cobalt startup. A value must also be specified for this switch, which is // the duration in seconds of how long the trace will be done for before ending
diff --git a/src/cobalt/browser/switches.h b/src/cobalt/browser/switches.h index 0a29c37..4c66e0c 100644 --- a/src/cobalt/browser/switches.h +++ b/src/cobalt/browser/switches.h
@@ -42,6 +42,9 @@ extern const char kViewport[]; extern const char kVideoDecoderStub[]; extern const char kWebDriverPort[]; +extern const char kSurfaceCacheSizeInBytes[]; +extern const char kScratchSurfaceCacheSizeInBytes[]; +extern const char kSkiaCacheSizeInBytes[]; #endif // ENABLE_COMMAND_LINE_SWITCHES } // namespace switches
diff --git a/src/cobalt/browser/web_module.cc b/src/cobalt/browser/web_module.cc index b3741c4..88b5286 100644 --- a/src/cobalt/browser/web_module.cc +++ b/src/cobalt/browser/web_module.cc
@@ -525,21 +525,6 @@ network_module, window_dimensions, resource_provider, layout_refresh_rate, options); -#if defined(ENABLE_PARTIAL_LAYOUT_CONTROL) - CommandLine* command_line = CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(browser::switches::kPartialLayout)) { - const std::string partial_layout_string = - command_line->GetSwitchValueASCII(browser::switches::kPartialLayout); - OnPartialLayoutConsoleCommandReceived(partial_layout_string); - } - partial_layout_command_handler_.reset( - new base::ConsoleCommandManager::CommandHandler( - browser::switches::kPartialLayout, - base::Bind(&WebModule::OnPartialLayoutConsoleCommandReceived, - base::Unretained(this)), - kPartialLayoutCommandShortHelp, kPartialLayoutCommandLongHelp)); -#endif // defined(ENABLE_PARTIAL_LAYOUT_CONTROL) - // Start the dedicated thread and create the internal implementation // object on that thread. #if defined(ADDRESS_SANITIZER) @@ -567,6 +552,21 @@ base::Bind(&base::WaitableEvent::Signal, base::Unretained(&is_initialized))); is_initialized.Wait(); + +#if defined(ENABLE_PARTIAL_LAYOUT_CONTROL) + CommandLine* command_line = CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(browser::switches::kPartialLayout)) { + const std::string partial_layout_string = + command_line->GetSwitchValueASCII(browser::switches::kPartialLayout); + OnPartialLayoutConsoleCommandReceived(partial_layout_string); + } + partial_layout_command_handler_.reset( + new base::ConsoleCommandManager::CommandHandler( + browser::switches::kPartialLayout, + base::Bind(&WebModule::OnPartialLayoutConsoleCommandReceived, + base::Unretained(this)), + kPartialLayoutCommandShortHelp, kPartialLayoutCommandLongHelp)); +#endif // defined(ENABLE_PARTIAL_LAYOUT_CONTROL) } WebModule::~WebModule() {
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id index 3acfe13..4db8c83 100644 --- a/src/cobalt/build/build.id +++ b/src/cobalt/build/build.id
@@ -1 +1 @@ -8885 \ No newline at end of file +9617 \ No newline at end of file
diff --git a/src/cobalt/build/config/base.gypi b/src/cobalt/build/config/base.gypi index fd0ee92..ae3ac78 100644 --- a/src/cobalt/build/config/base.gypi +++ b/src/cobalt/build/config/base.gypi
@@ -67,6 +67,9 @@ # Set to 1 to build with DIAL support. 'in_app_dial%': 0, + # Set to 1 to enable H5vccAccountManager. + 'enable_account_manager%': 0, + # Set to 1 to compile with SPDY support. 'enable_spdy%': 0, @@ -103,6 +106,24 @@ # "cobalt/renderer/egl_and_gles/egl_and_gles_<gl_type>.gyp not found" 'gl_type%': 'system_gles2', + # Determines the capacity of the skia cache. The Skia cache is maintained + # within Skia and is used to cache the results of complicated effects such + # as shadows, so that Skia draw calls that are used repeatedly across + # frames can be cached into surfaces. This setting is only relevant when + # using the hardware-accelerated Skia rasterizer. + 'skia_cache_size_in_bytes%': 4 * 1024 * 1024, + + # Determines the capacity of the scratch surface cache. The scratch + # surface cache facilitates the reuse of temporary offscreen surfaces + # within a single frame. This setting is only relevant when using the + # hardware-accelerated Skia rasterizer. + 'scratch_surface_cache_size_in_bytes%': 7 * 1024 * 1024, + + # Determines the capacity of the surface cache. The surface cache tracks + # which render tree nodes are being re-used across frames and stores the + # nodes that are most CPU-expensive to render into surfaces. + 'surface_cache_size_in_bytes%': 0, + # Compiler configuration. # The following variables are used to specify compiler and linker @@ -249,7 +270,7 @@ 'defines': [ 'COBALT_DISABLE_SPDY', ], - }] + }], ], # TODO: Revisit and remove unused configurations.
diff --git a/src/cobalt/build/config/base.py b/src/cobalt/build/config/base.py index 8e4a62f..4c46c70 100644 --- a/src/cobalt/build/config/base.py +++ b/src/cobalt/build/config/base.py
@@ -23,8 +23,15 @@ import gyp_utils +class Configs(object): + """Strings representing valid build configurations.""" + DEBUG = 'debug' + DEVEL = 'devel' + GOLD = 'gold' + QA = 'qa' + # Represents all valid build configurations. -VALID_BUILD_CONFIGS = ['debug', 'devel', 'qa', 'gold'] +VALID_BUILD_CONFIGS = [Configs.DEBUG, Configs.DEVEL, Configs.QA, Configs.GOLD] # Represents all supported platforms, uniquified and sorted.
diff --git a/src/cobalt/build/copy_data.py b/src/cobalt/build/copy_data.py deleted file mode 100755 index cd1d6a2..0000000 --- a/src/cobalt/build/copy_data.py +++ /dev/null
@@ -1,137 +0,0 @@ -#!/usr/bin/python -# Copyright 2014 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 file is based on build/copy_test_data_ios.py - -"""Copies data files or directories into a given output directory. - -Since the output of this script is intended to be use by GYP, all resulting -paths are using Unix-style forward flashes. -""" - -import argparse -import os -import posixpath -import shutil -import sys -if os.name == 'nt': - import win32api - - -class WrongNumberOfArgumentsException(Exception): - pass - - -def EscapePath(path): - """Returns a path with spaces escaped.""" - return path.replace(' ', '\\ ') - - -def ListFilesForPath(path): - """Returns a list of all the files under a given path.""" - output = [] - # Ignore revision control metadata directories. - if (os.path.basename(path).startswith('.git') or - os.path.basename(path).startswith('.svn')): - return output - - # Files get returned without modification. - if not os.path.isdir(path): - output.append(path) - return output - - # Directories get recursively expanded. - contents = os.listdir(path) - for item in contents: - full_path = posixpath.join(path, item) - output.extend(ListFilesForPath(full_path)) - return output - - -def CalcInputs(inputs): - """Computes the full list of input files. The output is a list of - (filepath, filepath relative to input dir)""" - # |inputs| is a list of paths, which may be directories. - output = [] - for input_file in inputs: - file_list = ListFilesForPath(input_file) - dirname = posixpath.dirname(input_file) - output.extend([(x, posixpath.relpath(x, dirname)) for x in file_list]) - return output - - -def CopyFiles(files_to_copy, output_basedir): - """Copies files to the given output directory.""" - for (filename, relative_filename) in files_to_copy: - if os.name == 'nt': - # Some of the files (especially for layout tests) result in very long - # paths (especially on build machines) such that shutil.copy fails. - filename = win32api.GetShortPathName(filename) - output_basedir = win32api.GetShortPathName(output_basedir) - output_filename = posixpath.join(output_basedir, relative_filename) - output_dir = posixpath.dirname(output_filename) - - # In cases where a directory has turned into a file or vice versa, delete it - # before copying it below. - if os.path.exists(output_dir) and not os.path.isdir(output_dir): - os.remove(output_dir) - if os.path.exists(output_filename) and os.path.isdir(output_filename): - shutil.rmtree(output_filename) - - if not os.path.exists(output_dir): - os.makedirs(output_dir) - shutil.copy(filename, output_filename) - - -def DoMain(argv): - """Called by GYP using pymod_do_main.""" - parser = argparse.ArgumentParser() - parser.add_argument('-o', dest='output_dir', help='output directory') - parser.add_argument('--inputs', action='store_true', dest='list_inputs', - help='prints a list of all input files') - parser.add_argument('--outputs', action='store_true', dest='list_outputs', - help='prints a list of all output files') - parser.add_argument('input_paths', metavar='path', nargs='+', - help='path to an input file or directory') - options = parser.parse_args(argv) - - escaped_files = [EscapePath(x) for x in options.input_paths] - files_to_copy = CalcInputs(escaped_files) - if options.list_inputs: - return '\n'.join([x[0] for x in files_to_copy]) - - if not options.output_dir: - raise WrongNumberOfArgumentsException('-o required.') - - if options.list_outputs: - outputs = [posixpath.join(options.output_dir, x[1]) for x in files_to_copy] - return '\n'.join(outputs) - - CopyFiles(files_to_copy, options.output_dir) - return - - -def main(argv): - try: - result = DoMain(argv[1:]) - except WrongNumberOfArgumentsException, e: - print >> sys.stderr, e - return 1 - if result: - print result - return 0 - -if __name__ == '__main__': - sys.exit(main(sys.argv))
diff --git a/src/cobalt/build/copy_test_data.gypi b/src/cobalt/build/copy_test_data.gypi index e4e47ed..13ac050 100644 --- a/src/cobalt/build/copy_test_data.gypi +++ b/src/cobalt/build/copy_test_data.gypi
@@ -50,14 +50,14 @@ { 'inputs': [ - '<!@pymod_do_main(copy_data --inputs <(input_files))', + '<!@pymod_do_main(starboard.build.copy_data --inputs <(input_files))', ], 'outputs': [ - '<!@pymod_do_main(copy_data -o <(PRODUCT_DIR)/content/dir_source_root/<(output_dir) --outputs <(input_files))', + '<!@pymod_do_main(starboard.build.copy_data -o <(PRODUCT_DIR)/content/dir_source_root/<(output_dir) --outputs <(input_files))', ], 'action': [ 'python', - '<(DEPTH)/cobalt/build/copy_data.py', + '<(DEPTH)/starboard/build/copy_data.py', '-o', '<(PRODUCT_DIR)/content/dir_source_root/<(output_dir)', '<@(input_files)', ],
diff --git a/src/cobalt/build/copy_web_data.gypi b/src/cobalt/build/copy_web_data.gypi index 4585eb2..b4f5c98 100644 --- a/src/cobalt/build/copy_web_data.gypi +++ b/src/cobalt/build/copy_web_data.gypi
@@ -50,14 +50,14 @@ { 'inputs': [ - '<!@pymod_do_main(copy_data --inputs <(input_files))', + '<!@pymod_do_main(starboard.build.copy_data --inputs <(input_files))', ], 'outputs': [ - '<!@pymod_do_main(copy_data -o <(PRODUCT_DIR)/content/data/web/<(output_dir) --outputs <(input_files))', + '<!@pymod_do_main(starboard.build.copy_data -o <(PRODUCT_DIR)/content/data/web/<(output_dir) --outputs <(input_files))', ], 'action': [ 'python', - '<(DEPTH)/cobalt/build/copy_data.py', + '<(DEPTH)/starboard/build/copy_data.py', '-o', '<(PRODUCT_DIR)/content/data/web/<(output_dir)', '<@(input_files)', ],
diff --git a/src/cobalt/build/deploy.gypi b/src/cobalt/build/deploy.gypi deleted file mode 100644 index d252e14..0000000 --- a/src/cobalt/build/deploy.gypi +++ /dev/null
@@ -1,43 +0,0 @@ -# Copyright 2014 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 file is meant to be included into a target to provide a rule -# to deploy a target on a target platform. -# -# To use this, create a gyp target with the following form: -# 'targets': [ -# { -# 'target_name': 'target_deploy', -# 'type': 'none', -# 'dependencies': [ -# 'target', -# ], -# 'variables': { -# 'executable_name': 'target', -# }, -# 'includes': [ -# '../build/deploy.gypi', -# ], -# }, -# - -{ - 'conditions': [ - ['OS=="starboard" and sb_has_deploy_step==1', { - 'dependencies': [ - '<(DEPTH)/<(starboard_path)/build/platform_files.gyp:platform_files', - ], - }], - ], -}
diff --git a/src/cobalt/build/gyp_cobalt b/src/cobalt/build/gyp_cobalt index a683762..0e60bb9 100755 --- a/src/cobalt/build/gyp_cobalt +++ b/src/cobalt/build/gyp_cobalt
@@ -191,6 +191,10 @@ '--toplevel-dir={}'.format(source_tree_dir), ] + # Add the source tree root to the Python path so that build files can + # easily reference other build files in the source tree. + sys.path.append(source_tree_dir) + # Pass through the debug options. for debug in self.options.debug: self.common_args.append('--debug=%s' % debug)
diff --git a/src/cobalt/csp/csp.gyp b/src/cobalt/csp/csp.gyp index 846471d..a493cd7 100644 --- a/src/cobalt/csp/csp.gyp +++ b/src/cobalt/csp/csp.gyp
@@ -73,7 +73,7 @@ 'variables': { 'executable_name': 'csp_test', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, {
diff --git a/src/cobalt/css_parser/css_parser.gyp b/src/cobalt/css_parser/css_parser.gyp index 088a212..185ee0b 100644 --- a/src/cobalt/css_parser/css_parser.gyp +++ b/src/cobalt/css_parser/css_parser.gyp
@@ -144,7 +144,7 @@ 'variables': { 'executable_name': 'css_parser_test', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, ],
diff --git a/src/cobalt/cssom/cssom_test.gyp b/src/cobalt/cssom/cssom_test.gyp index d61f561..a776fa4 100644 --- a/src/cobalt/cssom/cssom_test.gyp +++ b/src/cobalt/cssom/cssom_test.gyp
@@ -70,7 +70,7 @@ 'variables': { 'executable_name': 'cssom_test', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, ], }
diff --git a/src/cobalt/debug/render_overlay.cc b/src/cobalt/debug/render_overlay.cc index d769b99..85d03b0 100644 --- a/src/cobalt/debug/render_overlay.cc +++ b/src/cobalt/debug/render_overlay.cc
@@ -40,24 +40,27 @@ } void RenderOverlay::Process() { - // Calculate a modified layout time accounting for the offset between now and - // the time the input layout was received. - base::TimeDelta layout_time = - input_layout_.layout_time + - (base::TimeTicks::HighResNow() - *input_receipt_time_); + if (input_layout_.render_tree) { + // Calculate a modified layout time accounting for the offset between now + // and the time the input layout was received. + base::TimeDelta layout_time = input_layout_.layout_time; + DCHECK(input_receipt_time_); + base::TimeTicks now = base::TimeTicks::HighResNow(); + layout_time += now - input_receipt_time_.value_or(now); - if (overlay_) { - render_tree::CompositionNode::Builder builder; - builder.AddChild(input_layout_.render_tree); - builder.AddChild(overlay_); - scoped_refptr<render_tree::Node> combined_tree = - new render_tree::CompositionNode(builder); + if (overlay_) { + render_tree::CompositionNode::Builder builder; + builder.AddChild(input_layout_.render_tree); + builder.AddChild(overlay_); + scoped_refptr<render_tree::Node> combined_tree = + new render_tree::CompositionNode(builder); - render_tree_produced_callback_.Run( - LayoutResults(combined_tree, input_layout_.animations, layout_time)); - } else { - render_tree_produced_callback_.Run(LayoutResults( - input_layout_.render_tree, input_layout_.animations, layout_time)); + render_tree_produced_callback_.Run( + LayoutResults(combined_tree, input_layout_.animations, layout_time)); + } else { + render_tree_produced_callback_.Run(LayoutResults( + input_layout_.render_tree, input_layout_.animations, layout_time)); + } } }
diff --git a/src/cobalt/deprecated/platform_delegate.cc b/src/cobalt/deprecated/platform_delegate.cc index 98a6b62..6e7baaf 100644 --- a/src/cobalt/deprecated/platform_delegate.cc +++ b/src/cobalt/deprecated/platform_delegate.cc
@@ -44,6 +44,8 @@ *result = FilePath(plat->logging_output_path()); return true; } else { + DLOG(ERROR) << "Unable to get or create paths::DIR_COBALT_DEBUG_OUT: " + << plat->logging_output_path(); return false; } @@ -53,6 +55,8 @@ *result = FilePath(plat->logging_output_path()); return true; } else { + DLOG(ERROR) << "Unable to get or create paths::DIR_COBALT_TEST_OUT: " + << plat->logging_output_path(); return false; }
diff --git a/src/cobalt/dom/dom_test.gyp b/src/cobalt/dom/dom_test.gyp index e255ee4..a399a4e 100644 --- a/src/cobalt/dom/dom_test.gyp +++ b/src/cobalt/dom/dom_test.gyp
@@ -84,7 +84,7 @@ 'variables': { 'executable_name': 'dom_test', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, ], }
diff --git a/src/cobalt/dom/local_storage_database_test.cc b/src/cobalt/dom/local_storage_database_test.cc index af56dd2..55963ec 100644 --- a/src/cobalt/dom/local_storage_database_test.cc +++ b/src/cobalt/dom/local_storage_database_test.cc
@@ -18,8 +18,8 @@ #include <vector> -#include "base/message_loop.h" #include "base/file_path.h" +#include "base/message_loop.h" #include "base/path_service.h" #include "base/stringprintf.h" #include "base/time.h" @@ -41,7 +41,7 @@ CallbackWaiter() : was_called_event_(true, false) {} virtual ~CallbackWaiter() {} bool TimedWait() { - return was_called_event_.TimedWait(base::TimeDelta::FromMilliseconds(500)); + return was_called_event_.TimedWait(base::TimeDelta::FromSeconds(5)); } protected:
diff --git a/src/cobalt/dom/node.cc b/src/cobalt/dom/node.cc index c36ffe7..cf81ef0 100644 --- a/src/cobalt/dom/node.cc +++ b/src/cobalt/dom/node.cc
@@ -601,6 +601,7 @@ OnMutation(); InvalidateLayoutBoxesFromNodeAndAncestors(); + node->InvalidateLayoutBoxesFromNodeAndDescendants(); node->UpdateGenerationForNodeAndAncestors(); bool was_inserted_to_document = node->inserted_into_document_;
diff --git a/src/cobalt/dom_parser/dom_parser.gyp b/src/cobalt/dom_parser/dom_parser.gyp index ca12a0f..76ba70a 100644 --- a/src/cobalt/dom_parser/dom_parser.gyp +++ b/src/cobalt/dom_parser/dom_parser.gyp
@@ -67,7 +67,7 @@ 'variables': { 'executable_name': 'dom_parser_test', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, ], }
diff --git a/src/cobalt/h5vcc/H5vccAccountManager.idl b/src/cobalt/h5vcc/H5vccAccountManager.idl new file mode 100644 index 0000000..3192c74 --- /dev/null +++ b/src/cobalt/h5vcc/H5vccAccountManager.idl
@@ -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. + */ +[ + Conditional=COBALT_ENABLE_ACCOUNT_MANAGER, + Constructor +] +interface H5vccAccountManager { + void getAuthToken(AccessTokenCallback callback); + void requestPairing(AccessTokenCallback callback); + void requestUnpairing(AccessTokenCallback callback); +}; + +callback AccessTokenCallback = boolean(DOMString token, + unsigned long long expiration);
diff --git a/src/cobalt/h5vcc/h5vcc.gyp b/src/cobalt/h5vcc/h5vcc.gyp index a91d751..835c4f9 100644 --- a/src/cobalt/h5vcc/h5vcc.gyp +++ b/src/cobalt/h5vcc/h5vcc.gyp
@@ -57,6 +57,19 @@ # For cobalt_build_id.h '<(SHARED_INTERMEDIATE_DIR)', ], + 'conditions': [ + ['enable_account_manager == 1', { + 'sources': [ + 'h5vcc_account_manager.cc', + 'h5vcc_account_manager.h', + ], + 'direct_dependent_settings': { + 'defines': [ + 'COBALT_ENABLE_ACCOUNT_MANAGER', + ], + }, + }], + ], }, {
diff --git a/src/cobalt/h5vcc/h5vcc_account_manager.cc b/src/cobalt/h5vcc/h5vcc_account_manager.cc new file mode 100644 index 0000000..69dd9db --- /dev/null +++ b/src/cobalt/h5vcc/h5vcc_account_manager.cc
@@ -0,0 +1,135 @@ +/* + * 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/h5vcc/h5vcc_account_manager.h" + +#include "base/memory/scoped_ptr.h" +#include "starboard/user.h" + +namespace cobalt { +namespace h5vcc { + +H5vccAccountManager::H5vccAccountManager() + : thread_("AccountManager"), owning_message_loop_(MessageLoop::current()) { + thread_.Start(); +} + +void H5vccAccountManager::GetAuthToken( + const AccessTokenCallbackHolder& callback) { + DCHECK(thread_checker_.CalledOnValidThread()); + DLOG(INFO) << "Get authorization token."; + scoped_ptr<AccessTokenCallbackReference> token_callback( + new AccessTokenCallbackHolder::Reference(this, callback)); + thread_.message_loop()->PostTask( + FROM_HERE, base::Bind(&H5vccAccountManager::RequestOperationInternal, + this, kGetToken, base::Passed(&token_callback))); +} + +void H5vccAccountManager::RequestPairing( + const AccessTokenCallbackHolder& callback) { + DCHECK(thread_checker_.CalledOnValidThread()); + DLOG(INFO) << "Request application linking."; + scoped_ptr<AccessTokenCallbackReference> token_callback( + new AccessTokenCallbackHolder::Reference(this, callback)); + thread_.message_loop()->PostTask( + FROM_HERE, base::Bind(&H5vccAccountManager::RequestOperationInternal, + this, kPairing, base::Passed(&token_callback))); +} + +void H5vccAccountManager::RequestUnpairing( + const AccessTokenCallbackHolder& callback) { + DCHECK(thread_checker_.CalledOnValidThread()); + DLOG(INFO) << "Request application unlinking."; + scoped_ptr<AccessTokenCallbackReference> token_callback( + new AccessTokenCallbackHolder::Reference(this, callback)); + thread_.message_loop()->PostTask( + FROM_HERE, base::Bind(&H5vccAccountManager::RequestOperationInternal, + this, kUnpairing, base::Passed(&token_callback))); +} + +H5vccAccountManager::~H5vccAccountManager() { + DCHECK(thread_checker_.CalledOnValidThread()); +} + +void H5vccAccountManager::RequestOperationInternal( + OperationType operation, + scoped_ptr<AccessTokenCallbackReference> token_callback) { + DCHECK_EQ(thread_.message_loop(), MessageLoop::current()); + + SbUser current_user = SbUserGetCurrent(); + DCHECK(SbUserIsValid(current_user)); + + static size_t kBufferSize = SbUserMaxAuthenticationTokenSizeInBytes(); + scoped_array<char> token_buffer(new char[kBufferSize]); + SbUserApplicationTokenResults token_results; + token_results.token_buffer_size = kBufferSize; + token_results.token_buffer = token_buffer.get(); + + bool got_valid_token = false; + switch (operation) { + case kPairing: + got_valid_token = + SbUserRequestApplicationLinking(current_user, &token_results); + DLOG_IF(INFO, !got_valid_token) << "Application linking request failed."; + break; + case kUnpairing: + if (SbUserRequestApplicationUnlinking(current_user)) { + got_valid_token = false; + break; + } + // The user canceled the flow, or there was some error. Fall into the next + // case to get an access token if available and return that. + DLOG(INFO) << "Application unlinking request failed. Try to get token."; + case kGetToken: + got_valid_token = + SbUserRequestAuthenticationToken(current_user, &token_results); + DLOG_IF(INFO, !got_valid_token) << "Authentication token request failed."; + break; + } + + uint64_t expiration_in_seconds = 0; + if (got_valid_token) { + SbTime expires_in = token_results.expiry - SbTimeGetNow(); + // If this token's expiry is in the past, then we didn't get a valid token. + if (expires_in < 0) { + DLOG(WARNING) << "Authentication token expires in the past."; + got_valid_token = false; + } else { + expiration_in_seconds = expires_in / kSbTimeSecond; + } + } + // If we did not get a valid token to return to the caller, set the token + // buffer to an empty string. + if (!got_valid_token) { + token_buffer[0] = '\0'; + } + + owning_message_loop_->PostTask( + FROM_HERE, + base::Bind(&H5vccAccountManager::SendResult, this, + base::Passed(&token_callback), std::string(token_buffer.get()), + expiration_in_seconds)); +} + +void H5vccAccountManager::SendResult( + scoped_ptr<AccessTokenCallbackReference> token_callback, + const std::string& token, uint64_t expiration_in_seconds) { + DCHECK(thread_checker_.CalledOnValidThread()); + token_callback->value().Run(token, expiration_in_seconds); +} + +} // namespace h5vcc +} // namespace cobalt
diff --git a/src/cobalt/h5vcc/h5vcc_account_manager.h b/src/cobalt/h5vcc/h5vcc_account_manager.h new file mode 100644 index 0000000..3c5c6a4 --- /dev/null +++ b/src/cobalt/h5vcc/h5vcc_account_manager.h
@@ -0,0 +1,88 @@ +/* + * 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_H5VCC_H5VCC_ACCOUNT_MANAGER_H_ +#define COBALT_H5VCC_H5VCC_ACCOUNT_MANAGER_H_ + +#include <queue> +#include <string> + +#include "base/message_loop.h" +#include "base/threading/thread.h" +#include "base/threading/thread_checker.h" +#include "cobalt/script/callback_function.h" +#include "cobalt/script/script_object.h" +#include "cobalt/script/wrappable.h" + +namespace cobalt { +namespace h5vcc { + +// Implementation of the H5vccAccountManager interface. Requests will be handled +// one-at-time on another thread in FIFO order. When a request is complete, the +// AccessTokenCallback will be fired on the thread that the H5vccAccountManager +// was created on. +class H5vccAccountManager : public script::Wrappable { + public: + typedef script::CallbackFunction<bool(const std::string&, uint64_t)> + AccessTokenCallback; + typedef script::ScriptObject<AccessTokenCallback> AccessTokenCallbackHolder; + + H5vccAccountManager(); + // H5vccAccountManager interface. + void GetAuthToken(const AccessTokenCallbackHolder& callback); + void RequestPairing(const AccessTokenCallbackHolder& callback); + void RequestUnpairing(const AccessTokenCallbackHolder& callback); + + DEFINE_WRAPPABLE_TYPE(H5vccAccountManager); + + private: + typedef script::ScriptObject<AccessTokenCallback>::Reference + AccessTokenCallbackReference; + enum OperationType { + kPairing, + kUnpairing, + kGetToken, + }; + + ~H5vccAccountManager(); + + void RequestOperationInternal( + OperationType operation, + scoped_ptr<AccessTokenCallbackReference> token_callback); + void SendResult(scoped_ptr<AccessTokenCallbackReference> token_callback, + const std::string& token, + uint64_t expiration_in_seconds); + + // Thread checker for the thread that creates this instance. + base::ThreadChecker thread_checker_; + + // Each incoming request will have a corresponding task posted to this + // thread's message loop and will be handled in a FIFO manner. + base::Thread thread_; + + // The message loop that the H5vccAccountManager was created on. The public + // interface must be called from this message loop, and callbacks will be + // fired on this loop as well. + MessageLoop* owning_message_loop_; + + friend class scoped_refptr<H5vccAccountManager>; + DISALLOW_COPY_AND_ASSIGN(H5vccAccountManager); +}; + +} // namespace h5vcc +} // namespace cobalt + +#endif // COBALT_H5VCC_H5VCC_ACCOUNT_MANAGER_H_
diff --git a/src/cobalt/layout/block_container_box.cc b/src/cobalt/layout/block_container_box.cc index 57e34d7..79ad027 100644 --- a/src/cobalt/layout/block_container_box.cc +++ b/src/cobalt/layout/block_container_box.cc
@@ -246,6 +246,7 @@ WrapOpportunityPolicy /*wrap_opportunity_policy*/, bool /*is_line_existence_justified*/, LayoutUnit /*available_width*/, bool /*should_collapse_trailing_white_space*/) { + DCHECK(!IsAbsolutelyPositioned()); DCHECK_EQ(kInlineLevel, GetLevel()); return kWrapResultNoWrap; }
diff --git a/src/cobalt/layout/block_formatting_block_container_box.cc b/src/cobalt/layout/block_formatting_block_container_box.cc index 336aef4..b4023d8 100644 --- a/src/cobalt/layout/block_formatting_block_container_box.cc +++ b/src/cobalt/layout/block_formatting_block_container_box.cc
@@ -158,6 +158,7 @@ bool is_line_existence_justified, LayoutUnit /*available_width*/, bool /*should_collapse_trailing_white_space*/) { // NOTE: This logic must stay in sync with ReplacedBox::TryWrapAt(). + DCHECK(!IsAbsolutelyPositioned()); // Wrapping is not allowed until the line's existence is justified, meaning // that wrapping cannot occur before the box. Given that this box cannot be
diff --git a/src/cobalt/layout/box_generator.cc b/src/cobalt/layout/box_generator.cc index 09024973..a2affb9 100644 --- a/src/cobalt/layout/box_generator.cc +++ b/src/cobalt/layout/box_generator.cc
@@ -315,13 +315,19 @@ return; } + scoped_refptr<cssom::CSSComputedStyleDeclaration> + css_computed_style_declaration = new cssom::CSSComputedStyleDeclaration(); + css_computed_style_declaration->set_data( + GetComputedStyleOfAnonymousBox(br_element->computed_style())); + + css_computed_style_declaration->set_animations(br_element->animations()); + DCHECK(*paragraph_); int32 text_position = (*paragraph_)->GetTextEndPosition(); - scoped_refptr<TextBox> br_text_box = - new TextBox(br_element->css_computed_style_declaration(), *paragraph_, - text_position, text_position, true, - context_->used_style_provider, context_->layout_stat_tracker); + scoped_refptr<TextBox> br_text_box = new TextBox( + css_computed_style_declaration, *paragraph_, text_position, text_position, + true, context_->used_style_provider, context_->layout_stat_tracker); // Add a line feed code point to the paragraph to signify the new line for // the line breaking and bidirectional algorithms.
diff --git a/src/cobalt/layout/container_box.cc b/src/cobalt/layout/container_box.cc index 2fd8818..24f72b1 100644 --- a/src/cobalt/layout/container_box.cc +++ b/src/cobalt/layout/container_box.cc
@@ -89,11 +89,7 @@ // https://www.w3.org/TR/css-transforms-1/#transformable-element DCHECK(!split_sibling->IsTransformable()); if (split_sibling->IsPositioned()) { - // Absolutely positioned boxes are not splittable. - DCHECK(!split_sibling->IsAbsolutelyPositioned()); - // This container is the containing block because the split sibling cannot - // be an absolutely positioned box. - are_cross_references_valid_ = false; + split_sibling->GetContainingBlock()->are_cross_references_valid_ = false; split_sibling->GetStackingContext()->are_cross_references_valid_ = false; }
diff --git a/src/cobalt/layout/inline_container_box.cc b/src/cobalt/layout/inline_container_box.cc index 6d8ae8e..062bc6e 100644 --- a/src/cobalt/layout/inline_container_box.cc +++ b/src/cobalt/layout/inline_container_box.cc
@@ -181,6 +181,7 @@ WrapAtPolicy wrap_at_policy, WrapOpportunityPolicy wrap_opportunity_policy, bool is_line_existence_justified, LayoutUnit available_width, bool should_collapse_trailing_white_space) { + DCHECK(!IsAbsolutelyPositioned()); DCHECK(is_line_existence_justified || justifies_line_existence_); switch (wrap_at_policy) { @@ -469,7 +470,13 @@ // set to the number of child boxes. size_t overflow_index = 0; while (overflow_index < child_boxes().size()) { - LayoutUnit child_width = child_boxes()[overflow_index]->GetMarginBoxWidth(); + Box* child_box = child_boxes()[overflow_index]; + // Absolutely positioned boxes are not included in width calculations. + if (child_box->IsAbsolutelyPositioned()) { + continue; + } + + LayoutUnit child_width = child_box->GetMarginBoxWidth(); if (child_width > available_width) { break; } @@ -563,6 +570,10 @@ bool is_line_existence_justified, LayoutUnit available_width, bool should_collapse_trailing_white_space) { Box* child_box = child_boxes()[wrap_index]; + // Absolutely positioned boxes are not wrappable. + if (child_box->IsAbsolutelyPositioned()) { + return kWrapResultNoWrap; + } // Check for whether the line is justified before this child. If it is not, // then verify that the line is justified within this child. This function
diff --git a/src/cobalt/layout/layout.gyp b/src/cobalt/layout/layout.gyp index 5aa740c..cde6dba 100644 --- a/src/cobalt/layout/layout.gyp +++ b/src/cobalt/layout/layout.gyp
@@ -131,7 +131,7 @@ 'variables': { 'executable_name': 'layout_test', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, ], }
diff --git a/src/cobalt/layout/line_box.cc b/src/cobalt/layout/line_box.cc index be56c64..9012f31 100644 --- a/src/cobalt/layout/line_box.cc +++ b/src/cobalt/layout/line_box.cc
@@ -347,6 +347,14 @@ bool LineBox::TryWrapOverflowingBoxAndMaybeAddSplitChild( WrapAtPolicy wrap_at_policy, WrapOpportunityPolicy wrap_opportunity_policy, Box* child_box) { + // If none of the children justify the line's existence, then wrapping is + // unavailable. The wrap can't happen before the first child justifying the + // line. + if (!first_box_justifying_line_existence_index_ && + !child_box->JustifiesLineExistence()) { + return false; + } + // Attempt to wrap the child based upon the passed in wrap policy. WrapResult wrap_result = child_box->TryWrapAt( wrap_at_policy, wrap_opportunity_policy, LineExists(),
diff --git a/src/cobalt/layout/replaced_box.cc b/src/cobalt/layout/replaced_box.cc index a24ba76..62b771f 100644 --- a/src/cobalt/layout/replaced_box.cc +++ b/src/cobalt/layout/replaced_box.cc
@@ -94,6 +94,7 @@ bool /*should_collapse_trailing_white_space*/) { // NOTE: This logic must stay in sync with // InlineLevelBlockContainerBox::TryWrapAt(). + DCHECK(!IsAbsolutelyPositioned()); // Wrapping is not allowed until the line's existence is justified, meaning // that wrapping cannot occur before the box. Given that this box cannot be
diff --git a/src/cobalt/layout/text_box.cc b/src/cobalt/layout/text_box.cc index f5413ef..84e5823 100644 --- a/src/cobalt/layout/text_box.cc +++ b/src/cobalt/layout/text_box.cc
@@ -165,6 +165,8 @@ bool is_line_existence_justified, LayoutUnit available_width, bool should_collapse_trailing_white_space) { + DCHECK(!IsAbsolutelyPositioned()); + bool style_allows_break_word = computed_style()->overflow_wrap() == cssom::KeywordValue::GetBreakWord(); @@ -265,7 +267,7 @@ bool TextBox::IsCollapsed() const { return !HasLeadingWhiteSpace() && !HasTrailingWhiteSpace() && - !HasNonCollapsibleText() && !has_trailing_line_break_; + !HasNonCollapsibleText(); } bool TextBox::HasLeadingWhiteSpace() const {
diff --git a/src/cobalt/layout_tests/layout_tests.gyp b/src/cobalt/layout_tests/layout_tests.gyp index 5cf6941..454e3f2 100644 --- a/src/cobalt/layout_tests/layout_tests.gyp +++ b/src/cobalt/layout_tests/layout_tests.gyp
@@ -87,7 +87,7 @@ 'variables': { 'executable_name': 'layout_tests', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, { @@ -117,7 +117,7 @@ 'variables': { 'executable_name': 'layout_benchmarks', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, { 'target_name': 'web_platform_tests', @@ -148,7 +148,7 @@ 'variables': { 'executable_name': 'web_platform_tests', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, ],
diff --git a/src/cobalt/layout_tests/testdata/css-text-3/4-1-1-space-preceding-br-element-should-not-be-collapsed-expected.png b/src/cobalt/layout_tests/testdata/css-text-3/4-1-1-space-preceding-br-element-should-not-be-collapsed-expected.png index 234d180..358cba3 100644 --- a/src/cobalt/layout_tests/testdata/css-text-3/4-1-1-space-preceding-br-element-should-not-be-collapsed-expected.png +++ b/src/cobalt/layout_tests/testdata/css-text-3/4-1-1-space-preceding-br-element-should-not-be-collapsed-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-text-3/4-1-1-space-preceding-br-element-should-not-be-collapsed.html b/src/cobalt/layout_tests/testdata/css-text-3/4-1-1-space-preceding-br-element-should-not-be-collapsed.html index 4582fbd..fe3ccf4 100644 --- a/src/cobalt/layout_tests/testdata/css-text-3/4-1-1-space-preceding-br-element-should-not-be-collapsed.html +++ b/src/cobalt/layout_tests/testdata/css-text-3/4-1-1-space-preceding-br-element-should-not-be-collapsed.html
@@ -1,9 +1,6 @@ <!DOCTYPE html> <!-- - | The spec is ambiguous on how to handle whitespace preceding a <br> - | element on a line and browsers are not consistent in their - | handling of it. As a result, we're preventing whitespace collapsing - | preceding <br> elements to match Chrome's functionality. + | Whitespace preceding a <br> element should be collapsed. | https://www.w3.org/TR/css3-text/#white-space-phase-1 --> <html> @@ -15,12 +12,20 @@ font-size: 50px; font-weight: bold; } + .wrap-block { + width: 180px; + } + .blue-background { + background-color: #4285f4; + } .collapsed { background-color: #f50057; } </style> </head> <body> + <div class="wrap-block blue-background">Hi there <br>world!</div> + <div><span class="blue-background">Hello, <br></span>world!</div> <div>Hello,<span class="collapsed"> <br></span>world!</div> <div>Hello,<span class="collapsed"> </span><br>world!</div> </body>
diff --git a/src/cobalt/layout_tests/testdata/css-text-3/5-absolute-boxes-in-span-should-not-impact-line-wrapping-expected.png b/src/cobalt/layout_tests/testdata/css-text-3/5-absolute-boxes-in-span-should-not-impact-line-wrapping-expected.png new file mode 100644 index 0000000..bb1b326 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-text-3/5-absolute-boxes-in-span-should-not-impact-line-wrapping-expected.png Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-text-3/5-absolute-boxes-in-span-should-not-impact-line-wrapping.html b/src/cobalt/layout_tests/testdata/css-text-3/5-absolute-boxes-in-span-should-not-impact-line-wrapping.html new file mode 100644 index 0000000..17b1db3 --- /dev/null +++ b/src/cobalt/layout_tests/testdata/css-text-3/5-absolute-boxes-in-span-should-not-impact-line-wrapping.html
@@ -0,0 +1,29 @@ +<!DOCTYPE html> +<!-- + | Absolutely positioned boxes should not be considered during line + | wrapping. + --> +<html> +<head> + <style> + body { + margin: 0px; + font-family: Roboto; + font-size: 20px; + } + .containing-block { + background-color: #03a9f4; + width: 100px; + } + .absolute-block { + position: absolute; + margin: 40px; + } + </style> +</head> +<body> + <div class="containing-block"> + <div><span>abcdefghijkl<span class="absolute-block"> mnop</span>qrst</span></div> + </div> +</body> +</html>
diff --git a/src/cobalt/layout_tests/testdata/css-text-3/layout_tests.txt b/src/cobalt/layout_tests/testdata/css-text-3/layout_tests.txt index fbb14be..a001297 100644 --- a/src/cobalt/layout_tests/testdata/css-text-3/layout_tests.txt +++ b/src/cobalt/layout_tests/testdata/css-text-3/layout_tests.txt
@@ -29,6 +29,7 @@ 4-1-1-space-preceding-br-element-should-not-be-collapsed 4-1-3-spaces-at-beginning-and-end-of-line-should-be-collapsed 4-1-empty-inline-block-should-be-treated-as-non-empty-text +5-absolute-boxes-in-span-should-not-impact-line-wrapping 5-collapsible-leading-white-space-should-not-prevent-soft-wrap-opportunity 5-collapsible-trailing-white-space-should-not-prevent-soft-wrap-opportunity 5-collapsible-trailing-white-space-that-overflows-line-prior-to-collapse-should-not-cause-wrap
diff --git a/src/cobalt/loader/image/jpeg_image_decoder.cc b/src/cobalt/loader/image/jpeg_image_decoder.cc index da8c73e..a249c7e 100644 --- a/src/cobalt/loader/image/jpeg_image_decoder.cc +++ b/src/cobalt/loader/image/jpeg_image_decoder.cc
@@ -331,6 +331,7 @@ case render_tree::kPixelFormatY8: case render_tree::kPixelFormatU8: case render_tree::kPixelFormatV8: + case render_tree::kPixelFormatUV8: case render_tree::kPixelFormatInvalid: { NOTREACHED(); } break;
diff --git a/src/cobalt/loader/image/png_image_decoder.cc b/src/cobalt/loader/image/png_image_decoder.cc index 5e56c69..e048d41 100644 --- a/src/cobalt/loader/image/png_image_decoder.cc +++ b/src/cobalt/loader/image/png_image_decoder.cc
@@ -309,6 +309,7 @@ case render_tree::kPixelFormatY8: case render_tree::kPixelFormatU8: case render_tree::kPixelFormatV8: + case render_tree::kPixelFormatUV8: case render_tree::kPixelFormatInvalid: { NOTREACHED(); } break;
diff --git a/src/cobalt/loader/image/sandbox/sandbox.gyp b/src/cobalt/loader/image/sandbox/sandbox.gyp index 084bd31..88e4597 100644 --- a/src/cobalt/loader/image/sandbox/sandbox.gyp +++ b/src/cobalt/loader/image/sandbox/sandbox.gyp
@@ -45,7 +45,7 @@ 'variables': { 'executable_name': 'image_decoder_sandbox', }, - 'includes': [ '../../../build/deploy.gypi' ], + 'includes': [ '../../../../starboard/build/deploy.gypi' ], }, ], }
diff --git a/src/cobalt/loader/loader.gyp b/src/cobalt/loader/loader.gyp index 230a91e..0b6698f 100644 --- a/src/cobalt/loader/loader.gyp +++ b/src/cobalt/loader/loader.gyp
@@ -116,7 +116,7 @@ 'variables': { 'executable_name': 'loader_test', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, {
diff --git a/src/cobalt/math/math.gyp b/src/cobalt/math/math.gyp index c619a84..2752104 100644 --- a/src/cobalt/math/math.gyp +++ b/src/cobalt/math/math.gyp
@@ -104,7 +104,7 @@ 'variables': { 'executable_name': 'math_test', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, ], }
diff --git a/src/cobalt/media/fetcher_buffered_data_source.cc b/src/cobalt/media/fetcher_buffered_data_source.cc index 33af77b..3d96ea7 100644 --- a/src/cobalt/media/fetcher_buffered_data_source.cc +++ b/src/cobalt/media/fetcher_buffered_data_source.cc
@@ -28,6 +28,16 @@ namespace cobalt { namespace media { +namespace { + +const uint32 kBackwardBytes = 256 * 1024; +const uint32 kInitialForwardBytes = 3 * 256 * 1024; +const uint32 kInitialBufferCapacity = kBackwardBytes + kInitialForwardBytes; + +} // namespace + +using base::CircularBufferShell; + FetcherBufferedDataSource::FetcherBufferedDataSource( const scoped_refptr<base::MessageLoopProxy>& message_loop, const GURL& url, const csp::SecurityCallback& security_callback, @@ -35,7 +45,7 @@ : message_loop_(message_loop), url_(url), network_module_(network_module), - buffer_(kBufferCapacity, base::CircularBufferShell::kReserve), + buffer_(kInitialBufferCapacity, CircularBufferShell::kReserve), buffer_offset_(0), error_occured_(false), last_request_offset_(0), @@ -57,6 +67,11 @@ DCHECK_GE(position, 0); DCHECK_GE(size, 0); + if (position < 0 || size < 0) { + read_cb.Run(kInvalidSize); + return; + } + base::AutoLock auto_lock(lock_); Read_Locked(static_cast<uint64>(position), static_cast<uint64>(size), data, read_cb); @@ -206,11 +221,13 @@ } // If we are overflow, remove some data from the front of the buffer_. - if (buffer_.GetLength() + size > kBufferCapacity) { + if (buffer_.GetLength() + size > buffer_.GetMaxCapacity()) { size_t bytes_skipped; - buffer_.Skip(buffer_.GetLength() + size - kBufferCapacity, &bytes_skipped); - // "+ 0" converts kBufferCapacity into a r-value to avoid link error. - DCHECK_EQ(buffer_.GetLength() + size, kBufferCapacity + 0); + buffer_.Skip(buffer_.GetLength() + size - buffer_.GetMaxCapacity(), + &bytes_skipped); + // "+ 0" converts buffer_.GetMaxCapacity() into a r-value to avoid link + // error. + DCHECK_EQ(buffer_.GetLength() + size, buffer_.GetMaxCapacity() + 0); buffer_offset_ += bytes_skipped; } @@ -360,14 +377,24 @@ // Now we have to issue a new fetch and we no longer care about the range // of the current fetch in progress if there is any. Ideally the request // range starts at |last_read_position_ - kBackwardBytes| with length of - // kBufferCapacity. + // buffer_.GetMaxCapacity(). if (last_read_position_ > kBackwardBytes) { last_request_offset_ = last_read_position_ - kBackwardBytes; } else { last_request_offset_ = 0; } - last_request_size_ = kBufferCapacity; + size_t required_size = + last_read_position_ - last_request_offset_ + pending_read_size_; + if (required_size > buffer_.GetMaxCapacity()) { + // The capacity of the current buffer is not large enough to hold the + // pending read. + size_t new_capacity = + std::max<size_t>(buffer_.GetMaxCapacity() * 2, required_size); + buffer_.IncreaseMaxCapacityTo(new_capacity); + } + + last_request_size_ = buffer_.GetMaxCapacity(); if (last_request_offset_ >= buffer_offset_ && last_request_offset_ <= buffer_offset_ + buffer_.GetLength()) {
diff --git a/src/cobalt/media/fetcher_buffered_data_source.h b/src/cobalt/media/fetcher_buffered_data_source.h index 1c2dd04..530f403 100644 --- a/src/cobalt/media/fetcher_buffered_data_source.h +++ b/src/cobalt/media/fetcher_buffered_data_source.h
@@ -55,9 +55,6 @@ class FetcherBufferedDataSource : public ::media::BufferedDataSource, private net::URLFetcherDelegate { public: - static const uint32 kBackwardBytes = 256 * 1024; - static const uint32 kForwardBytes = 3 * 256 * 1024; - static const uint32 kBufferCapacity = kBackwardBytes + kForwardBytes; static const int64 kInvalidSize = -1; // Because the Fetchers have to be created and destroyed on the same thread,
diff --git a/src/cobalt/media/media_module.h b/src/cobalt/media/media_module.h index addced3..933b214 100644 --- a/src/cobalt/media/media_module.h +++ b/src/cobalt/media/media_module.h
@@ -31,6 +31,7 @@ #include "cobalt/render_tree/resource_provider.h" #include "media/base/shell_media_platform.h" #include "media/base/shell_video_frame_provider.h" +#include "media/filters/shell_video_decoder_impl.h" #include "media/player/web_media_player_delegate.h" namespace cobalt { @@ -64,6 +65,12 @@ return false; } +#if !defined(COBALT_BUILD_TYPE_GOLD) + virtual ::media::ShellRawVideoDecoderFactory* GetRawVideoDecoderFactory() { + return NULL; + } +#endif // !defined(COBALT_RELEASE) + // TODO: Move the following methods into class like MediaModuleBase // to ensure that MediaModule is an interface. // WebMediaPlayerDelegate methods
diff --git a/src/cobalt/media/sandbox/fuzzer_app.cc b/src/cobalt/media/sandbox/fuzzer_app.cc new file mode 100644 index 0000000..4495e34 --- /dev/null +++ b/src/cobalt/media/sandbox/fuzzer_app.cc
@@ -0,0 +1,155 @@ +/* + * 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/media/sandbox/fuzzer_app.h" + +#include "base/file_util.h" +#include "base/logging.h" +#include "starboard/directory.h" +#include "starboard/string.h" + +namespace cobalt { +namespace media { +namespace sandbox { + +FuzzerApp::FuzzerApp() : number_of_iterations_(-1) {} + +bool FuzzerApp::Init(int argc, char* argv[], double min_ratio, + double max_ratio) { + file_entries_.clear(); + + int initial_seed; + if (ParseInitialSeedAndNumberOfIterations(argc, argv, &initial_seed)) { + CollectFiles(argv[argc - 1], min_ratio, max_ratio, initial_seed); + } + return !file_entries_.empty() && number_of_iterations_ > 0; +} + +void FuzzerApp::RunFuzzingLoop() { + DCHECK_GT(number_of_iterations_, 0); + + for (int i = 0; i < number_of_iterations_; ++i) { + for (size_t file_index = 0; file_index < file_entries_.size(); + ++file_index) { + LOG(INFO) << "Fuzzing \"" << file_entries_[file_index].file_name << "\" " + << "with seed " << file_entries_[file_index].fuzzer.seed(); + + Fuzz(file_entries_[file_index].file_name, + file_entries_[file_index].fuzzer.GetFuzzedContent()); + file_entries_[file_index].fuzzer.AdvanceSeed(); + } + } +} + +bool FuzzerApp::ParseInitialSeedAndNumberOfIterations(int argc, char* argv[], + int* initial_seed) { + DCHECK(initial_seed); + + *initial_seed = ZzufFuzzer::kSeedForOriginalContent; + + if (argc != 3 && argc != 4) { + LOG(ERROR) << "Usage: " << argv[0] + << " [initial seed (non-negative integer)]" + << " <number of iterations>" + << " <file name|directory name contains files to be fuzzed>"; + LOG(ERROR) << "For example: " << argv[0] << " 200000 /data/video-files"; + LOG(ERROR) << " " << argv[0] << " 115 200000 /data/video-files"; + return false; + } + + if (argc == 3) { + *initial_seed = ZzufFuzzer::kSeedForOriginalContent; + number_of_iterations_ = SbStringParseSignedInteger(argv[1], NULL, 10); + + if (number_of_iterations_ <= 0) { + LOG(ERROR) << "Invalid 'number of iterations' " << argv[1]; + return false; + } + } else { + DCHECK_EQ(argc, 4); + *initial_seed = SbStringParseSignedInteger(argv[1], NULL, 10); + + if (*initial_seed < 0) { + LOG(ERROR) << "Invalid 'initial seed' " << argv[1]; + return false; + } + + number_of_iterations_ = SbStringParseSignedInteger(argv[2], NULL, 10); + + if (number_of_iterations_ <= 0) { + LOG(ERROR) << "Invalid 'number of iterations' " << argv[2]; + return false; + } + } + + return true; +} + +void FuzzerApp::CollectFiles(const std::string& path_name, double min_ratio, + double max_ratio, int initial_seed) { + file_entries_.clear(); + + SbDirectory directory = SbDirectoryOpen(path_name.c_str(), NULL); + if (!SbDirectoryIsValid(directory)) { + // Assuming it is a file. + AddFile(path_name, min_ratio, max_ratio, initial_seed); + return; + } + + SbDirectoryEntry entry; + while (SbDirectoryGetNext(directory, &entry)) { + std::string file_name = path_name + SB_FILE_SEP_STRING + entry.name; + AddFile(file_name, min_ratio, max_ratio, initial_seed); + } + + SbDirectoryClose(directory); +} + +void FuzzerApp::AddFile(const std::string& file_name, double min_ratio, + double max_ratio, int initial_seed) { + LOG(INFO) << "Loading " << file_name; + + std::string content; + if (!file_util::ReadFileToString(FilePath(file_name), &content)) { + LOG(ERROR) << "Failed to load file " << file_name; + return; + } + if (content.empty()) { + LOG(ERROR) << file_name << " is empty"; + return; + } + std::vector<uint8> uint8_content(content.begin(), content.end()); + std::vector<uint8> parsed_content = + ParseFileContent(file_name, uint8_content); + if (parsed_content.empty()) { + return; + } + file_entries_.push_back(FileEntry(file_name, uint8_content, parsed_content, + min_ratio, max_ratio, initial_seed)); +} + +FuzzerApp::FileEntry::FileEntry(const std::string& file_name, + const std::vector<uint8>& file_content, + const std::vector<uint8>& fuzz_content, + double min_ratio, double max_ratio, + int initial_seed) + : file_name(file_name), + file_content(file_content), + fuzzer(fuzz_content, min_ratio, max_ratio, initial_seed) {} + +} // namespace sandbox +} // namespace media +} // namespace cobalt
diff --git a/src/cobalt/media/sandbox/fuzzer_app.h b/src/cobalt/media/sandbox/fuzzer_app.h new file mode 100644 index 0000000..03292a3 --- /dev/null +++ b/src/cobalt/media/sandbox/fuzzer_app.h
@@ -0,0 +1,82 @@ +/* + * 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_MEDIA_SANDBOX_FUZZER_APP_H_ +#define COBALT_MEDIA_SANDBOX_FUZZER_APP_H_ + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "cobalt/media/sandbox/zzuf_fuzzer.h" + +namespace cobalt { +namespace media { +namespace sandbox { + +// This class provides common functionalities required by fuzzer applications +// including command line parsing, file data collecting, and the fuzzing loop. +class FuzzerApp { + public: + FuzzerApp(); + + bool Init(int argc, char* argv[], double min_ratio = 0.01f, + double max_ratio = 0.05f); + void RunFuzzingLoop(); + + // This function parse |file_content| and returns the content used to fuzz. + // The return value may be different than |file_content|. It will be used to + // generate the |fuzzing_content| parameter passed to Fuzz(). + // The derived class may also take this opportunity to initialize any other + // data required by the fuzzing process and associate with |file_name|. + // If the return value is empty, the file will be excluded during the fuzzing + // process. + virtual std::vector<uint8> ParseFileContent( + const std::string& file_name, const std::vector<uint8>& file_content) = 0; + virtual void Fuzz(const std::string& file_name, + const std::vector<uint8>& fuzzing_content) = 0; + + protected: + ~FuzzerApp() {} + + private: + struct FileEntry { + std::string file_name; + std::vector<uint8> file_content; + ZzufFuzzer fuzzer; + + FileEntry(const std::string& file_name, + const std::vector<uint8>& file_content, + const std::vector<uint8>& fuzz_content, double min_ratio, + double max_ratio, int initial_seed); + }; + + bool ParseInitialSeedAndNumberOfIterations(int argc, char* argv[], + int* initial_seed); + void CollectFiles(const std::string& path_name, double min_ratio, + double max_ratio, int initial_seed); + void AddFile(const std::string& file_name, double min_ratio, double max_ratio, + int initial_seed); + + int number_of_iterations_; + std::vector<FileEntry> file_entries_; +}; + +} // namespace sandbox +} // namespace media +} // namespace cobalt + +#endif // COBALT_MEDIA_SANDBOX_FUZZER_APP_H_
diff --git a/src/cobalt/media/sandbox/in_memory_data_source.cc b/src/cobalt/media/sandbox/in_memory_data_source.cc new file mode 100644 index 0000000..9abd0ca --- /dev/null +++ b/src/cobalt/media/sandbox/in_memory_data_source.cc
@@ -0,0 +1,62 @@ +/* + * 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/media/sandbox/in_memory_data_source.h" + +namespace cobalt { +namespace media { +namespace sandbox { + +InMemoryDataSource::InMemoryDataSource(const std::vector<uint8>& content) + : content_(content) {} + +void InMemoryDataSource::Read(int64 position, int size, uint8* data, + const ReadCB& read_cb) { + DCHECK(data); + + if (position < 0 || size < 0) { + read_cb.Run(kInvalidSize); + return; + } + + uint64 uint64_position = static_cast<uint64>(position); + + if (uint64_position > content_.size() || + uint64_position + size > content_.size()) { + read_cb.Run(kInvalidSize); + return; + } + + if (size == 0) { + read_cb.Run(0); + return; + } + + memcpy(data, &content_[0] + position, size); + read_cb.Run(size); +} + +void InMemoryDataSource::Stop(const base::Closure& callback) { callback.Run(); } + +bool InMemoryDataSource::GetSize(int64* size_out) { + DCHECK(size_out); + *size_out = content_.size(); + return true; +} + +} // namespace sandbox +} // namespace media +} // namespace cobalt
diff --git a/src/cobalt/media/sandbox/in_memory_data_source.h b/src/cobalt/media/sandbox/in_memory_data_source.h new file mode 100644 index 0000000..adfbf42 --- /dev/null +++ b/src/cobalt/media/sandbox/in_memory_data_source.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_MEDIA_SANDBOX_IN_MEMORY_DATA_SOURCE_H_ +#define COBALT_MEDIA_SANDBOX_IN_MEMORY_DATA_SOURCE_H_ + +#include <vector> + +#include "base/compiler_specific.h" +#include "media/base/data_source.h" + +namespace cobalt { +namespace media { +namespace sandbox { + +// A BufferedDataSource that keeps all its data in memory. This is used for +// testing or fuzzing only. +class InMemoryDataSource : public ::media::DataSource { + public: + static const int64 kInvalidSize = -1; + + explicit InMemoryDataSource(const std::vector<uint8>& content); + + // DataSource methods. + void Read(int64 position, int size, uint8* data, + const ReadCB& read_cb) OVERRIDE; + void Stop(const base::Closure& callback) OVERRIDE; + bool GetSize(int64* size_out) OVERRIDE; + bool IsStreaming() OVERRIDE { return false; } + void SetBitrate(int bitrate) OVERRIDE { UNREFERENCED_PARAMETER(bitrate); } + + private: + std::vector<uint8> content_; +}; + +} // namespace sandbox +} // namespace media +} // namespace cobalt + +#endif // COBALT_MEDIA_SANDBOX_IN_MEMORY_DATA_SOURCE_H_
diff --git a/src/cobalt/media/sandbox/media_source_demuxer.cc b/src/cobalt/media/sandbox/media_source_demuxer.cc new file mode 100644 index 0000000..b657f27 --- /dev/null +++ b/src/cobalt/media/sandbox/media_source_demuxer.cc
@@ -0,0 +1,252 @@ +/* + * 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/media/sandbox/media_source_demuxer.h" + +#include <algorithm> +#include <string> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/file_util.h" +#include "base/logging.h" +#include "base/message_loop.h" +#include "media/base/bind_to_loop.h" +#include "media/base/demuxer.h" +#include "media/base/pipeline_status.h" +#include "media/filters/chunk_demuxer.h" + +namespace cobalt { +namespace media { +namespace sandbox { + +namespace { + +using base::Bind; +using ::media::BindToCurrentLoop; +using ::media::DecoderBuffer; +using ::media::DemuxerStream; +using ::media::ChunkDemuxer; + +const char kSourceId[] = "id"; + +// Stub log function. +void Log(const std::string& message) { UNREFERENCED_PARAMETER(message); } + +// Stub need key callback. +void NeedKeyCB(const std::string& type, scoped_array<uint8> init_data, + int init_data_size) { + NOTREACHED(); +} + +bool IsMP4(const std::vector<uint8>& content) { + return content.size() >= 8 && memcmp(&content[4], "ftyp", 4) == 0; +} + +std::vector<std::string> MakeStringVector(const char* string) { + std::vector<std::string> result; + result.push_back(string); + return result; +} + +bool AddSourceBuffer(bool is_mp4, ChunkDemuxer* demuxer) { + const char kMP4Mime[] = "video/mp4"; + const char kAVCCodecs[] = "avc1.640028"; + const char kWebMMime[] = "video/webm"; + const char kVp9Codecs[] = "vp9"; + + std::vector<std::string> codecs = + MakeStringVector(is_mp4 ? kAVCCodecs : kVp9Codecs); + ChunkDemuxer::Status status = + demuxer->AddId(kSourceId, is_mp4 ? kMP4Mime : kWebMMime, codecs); + CHECK_EQ(status, ChunkDemuxer::kOk); + return status == ChunkDemuxer::kOk; +} + +// Helper class to load an adaptive video file and call |append_buffer_cb| for +// every frame. +class Loader : public ::media::DemuxerHost { + public: + typedef base::Callback<void(::media::Buffer*)> AppendBufferCB; + + Loader(const std::vector<uint8>& content, + const AppendBufferCB& append_buffer_cb) + : valid_(true), + ended_(false), + append_buffer_cb_(append_buffer_cb), + content_(content), + offset_(0), + read_in_progress_(false) { + DCHECK(!append_buffer_cb.is_null()); + + demuxer_ = new ChunkDemuxer( + BindToCurrentLoop(Bind(&Loader::OnDemuxerOpen, base::Unretained(this), + IsMP4(content))), + Bind(NeedKeyCB), Bind(Log)); + demuxer_->Initialize( + this, ::media::BindToCurrentLoop( + Bind(&Loader::OnDemuxerStatus, base::Unretained(this)))); + while (valid_ && !ended_) { + MessageLoop::current()->RunUntilIdle(); + } + } + + bool valid() const { return valid_; } + const ::media::VideoDecoderConfig& config() const { return config_; } + + private: + void SetTotalBytes(int64 total_bytes) OVERRIDE { + UNREFERENCED_PARAMETER(total_bytes); + } + void AddBufferedByteRange(int64 start, int64 end) OVERRIDE { + UNREFERENCED_PARAMETER(start); + UNREFERENCED_PARAMETER(end); + } + void AddBufferedTimeRange(base::TimeDelta start, + base::TimeDelta end) OVERRIDE { + UNREFERENCED_PARAMETER(start); + UNREFERENCED_PARAMETER(end); + } + + void SetDuration(base::TimeDelta duration) OVERRIDE { + UNREFERENCED_PARAMETER(duration); + } + void OnDemuxerError(::media::PipelineStatus error) OVERRIDE { + valid_ = false; + } + void OnDemuxerOpen(bool is_mp4) { + valid_ &= AddSourceBuffer(is_mp4, demuxer_); + if (!valid_) { + return; + } + ConsumeContent(); + if (!demuxer_->GetStream(DemuxerStream::VIDEO)) { + valid_ = false; + return; + } + while (valid_ && !ended_) { + ConsumeContent(); + ProduceBuffer(); + MessageLoop::current()->RunUntilIdle(); + } + } + void OnDemuxerStatus(::media::PipelineStatus status) { + if (status == ::media::PIPELINE_OK) { + config_.CopyFrom( + demuxer_->GetStream(DemuxerStream::VIDEO)->video_decoder_config()); + } else { + valid_ = false; + } + } + void ConsumeContent() { + const float kLowWaterMarkInSeconds = 1.f; + const size_t kMaxBytesToAppend = 5 * 1024 * 1024; + + ::media::Ranges<base::TimeDelta> ranges = + demuxer_->GetBufferedRanges(kSourceId); + if (offset_ < content_.size()) { + base::TimeDelta range_end; + if (ranges.size() != 0) { + range_end = ranges.end(ranges.size() - 1); + } + if ((range_end - timestamp_of_last_buffer_).InSecondsF() > + kLowWaterMarkInSeconds) { + return; + } + size_t bytes_to_append = + std::min(kMaxBytesToAppend, content_.size() - offset_); + demuxer_->AppendData(kSourceId, &content_[0] + offset_, bytes_to_append); + offset_ += bytes_to_append; + } + if (offset_ == content_.size()) { + demuxer_->EndOfStream(::media::PIPELINE_OK); + ++offset_; + } + } + void ProduceBuffer() { + if (!read_in_progress_) { + read_in_progress_ = true; + demuxer_->GetStream(DemuxerStream::VIDEO) + ->Read(Bind(&Loader::OnDemuxerRead, base::Unretained(this))); + } + } + void OnDemuxerRead(DemuxerStream::Status status, + const scoped_refptr<DecoderBuffer>& buffer) { + // This should only happen during seeking which won't happen to this class. + DCHECK_NE(status, DemuxerStream::kAborted); + if (status == DemuxerStream::kConfigChanged) { + config_.CopyFrom( + demuxer_->GetStream(DemuxerStream::VIDEO)->video_decoder_config()); + ProduceBuffer(); + return; + } + DCHECK_EQ(status, DemuxerStream::kOk); + if (buffer->IsEndOfStream()) { + ended_ = true; + } else { + timestamp_of_last_buffer_ = buffer->GetTimestamp(); + append_buffer_cb_.Run(buffer); + } + read_in_progress_ = false; + } + + bool valid_; + bool ended_; + AppendBufferCB append_buffer_cb_; + const std::vector<uint8>& content_; + size_t offset_; + bool read_in_progress_; + base::TimeDelta timestamp_of_last_buffer_; + scoped_refptr<ChunkDemuxer> demuxer_; + ::media::VideoDecoderConfig config_; +}; + +} // namespace + +MediaSourceDemuxer::MediaSourceDemuxer(const std::vector<uint8>& content) + : valid_(true) { + Loader loader( + content, Bind(&MediaSourceDemuxer::AppendBuffer, base::Unretained(this))); + valid_ = loader.valid(); + if (valid_) { + config_.CopyFrom(loader.config()); + } else { + au_data_.clear(); + descs_.clear(); + } +} + +void MediaSourceDemuxer::AppendBuffer(::media::Buffer* buffer) { + AUDescriptor desc = {0}; + desc.offset = au_data_.size(); + desc.size = buffer->GetDataSize(); + desc.timestamp = buffer->GetTimestamp(); + + au_data_.insert(au_data_.end(), buffer->GetData(), + buffer->GetData() + buffer->GetDataSize()); + descs_.push_back(desc); +} + +const MediaSourceDemuxer::AUDescriptor& MediaSourceDemuxer::GetFrame( + size_t index) const { + DCHECK_LT(index, descs_.size()); + + return descs_[index]; +} + +} // namespace sandbox +} // namespace media +} // namespace cobalt
diff --git a/src/cobalt/media/sandbox/media_source_demuxer.h b/src/cobalt/media/sandbox/media_source_demuxer.h new file mode 100644 index 0000000..f86679a --- /dev/null +++ b/src/cobalt/media/sandbox/media_source_demuxer.h
@@ -0,0 +1,63 @@ +/* + * 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_MEDIA_SANDBOX_MEDIA_SOURCE_DEMUXER_H_ +#define COBALT_MEDIA_SANDBOX_MEDIA_SOURCE_DEMUXER_H_ + +#include <vector> + +#include "base/basictypes.h" +#include "base/time.h" +#include "media/base/buffers.h" +#include "media/base/video_decoder_config.h" + +namespace cobalt { +namespace media { +namespace sandbox { + +// This class turns a buffer containing a whole media source file into AUs. +class MediaSourceDemuxer { + public: + struct AUDescriptor { + size_t offset; + size_t size; + base::TimeDelta timestamp; + }; + + explicit MediaSourceDemuxer(const std::vector<uint8>& content); + + bool valid() const { return valid_; } + + size_t GetFrameCount() const { return descs_.size(); } + const AUDescriptor& GetFrame(size_t index) const; + const std::vector<uint8>& au_data() const { return au_data_; } + + const ::media::VideoDecoderConfig& config() const { return config_; } + + private: + void AppendBuffer(::media::Buffer* buffer); + + bool valid_; + std::vector<uint8> au_data_; + std::vector<AUDescriptor> descs_; + ::media::VideoDecoderConfig config_; +}; + +} // namespace sandbox +} // namespace media +} // namespace cobalt + +#endif // COBALT_MEDIA_SANDBOX_MEDIA_SOURCE_DEMUXER_H_
diff --git a/src/cobalt/media/sandbox/media_source_sandbox.cc b/src/cobalt/media/sandbox/media_source_sandbox.cc index 74e528b..07861b8 100644 --- a/src/cobalt/media/sandbox/media_source_sandbox.cc +++ b/src/cobalt/media/sandbox/media_source_sandbox.cc
@@ -18,6 +18,8 @@ #include <string> #include <vector> +#include "base/bind.h" +#include "base/bind_helpers.h" #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" #include "base/message_loop.h" @@ -26,6 +28,7 @@ #include "cobalt/base/wrap_main.h" #include "cobalt/media/sandbox/media_sandbox.h" #include "cobalt/media/sandbox/web_media_player_helper.h" +#include "cobalt/render_tree/image.h" #include "media/base/video_frame.h" #include "net/base/net_util.h" @@ -35,9 +38,11 @@ namespace { typedef ::media::WebMediaPlayer::AddIdStatus AddIdStatus; + using base::TimeDelta; using ::media::VideoFrame; using ::media::WebMediaPlayer; +using render_tree::Image; GURL ResolveUrl(const char* arg) { GURL video_url(arg); @@ -137,6 +142,14 @@ } } +scoped_refptr<Image> FrameCB(WebMediaPlayerHelper* player_helper, + const base::TimeDelta& time) { + UNREFERENCED_PARAMETER(time); + + scoped_refptr<VideoFrame> frame = player_helper->GetCurrentFrame(); + return frame ? reinterpret_cast<Image*>(frame->texture_id()) : NULL; +} + int SandboxMain(int argc, char** argv) { if (argc != 3 && argc != 4) { LOG(ERROR) << "Usage: " << argv[0] @@ -198,6 +211,9 @@ scoped_refptr<VideoFrame> last_frame; + media_sandbox.RegisterFrameCB( + base::Bind(FrameCB, base::Unretained(&player_helper))); + for (;;) { AppendData(kAudioId, audio_loader.buffer(), &audio_offset, player); AppendData(kVideoId, video_loader.buffer(), &video_offset, player); @@ -211,7 +227,7 @@ break; } scoped_refptr<VideoFrame> frame = player_helper.GetCurrentFrame(); - if (frame != last_frame) { + if (frame && frame != last_frame) { LOG(INFO) << "showing frame " << frame->GetTimestamp().InMicroseconds(); last_frame = frame; }
diff --git a/src/cobalt/media/sandbox/raw_video_decoder_fuzzer.cc b/src/cobalt/media/sandbox/raw_video_decoder_fuzzer.cc new file mode 100644 index 0000000..b5ab128 --- /dev/null +++ b/src/cobalt/media/sandbox/raw_video_decoder_fuzzer.cc
@@ -0,0 +1,222 @@ +/* + * 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 <map> +#include <vector> + +#include "base/file_path.h" +#include "base/file_util.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/time.h" +#include "cobalt/base/wrap_main.h" +#include "cobalt/media/sandbox/fuzzer_app.h" +#include "cobalt/media/sandbox/media_sandbox.h" +#include "cobalt/media/sandbox/media_source_demuxer.h" +#include "cobalt/media/sandbox/zzuf_fuzzer.h" +#include "media/base/bind_to_loop.h" + +namespace cobalt { +namespace media { +namespace sandbox { +namespace { + +using base::Time; +using ::media::BindToCurrentLoop; +using ::media::DecoderBuffer; +using ::media::ShellRawVideoDecoder; +using ::media::VideoFrame; + +class VideoDecoderFuzzer { + public: + VideoDecoderFuzzer(const std::vector<uint8_t>& au_data, + MediaSourceDemuxer* demuxer, ShellRawVideoDecoder* decoder) + : au_data_(au_data), + demuxer_(demuxer), + decoder_(decoder), + au_index_(0), + error_occured_(false), + eos_decoded_(false) {} + + void Fuzz() { + UpdateCurrentAUBuffer(); + decoder_->Decode(current_au_buffer_, BindToCurrentLoop(base::Bind( + &VideoDecoderFuzzer::FrameDecoded, + base::Unretained(this)))); + MessageLoop::current()->RunUntilIdle(); + DCHECK(IsEnded()); + } + + private: + void UpdateCurrentAUBuffer() { + if (au_index_ < demuxer_->GetFrameCount()) { + MediaSourceDemuxer::AUDescriptor desc = demuxer_->GetFrame(au_index_); + current_au_buffer_ = + ::media::ShellBufferFactory::Instance()->AllocateBufferNow(desc.size); + memcpy(current_au_buffer_->GetWritableData(), &au_data_[0] + desc.offset, + desc.size); + ++au_index_; + } else if (!current_au_buffer_->IsEndOfStream()) { + current_au_buffer_ = + DecoderBuffer::CreateEOSBuffer(::media::kNoTimestamp()); + } + } + void FrameDecoded(ShellRawVideoDecoder::DecodeStatus status, + const scoped_refptr<VideoFrame>& frame) { + if (frame) { + last_frame_decoded_time_ = Time::Now(); + if (frame->IsEndOfStream()) { + eos_decoded_ = true; + } + } + switch (status) { + case ShellRawVideoDecoder::FRAME_DECODED: + case ShellRawVideoDecoder::NEED_MORE_DATA: + UpdateCurrentAUBuffer(); + break; + case ShellRawVideoDecoder::FATAL_ERROR: + error_occured_ = true; + // Even if there is a fatal error, we still want to keep sending the + // rest buffers to decoder. + UpdateCurrentAUBuffer(); + break; + case ShellRawVideoDecoder::RETRY_WITH_SAME_BUFFER: + if (current_au_buffer_->IsEndOfStream() && + (Time::Now() - last_frame_decoded_time_).InMilliseconds() > 500) { + error_occured_ = true; + } + break; + } + if (!IsEnded()) { + decoder_->Decode( + current_au_buffer_, + BindToCurrentLoop(base::Bind(&VideoDecoderFuzzer::FrameDecoded, + base::Unretained(this)))); + } + } + bool IsEnded() const { + if (error_occured_) return true; + return eos_decoded_ || + (error_occured_ && current_au_buffer_->IsEndOfStream()); + } + + const std::vector<uint8_t>& au_data_; + MediaSourceDemuxer* demuxer_; + ShellRawVideoDecoder* decoder_; + size_t au_index_; + scoped_refptr<DecoderBuffer> current_au_buffer_; + bool error_occured_; + bool eos_decoded_; + Time last_frame_decoded_time_; +}; + +int CalculateCheckSum(const std::vector<uint8>& data) { + int checksum = 0; + for (size_t i = 0; i < data.size(); ++i) { + checksum += data[i]; + } + return checksum; +} + +// This function replace the original data inside the original file with the +// fuzzed data to created a valid container with fuzzed AUs. |filename| should +// contain a file that inside a path readable by the host. +void DumpFuzzedData(const std::string& filename, std::vector<uint8> container, + const MediaSourceDemuxer& demuxer, + const ZzufFuzzer& fuzzer) { + std::vector<uint8>::iterator last_found = container.begin(); + for (size_t i = 0; i < demuxer.GetFrameCount(); ++i) { + MediaSourceDemuxer::AUDescriptor desc = demuxer.GetFrame(i); + std::vector<uint8>::const_iterator begin = + demuxer.au_data().begin() + desc.offset; + std::vector<uint8>::const_iterator end = begin + desc.size; + std::vector<uint8>::iterator offset = + std::search(last_found, container.end(), begin, end); + std::copy(fuzzer.GetFuzzedContent().begin() + desc.offset, + fuzzer.GetFuzzedContent().begin() + desc.offset + desc.size, + offset); + last_found = offset + desc.size + 1; + } + file_util::WriteFile(FilePath(filename), + reinterpret_cast<const char*>(&container[0]), + container.size()); +} + +class RawVideoDecoderFuzzerApp : public FuzzerApp { + public: + explicit RawVideoDecoderFuzzerApp(MediaSandbox* media_sandbox) + : media_sandbox_(media_sandbox) {} + ~RawVideoDecoderFuzzerApp() { + while (!demuxers_.empty()) { + delete demuxers_.begin()->second; + demuxers_.erase(demuxers_.begin()); + } + } + + std::vector<uint8> ParseFileContent( + const std::string& file_name, + const std::vector<uint8>& file_content) OVERRIDE { + std::string ext = FilePath(file_name).Extension(); + if (ext != ".webm" && ext != ".mp4") { + LOG(ERROR) << "Skip unsupported file " << file_name; + return std::vector<uint8>(); + } + + scoped_ptr<MediaSourceDemuxer> demuxer(new MediaSourceDemuxer( + std::vector<uint8>(file_content.begin(), file_content.end()))); + if (demuxer->valid() && demuxer->GetFrameCount() > 0) { + demuxers_[file_name] = demuxer.release(); + return demuxers_[file_name]->au_data(); + } + LOG(ERROR) << "Failed to demux video: " << file_name; + return std::vector<uint8>(); + } + + void Fuzz(const std::string& file_name, + const std::vector<uint8>& fuzzing_content) OVERRIDE { + DCHECK(demuxers_.find(file_name) != demuxers_.end()); + MediaSourceDemuxer* demuxer = demuxers_[file_name]; + scoped_ptr<ShellRawVideoDecoder> decoder = + media_sandbox_->GetMediaModule()->GetRawVideoDecoderFactory()->Create( + demuxer->config(), NULL, false); + DCHECK(decoder); + VideoDecoderFuzzer decoder_fuzzer(fuzzing_content, demuxer, decoder.get()); + decoder_fuzzer.Fuzz(); + } + + private: + MediaSandbox* media_sandbox_; + std::map<std::string, MediaSourceDemuxer*> demuxers_; +}; + +int SandboxMain(int argc, char** argv) { + MediaSandbox media_sandbox( + argc, argv, FilePath(FILE_PATH_LITERAL("raw_video_decoder_fuzzer.json"))); + RawVideoDecoderFuzzerApp fuzzer_app(&media_sandbox); + + if (fuzzer_app.Init(argc, argv)) { + fuzzer_app.RunFuzzingLoop(); + } + + return 0; +} + +} // namespace +} // namespace sandbox +} // namespace media +} // namespace cobalt + +COBALT_WRAP_SIMPLE_MAIN(cobalt::media::sandbox::SandboxMain);
diff --git a/src/cobalt/media/sandbox/sandbox.gyp b/src/cobalt/media/sandbox/sandbox.gyp index 8c055c4..3290d35 100644 --- a/src/cobalt/media/sandbox/sandbox.gyp +++ b/src/cobalt/media/sandbox/sandbox.gyp
@@ -16,6 +16,9 @@ # media/renderer interface. { + 'variables': { + 'has_zzuf': '<!(python ../../../build/dir_exists.py ../../../third_party/zzuf)', + }, 'targets': [ # This target will build a sandbox application that allows for easy # experimentation with the media interface on any platform. This can @@ -54,7 +57,7 @@ 'variables': { 'executable_name': 'web_media_player_sandbox', }, - 'includes': [ '../../build/deploy.gypi' ], + 'includes': [ '../../../starboard/build/deploy.gypi' ], }, # This target will build a sandbox application that allows for easy @@ -65,9 +68,9 @@ 'sources': [ 'media_sandbox.cc', 'media_sandbox.h', + 'media_source_sandbox.cc', 'web_media_player_helper.cc', 'web_media_player_helper.h', - 'media_source_sandbox.cc', ], 'dependencies': [ '<(DEPTH)/cobalt/base/base.gyp:base', @@ -92,7 +95,98 @@ 'variables': { 'executable_name': 'media_source_sandbox', }, - 'includes': [ '../../build/deploy.gypi' ], + 'includes': [ '../../../starboard/build/deploy.gypi' ], }, ], + 'conditions': [ + ['OS == "starboard" and has_zzuf == "True"', { + 'targets': [ + # This target will build a sandbox application that allows for fuzzing + # decoder. + { + 'target_name': 'raw_video_decoder_fuzzer', + 'type': '<(final_executable_type)', + 'sources': [ + 'fuzzer_app.cc', + 'fuzzer_app.h', + 'media_sandbox.cc', + 'media_sandbox.h', + 'media_source_demuxer.cc', + 'media_source_demuxer.h', + 'raw_video_decoder_fuzzer.cc', + 'zzuf_fuzzer.cc', + 'zzuf_fuzzer.h', + ], + 'dependencies': [ + '<(DEPTH)/cobalt/base/base.gyp:base', + # Use test data from browser to avoid keeping two copies of video files. + '<(DEPTH)/cobalt/browser/browser.gyp:browser_copy_test_data', + '<(DEPTH)/cobalt/loader/loader.gyp:loader', + '<(DEPTH)/cobalt/media/media.gyp:media', + '<(DEPTH)/cobalt/network/network.gyp:network', + '<(DEPTH)/cobalt/renderer/renderer.gyp:renderer', + '<(DEPTH)/cobalt/system_window/system_window.gyp:system_window', + '<(DEPTH)/cobalt/trace_event/trace_event.gyp:trace_event', + '<(DEPTH)/googleurl/googleurl.gyp:googleurl', + '<(DEPTH)/third_party/zzuf/zzuf.gyp:zzuf', + ], + }, + + { + 'target_name': 'raw_video_decoder_fuzzer_deploy', + 'type': 'none', + 'dependencies': [ + 'raw_video_decoder_fuzzer', + ], + 'variables': { + 'executable_name': 'raw_video_decoder_fuzzer', + }, + 'includes': [ '../../../starboard/build/deploy.gypi' ], + }, + + # This target will build a sandbox application that allows for fuzzing + # shell demuxers. + { + 'target_name': 'shell_demuxer_fuzzer', + 'type': '<(final_executable_type)', + 'sources': [ + 'fuzzer_app.cc', + 'fuzzer_app.h', + 'in_memory_data_source.cc', + 'in_memory_data_source.h', + 'media_sandbox.cc', + 'media_sandbox.h', + 'shell_demuxer_fuzzer.cc', + 'zzuf_fuzzer.cc', + 'zzuf_fuzzer.h', + ], + 'dependencies': [ + '<(DEPTH)/cobalt/base/base.gyp:base', + # Use test data from browser to avoid keeping two copies of video files. + '<(DEPTH)/cobalt/browser/browser.gyp:browser_copy_test_data', + '<(DEPTH)/cobalt/loader/loader.gyp:loader', + '<(DEPTH)/cobalt/media/media.gyp:media', + '<(DEPTH)/cobalt/network/network.gyp:network', + '<(DEPTH)/cobalt/renderer/renderer.gyp:renderer', + '<(DEPTH)/cobalt/system_window/system_window.gyp:system_window', + '<(DEPTH)/cobalt/trace_event/trace_event.gyp:trace_event', + '<(DEPTH)/googleurl/googleurl.gyp:googleurl', + '<(DEPTH)/third_party/zzuf/zzuf.gyp:zzuf', + ], + }, + + { + 'target_name': 'shell_demuxer_fuzzer_deploy', + 'type': 'none', + 'dependencies': [ + 'shell_demuxer_fuzzer', + ], + 'variables': { + 'executable_name': 'shell_demuxer_fuzzer', + }, + 'includes': [ '../../../starboard/build/deploy.gypi' ], + }, + ], + }], + ], }
diff --git a/src/cobalt/media/sandbox/shell_demuxer_fuzzer.cc b/src/cobalt/media/sandbox/shell_demuxer_fuzzer.cc new file mode 100644 index 0000000..c469c5c --- /dev/null +++ b/src/cobalt/media/sandbox/shell_demuxer_fuzzer.cc
@@ -0,0 +1,186 @@ +/* + * 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 <vector> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/compiler_specific.h" +#include "base/file_path.h" +#include "base/memory/ref_counted.h" +#include "cobalt/base/wrap_main.h" +#include "cobalt/media/sandbox/fuzzer_app.h" +#include "cobalt/media/sandbox/in_memory_data_source.h" +#include "cobalt/media/sandbox/media_sandbox.h" +#include "media/base/bind_to_loop.h" +#include "media/base/pipeline_status.h" +#include "media/filters/shell_demuxer.h" + +namespace cobalt { +namespace media { +namespace sandbox { +namespace { + +using base::Bind; +using ::media::BindToCurrentLoop; +using ::media::DecoderBuffer; +using ::media::Demuxer; +using ::media::DemuxerHost; +using ::media::DemuxerStream; +using ::media::PipelineStatus; +using ::media::ShellDemuxer; + +class ShellDemuxerFuzzer : DemuxerHost { + public: + explicit ShellDemuxerFuzzer(const std::vector<uint8>& content) + : error_occurred_(false), eos_count_(0), stopped_(false) { + demuxer_ = new ShellDemuxer(base::MessageLoopProxy::current(), + new InMemoryDataSource(content)); + } + + void Fuzz() { + demuxer_->Initialize( + this, Bind(&ShellDemuxerFuzzer::InitializeCB, base::Unretained(this))); + + // Check if there is any error or if both of the audio and video streams + // have reached eos. + while (!error_occurred_ && eos_count_ != 2) { + MessageLoop::current()->RunUntilIdle(); + } + + demuxer_->Stop(Bind(&ShellDemuxerFuzzer::StopCB, base::Unretained(this))); + + while (!stopped_) { + MessageLoop::current()->RunUntilIdle(); + } + } + + private: + // DataSourceHost methods (parent class of DemuxerHost) + void SetTotalBytes(int64 total_bytes) OVERRIDE { + UNREFERENCED_PARAMETER(total_bytes); + } + + void AddBufferedByteRange(int64 start, int64 end) OVERRIDE { + UNREFERENCED_PARAMETER(start); + UNREFERENCED_PARAMETER(end); + } + + void AddBufferedTimeRange(base::TimeDelta start, + base::TimeDelta end) OVERRIDE { + UNREFERENCED_PARAMETER(start); + UNREFERENCED_PARAMETER(end); + } + + // DemuxerHost methods + void SetDuration(base::TimeDelta duration) OVERRIDE { + UNREFERENCED_PARAMETER(duration); + } + void OnDemuxerError(PipelineStatus error) OVERRIDE { + UNREFERENCED_PARAMETER(error); + error_occurred_ = true; + } + + void InitializeCB(PipelineStatus status) { + DCHECK(!error_occurred_); + if (status != ::media::PIPELINE_OK) { + error_occurred_ = true; + return; + } + scoped_refptr<DemuxerStream> audio_stream = + demuxer_->GetStream(DemuxerStream::AUDIO); + scoped_refptr<DemuxerStream> video_stream = + demuxer_->GetStream(DemuxerStream::VIDEO); + if (!audio_stream || !video_stream || + !audio_stream->audio_decoder_config().IsValidConfig() || + !video_stream->video_decoder_config().IsValidConfig()) { + error_occurred_ = true; + return; + } + audio_stream->Read(BindToCurrentLoop(Bind( + &ShellDemuxerFuzzer::ReadCB, base::Unretained(this), audio_stream))); + video_stream->Read(BindToCurrentLoop(Bind( + &ShellDemuxerFuzzer::ReadCB, base::Unretained(this), video_stream))); + } + + void StopCB() { stopped_ = true; } + + void ReadCB(const scoped_refptr<DemuxerStream>& stream, + DemuxerStream::Status status, + const scoped_refptr<DecoderBuffer>& buffer) { + DCHECK_NE(status, DemuxerStream::kAborted); + if (status == DemuxerStream::kOk) { + DCHECK(buffer); + if (buffer->IsEndOfStream()) { + ++eos_count_; + return; + } + } + DCHECK(!error_occurred_); + stream->Read(BindToCurrentLoop( + Bind(&ShellDemuxerFuzzer::ReadCB, base::Unretained(this), stream))); + } + + bool error_occurred_; + int eos_count_; + bool stopped_; + scoped_refptr<ShellDemuxer> demuxer_; +}; + +class ShellDemuxerFuzzerApp : public FuzzerApp { + public: + explicit ShellDemuxerFuzzerApp(MediaSandbox* media_sandbox) + : media_sandbox_(media_sandbox) {} + + std::vector<uint8> ParseFileContent( + const std::string& file_name, + const std::vector<uint8>& file_content) OVERRIDE { + std::string ext = FilePath(file_name).Extension(); + if (ext != ".flv" && ext != ".mp4") { + LOG(ERROR) << "Skip unsupported file " << file_name; + return std::vector<uint8>(); + } + return file_content; + } + + void Fuzz(const std::string& file_name, + const std::vector<uint8>& fuzzing_content) OVERRIDE { + ShellDemuxerFuzzer demuxer_fuzzer(fuzzing_content); + demuxer_fuzzer.Fuzz(); + } + + private: + MediaSandbox* media_sandbox_; +}; + +int SandboxMain(int argc, char** argv) { + MediaSandbox media_sandbox( + argc, argv, FilePath(FILE_PATH_LITERAL("shell_demuxer_fuzzer.json"))); + ShellDemuxerFuzzerApp fuzzer_app(&media_sandbox); + + if (fuzzer_app.Init(argc, argv)) { + fuzzer_app.RunFuzzingLoop(); + } + + return 0; +} + +} // namespace +} // namespace sandbox +} // namespace media +} // namespace cobalt + +COBALT_WRAP_SIMPLE_MAIN(cobalt::media::sandbox::SandboxMain);
diff --git a/src/cobalt/media/sandbox/zzuf_fuzzer.cc b/src/cobalt/media/sandbox/zzuf_fuzzer.cc new file mode 100644 index 0000000..bb52fa7 --- /dev/null +++ b/src/cobalt/media/sandbox/zzuf_fuzzer.cc
@@ -0,0 +1,66 @@ +/* + * 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/media/sandbox/zzuf_fuzzer.h" + +#include "base/logging.h" + +namespace cobalt { +namespace media { +namespace sandbox { + +ZzufFuzzer::ZzufFuzzer(const std::vector<uint8>& original_content, + double min_ratio, double max_ratio, + int initial_seed /*= kSeedForOriginalContent*/) + : seed_(initial_seed) { + original_content_.assign(original_content.begin(), original_content.end()); + DCHECK(!original_content_.empty()); + + _zz_fd_init(); + zzuf_set_ratio(min_ratio, max_ratio); + + UpdateFuzzedContent(); +} + +ZzufFuzzer::~ZzufFuzzer() { _zz_fd_fini(); } + +void ZzufFuzzer::AdvanceSeed() { + ++seed_; + UpdateFuzzedContent(); +} + +void ZzufFuzzer::UpdateFuzzedContent() { + // Because zzuf is not actually doing any io, the fd just serves as an index + // to its fd to fuzz context map. + static const int kFd = 0; + + if (seed_ == kSeedForOriginalContent) { + fuzzed_content_ = original_content_; + return; + } + + fuzzed_content_ = original_content_; + + zzuf_set_seed(seed_); + + _zz_register(kFd); + _zz_fuzz(kFd, &fuzzed_content_[0], fuzzed_content_.size()); + _zz_unregister(kFd); +} + +} // namespace sandbox +} // namespace media +} // namespace cobalt
diff --git a/src/cobalt/media/sandbox/zzuf_fuzzer.h b/src/cobalt/media/sandbox/zzuf_fuzzer.h new file mode 100644 index 0000000..6020b22 --- /dev/null +++ b/src/cobalt/media/sandbox/zzuf_fuzzer.h
@@ -0,0 +1,69 @@ +/* + * 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_MEDIA_SANDBOX_ZZUF_FUZZER_H_ +#define COBALT_MEDIA_SANDBOX_ZZUF_FUZZER_H_ + +#include <vector> + +#include "base/basictypes.h" + +extern "C" { +#include "third_party/zzuf/src/common/fd.h" +#include "third_party/zzuf/src/common/fuzz.h" +} + +namespace cobalt { +namespace media { +namespace sandbox { + +// This class provide fuzzed content based on the original content and a seed +// that can be advanced. By default the first fuzzed content it returns is the +// same as the original content. +class ZzufFuzzer { + public: + static const int kSeedForOriginalContent = -1; + + // |initial_seed| can be used to "fast-forward" to the particular seed that + // generates the data to cause an issue. During normal fuzzing this should be + // left to its default argument to ensure that it covers the original data. + ZzufFuzzer(const std::vector<uint8>& original_content, double min_ratio, + double max_ratio, int initial_seed = kSeedForOriginalContent); + ~ZzufFuzzer(); + + int seed() const { return seed_; } + const std::vector<uint8_t>& GetOriginalContent() const { + return original_content_; + } + const std::vector<uint8_t>& GetFuzzedContent() const { + return fuzzed_content_; + } + + void AdvanceSeed(); + + private: + void UpdateFuzzedContent(); + + int seed_; + std::vector<uint8_t> original_content_; + std::vector<uint8_t> fuzzed_content_; +}; + +} // namespace sandbox +} // namespace media +} // namespace cobalt + +#endif // COBALT_MEDIA_SANDBOX_ZZUF_FUZZER_H_
diff --git a/src/cobalt/media/shell_video_data_allocator_common.cc b/src/cobalt/media/shell_video_data_allocator_common.cc index 221119b..be0107b 100644 --- a/src/cobalt/media/shell_video_data_allocator_common.cc +++ b/src/cobalt/media/shell_video_data_allocator_common.cc
@@ -34,10 +34,12 @@ using cobalt::render_tree::kPixelFormatRGBA8; using cobalt::render_tree::MultiPlaneImageDataDescriptor; using cobalt::render_tree::ResourceProvider; +using cobalt::render_tree::kMultiPlaneImageFormatYUV2PlaneBT709; using cobalt::render_tree::kMultiPlaneImageFormatYUV3PlaneBT709; using cobalt::render_tree::kPixelFormatU8; using cobalt::render_tree::kPixelFormatV8; using cobalt::render_tree::kPixelFormatY8; +using cobalt::render_tree::kPixelFormatUV8; namespace { void ReleaseImage(scoped_refptr<Image> /* image */) {} @@ -76,35 +78,35 @@ scoped_refptr<FrameBufferCommon> frame_buffer_common = base::polymorphic_downcast<FrameBufferCommon*>(frame_buffer.get()); + DCHECK_LE(frame_buffer->data(), param.y_data()); + DCHECK_LE(param.y_data() + param.y_pitch() * param.decoded_height(), + param.u_data()); + DCHECK_LE(param.u_data() + param.uv_pitch() * param.decoded_height() / 2, + param.v_data()); + DCHECK_LE(param.v_data() + param.uv_pitch() * param.decoded_height() / 2, + frame_buffer->data() + frame_buffer->size()); + // TODO: Ensure it work with visible_rect with non-zero left and // top. Note that simply add offset to the image buffer may cause alignment // issues. - gfx::Size decoded_size(param.decoded_width(), param.decoded_height()); gfx::Size visible_size(param.visible_rect().size()); - intptr_t offset = 0; - int pitch_in_bytes = decoded_size.width(); - - DCHECK_EQ(pitch_in_bytes % 2, 0) << pitch_in_bytes << " has to be even."; - // Create image data descriptor for the frame in I420. MultiPlaneImageDataDescriptor descriptor( kMultiPlaneImageFormatYUV3PlaneBT709); descriptor.AddPlane( - offset, ImageDataDescriptor(visible_size, kPixelFormatY8, - kAlphaFormatUnpremultiplied, pitch_in_bytes)); - offset += pitch_in_bytes * decoded_size.height(); + param.y_data() - frame_buffer->data(), + ImageDataDescriptor(visible_size, kPixelFormatY8, + kAlphaFormatUnpremultiplied, param.y_pitch())); visible_size.SetSize(visible_size.width() / 2, visible_size.height() / 2); - pitch_in_bytes /= 2; descriptor.AddPlane( - offset, ImageDataDescriptor(visible_size, kPixelFormatU8, - kAlphaFormatUnpremultiplied, pitch_in_bytes)); - offset += pitch_in_bytes * decoded_size.height() / 2; + param.u_data() - frame_buffer->data(), + ImageDataDescriptor(visible_size, kPixelFormatU8, + kAlphaFormatUnpremultiplied, param.uv_pitch())); descriptor.AddPlane( - offset, ImageDataDescriptor(visible_size, kPixelFormatV8, - kAlphaFormatUnpremultiplied, pitch_in_bytes)); - offset += pitch_in_bytes * decoded_size.height() / 2; - CHECK_EQ(offset, param.decoded_width() * param.decoded_height() * 3 / 2); + param.v_data() - frame_buffer->data(), + ImageDataDescriptor(visible_size, kPixelFormatV8, + kAlphaFormatUnpremultiplied, param.uv_pitch())); scoped_refptr<Image> image = resource_provider_->CreateMultiPlaneImageFromRawMemory( @@ -128,32 +130,26 @@ // TODO: Ensure it work with visible_rect with non-zero left and // top. Note that simply add offset to the image buffer may cause alignment // issues. - gfx::Size decoded_size(param.decoded_width(), param.decoded_height()); gfx::Size visible_size(param.visible_rect().size()); intptr_t offset = 0; - int pitch_in_bytes = decoded_size.width(); + int pitch_in_bytes = param.y_pitch(); DCHECK_EQ(pitch_in_bytes % 2, 0) << pitch_in_bytes << " has to be even."; - // Create image data descriptor for the frame in I420. + // Create image data descriptor for the frame in NV12. MultiPlaneImageDataDescriptor descriptor( - kMultiPlaneImageFormatYUV3PlaneBT709); + kMultiPlaneImageFormatYUV2PlaneBT709); descriptor.AddPlane( offset, ImageDataDescriptor(visible_size, kPixelFormatY8, kAlphaFormatPremultiplied, pitch_in_bytes)); - offset += pitch_in_bytes * decoded_size.height(); + offset += pitch_in_bytes * param.decoded_height(); visible_size.SetSize(visible_size.width() / 2, visible_size.height() / 2); - pitch_in_bytes /= 2; descriptor.AddPlane( - offset, ImageDataDescriptor(visible_size, kPixelFormatU8, + offset, ImageDataDescriptor(visible_size, kPixelFormatUV8, kAlphaFormatPremultiplied, pitch_in_bytes)); - offset += pitch_in_bytes * decoded_size.height() / 2; - descriptor.AddPlane( - offset, ImageDataDescriptor(visible_size, kPixelFormatV8, - kAlphaFormatPremultiplied, pitch_in_bytes)); - offset += pitch_in_bytes * decoded_size.height() / 2; - CHECK_EQ(offset, param.decoded_width() * param.decoded_height() * 3 / 2); + offset += pitch_in_bytes * param.decoded_height() / 2; + DCHECK_EQ(offset, pitch_in_bytes * param.decoded_height() * 3 / 2); scoped_refptr<Image> image = resource_provider_->CreateMultiPlaneImageFromRawMemory(
diff --git a/src/cobalt/network/network.gyp b/src/cobalt/network/network.gyp index 3324a9c..1cbcb99 100644 --- a/src/cobalt/network/network.gyp +++ b/src/cobalt/network/network.gyp
@@ -123,7 +123,7 @@ 'variables': { 'executable_name': 'network_test', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, ], }
diff --git a/src/cobalt/network/persistent_cookie_store_test.cc b/src/cobalt/network/persistent_cookie_store_test.cc index ba935a3..7d2762b 100644 --- a/src/cobalt/network/persistent_cookie_store_test.cc +++ b/src/cobalt/network/persistent_cookie_store_test.cc
@@ -18,9 +18,9 @@ #include <vector> -#include "base/message_loop.h" #include "base/file_path.h" #include "base/file_util.h" +#include "base/message_loop.h" #include "base/path_service.h" #include "base/stringprintf.h" #include "base/time.h" @@ -28,8 +28,8 @@ #include "cobalt/storage/savegame.h" #include "cobalt/storage/savegame_fake.h" #include "cobalt/storage/storage_manager.h" -#include "net/cookies/canonical_cookie.h" #include "googleurl/src/gurl.h" +#include "net/cookies/canonical_cookie.h" #include "sql/connection.h" #include "sql/statement.h" #include "testing/gtest/include/gtest/gtest.h" @@ -58,7 +58,7 @@ CallbackWaiter() : was_called_event_(true, false) {} virtual ~CallbackWaiter() {} bool TimedWait() { - return was_called_event_.TimedWait(base::TimeDelta::FromMilliseconds(500)); + return was_called_event_.TimedWait(base::TimeDelta::FromSeconds(5)); } protected: @@ -120,7 +120,6 @@ DISALLOW_COPY_AND_ASSIGN(CookieVerifier); }; - std::string GetSavePath() { FilePath test_path; CHECK(PathService::Get(paths::DIR_COBALT_TEST_OUT, &test_path));
diff --git a/src/cobalt/render_tree/font_provider.h b/src/cobalt/render_tree/font_provider.h index 7c47a50..c5a3380 100644 --- a/src/cobalt/render_tree/font_provider.h +++ b/src/cobalt/render_tree/font_provider.h
@@ -28,10 +28,10 @@ // character based upon what it considers to be the best match. class FontProvider { public: - // Returns a font-glyph combination based upon a passed in character. The - // returned font is guaranteed to be non-NULL. However, the glyph index may - // be set to |kInvalidGlyphIndex| if no font is found that supports the - // requested character. + // Returns the font-glyph combination that the FontProvider considers to be + // the best match for the passed in character. The returned font is guaranteed + // to be non-NULL. However, the glyph index may be set to |kInvalidGlyphIndex| + // if the returned font does not provide a glyph for the character. virtual const scoped_refptr<Font>& GetCharacterFont( int32 utf32_character, GlyphIndex* glyph_index) = 0;
diff --git a/src/cobalt/render_tree/image.h b/src/cobalt/render_tree/image.h index 55a1bc8..8faa040 100644 --- a/src/cobalt/render_tree/image.h +++ b/src/cobalt/render_tree/image.h
@@ -32,6 +32,7 @@ kPixelFormatY8, kPixelFormatU8, kPixelFormatV8, + kPixelFormatUV8, kPixelFormatInvalid, }; @@ -47,6 +48,8 @@ return 1; case kPixelFormatV8: return 1; + case kPixelFormatUV8: + return 2; case kPixelFormatInvalid: default: DLOG(FATAL) << "Unexpected pixel format."; @@ -115,6 +118,9 @@ // A YUV image where each channel, Y, U and V, is stored as a separate // single-channel image plane. kMultiPlaneImageFormatYUV3PlaneBT709, + // A YUV image where the Y channel is stored as a single-channel image plane + // and the U and V channels are interleaved in a second image plane. + kMultiPlaneImageFormatYUV2PlaneBT709, }; // Like the ImageDataDescriptor object, a MultiPlaneImageDataDescriptor
diff --git a/src/cobalt/render_tree/render_tree.gyp b/src/cobalt/render_tree/render_tree.gyp index 9f53105..5af25ff 100644 --- a/src/cobalt/render_tree/render_tree.gyp +++ b/src/cobalt/render_tree/render_tree.gyp
@@ -110,7 +110,7 @@ 'variables': { 'executable_name': 'render_tree_test', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, ], }
diff --git a/src/cobalt/renderer/animations_test.cc b/src/cobalt/renderer/animations_test.cc index 9cd167c..8c488a5 100644 --- a/src/cobalt/renderer/animations_test.cc +++ b/src/cobalt/renderer/animations_test.cc
@@ -38,18 +38,59 @@ namespace renderer { namespace { +scoped_refptr<Image> CreateDummyImage(ResourceProvider* resource_provider) { + // Initialize the image data and store a predictable, testable pattern + // of image data into it. + math::Size image_size(16, 16); + + int rgba_mapping[4] = {0, 1, 2, 3}; + render_tree::PixelFormat pixel_format = render_tree::kPixelFormatInvalid; + if (resource_provider->PixelFormatSupported(render_tree::kPixelFormatRGBA8)) { + pixel_format = render_tree::kPixelFormatRGBA8; + } else if (resource_provider->PixelFormatSupported( + render_tree::kPixelFormatBGRA8)) { + pixel_format = render_tree::kPixelFormatBGRA8; + rgba_mapping[0] = 2; + rgba_mapping[2] = 0; + } else { + NOTREACHED() << "Unsupported pixel format."; + } + + scoped_ptr<render_tree::ImageData> image_data = + resource_provider->AllocateImageData( + image_size, pixel_format, render_tree::kAlphaFormatPremultiplied); + for (int i = 0; i < image_size.width() * image_size.height(); ++i) { + image_data->GetMemory()[i * 4 + rgba_mapping[0]] = 1; + image_data->GetMemory()[i * 4 + rgba_mapping[1]] = 2; + image_data->GetMemory()[i * 4 + rgba_mapping[2]] = 3; + image_data->GetMemory()[i * 4 + rgba_mapping[3]] = 255; + } + + // Create and return the new image. + return resource_provider->CreateImage(image_data.Pass()); +} + void AnimateImageNode(base::WaitableEvent* animate_has_started, base::WaitableEvent* image_ready, - scoped_refptr<Image>* image, + scoped_refptr<Image>* image, bool* first_animate, ImageNode::Builder* image_node, base::TimeDelta time) { UNREFERENCED_PARAMETER(time); + if (!*first_animate) { + // We only do the test the first time this animation runs, ignore the + // subsequent animate calls. + return; + } + *first_animate = false; + // Time to animate the image! First signal that we are in the animation // callback which will prompt the CreateImageThread to create the image. animate_has_started->Signal(); // Wait for the CreateImageThread to finish creating the image. image_ready->Wait(); + DCHECK(*image); + // Animate the image node by setting its image to the newly created image. image_node->source = *image; @@ -75,35 +116,9 @@ // animation callback. animate_has_started_->Wait(); - // Initialize the image data and store a predictable, testable pattern - // of image data into it. - math::Size image_size(16, 16); + *image_ = CreateDummyImage(resource_provider_); - int rgba_mapping[4] = {0, 1, 2, 3}; - render_tree::PixelFormat pixel_format = render_tree::kPixelFormatInvalid; - if (resource_provider_->PixelFormatSupported( - render_tree::kPixelFormatRGBA8)) { - pixel_format = render_tree::kPixelFormatRGBA8; - } else if (resource_provider_->PixelFormatSupported( - render_tree::kPixelFormatBGRA8)) { - pixel_format = render_tree::kPixelFormatBGRA8; - rgba_mapping[0] = 2; - rgba_mapping[2] = 0; - } else { - NOTREACHED() << "Unsupported pixel format."; - } - - scoped_ptr<render_tree::ImageData> image_data = - resource_provider_->AllocateImageData( - image_size, pixel_format, render_tree::kAlphaFormatPremultiplied); - for (int i = 0; i < image_size.width() * image_size.height(); ++i) { - image_data->GetMemory()[i * 4 + rgba_mapping[0]] = 1; - image_data->GetMemory()[i * 4 + rgba_mapping[1]] = 2; - image_data->GetMemory()[i * 4 + rgba_mapping[2]] = 3; - image_data->GetMemory()[i * 4 + rgba_mapping[3]] = 255; - } - // Create the new image. - *image_ = resource_provider_->CreateImage(image_data.Pass()); + DCHECK(*image_); // Signal to the animation callback that it can now reference the newly // created image. @@ -139,7 +154,8 @@ scoped_refptr<backend::RenderTarget> dummy_output_surface = graphics_context->CreateOffscreenRenderTarget(kDummySurfaceDimensions); - { + const int kNumTestTrials = 5; + for (int i = 0; i < kNumTestTrials; ++i) { // Setup some synchronization objects so we can ensure the image is created // while the animation callback is being executed, and also that the image // is referenced only after it is created. It is important that these @@ -153,19 +169,21 @@ RendererModule::Options render_module_options; Pipeline pipeline( base::Bind(render_module_options.create_rasterizer_function, - graphics_context.get()), + graphics_context.get(), render_module_options), dummy_output_surface, NULL); // Our test render tree will consist of only a single ImageNode. - scoped_refptr<ImageNode> test_node = - new ImageNode(scoped_refptr<Image>(), math::RectF(1.0f, 1.0f)); + scoped_refptr<ImageNode> test_node = new ImageNode( + scoped_refptr<Image>(CreateDummyImage(pipeline.GetResourceProvider())), + math::RectF(1.0f, 1.0f)); // Animate the ImageNode and pass in our callback function to be executed // upon render_tree animation. NodeAnimationsMap::Builder animations; + bool first_animate = true; animations.Add(test_node, base::Bind(&AnimateImageNode, &animate_has_started, - &image_ready, &image)); + &image_ready, &image, &first_animate)); // Setup a separate thread to be responsible for creating the image, so that // we can guarantee that this operation will occur on a separate thread.
diff --git a/src/cobalt/renderer/backend/egl/utils.cc b/src/cobalt/renderer/backend/egl/utils.cc index b8ee608..c72f73e 100644 --- a/src/cobalt/renderer/backend/egl/utils.cc +++ b/src/cobalt/renderer/backend/egl/utils.cc
@@ -54,6 +54,8 @@ case GL_RGBA: case GL_BGRA_EXT: return 4; + case GL_LUMINANCE_ALPHA: + return 2; case GL_ALPHA: return 1; default:
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_nv12.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_nv12.glsl new file mode 100644 index 0000000..6fcae22 --- /dev/null +++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_nv12.glsl
@@ -0,0 +1,18 @@ +#version 100 +precision mediump float; +uniform sampler2D uSampler0_Stage0; +uniform sampler2D uSampler1_Stage0; +uniform mat4 uYUVMatrix_Stage0; +varying vec2 vMatrixCoord_Stage0; + +void main() { + vec4 output_Stage0; + { + // Stage 0: YUV to RGB + output_Stage0 = vec4( + texture2D(uSampler0_Stage0, vMatrixCoord_Stage0).aaaa.r, + texture2D(uSampler1_Stage0, vMatrixCoord_Stage0).ba, + 1.0) * uYUVMatrix_Stage0; + } + gl_FragColor = output_Stage0; +}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/shaders.gypi b/src/cobalt/renderer/glimp_shaders/glsl/shaders.gypi index 843878c..b0e8820 100644 --- a/src/cobalt/renderer/glimp_shaders/glsl/shaders.gypi +++ b/src/cobalt/renderer/glimp_shaders/glsl/shaders.gypi
@@ -45,6 +45,7 @@ 'fragment_skia_linear_gradient_many_colors.glsl', 'fragment_skia_linear_gradient_three_colors.glsl', 'fragment_skia_linear_gradient_two_colors.glsl', + 'fragment_skia_nv12.glsl', 'fragment_skia_radial_gradient_many_colors.glsl', 'fragment_skia_radial_gradient_three_colors.glsl', 'fragment_skia_radial_gradient_two_colors.glsl',
diff --git a/src/cobalt/renderer/rasterizer/benchmark.cc b/src/cobalt/renderer/rasterizer/benchmark.cc index ffc3fe8..aefb362 100644 --- a/src/cobalt/renderer/rasterizer/benchmark.cc +++ b/src/cobalt/renderer/rasterizer/benchmark.cc
@@ -50,7 +50,8 @@ scoped_ptr<Rasterizer> CreateDefaultRasterizer( GraphicsContext* graphics_context) { RendererModule::Options render_module_options; - return render_module_options.create_rasterizer_function.Run(graphics_context); + return render_module_options.create_rasterizer_function.Run( + graphics_context, render_module_options); } // Allow test writers to choose whether the rasterizer results should be drawn
diff --git a/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc b/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc index e2102eb..2f73a29 100644 --- a/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc +++ b/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc
@@ -52,7 +52,7 @@ backend::GraphicsContextBlitter* context_; - skia::SkiaSoftwareRasterizer software_rasterizer_; + skia::SoftwareRasterizer software_rasterizer_; scoped_ptr<render_tree::ResourceProvider> resource_provider_; int64 submit_count_;
diff --git a/src/cobalt/renderer/rasterizer/blitter/image.h b/src/cobalt/renderer/rasterizer/blitter/image.h index 4a2b1ec..7275225 100644 --- a/src/cobalt/renderer/rasterizer/blitter/image.h +++ b/src/cobalt/renderer/rasterizer/blitter/image.h
@@ -64,11 +64,11 @@ // render_tree::Image objects are implemented in the Blitter API via // SbBlitterSurface objects, which are conceptually an exact match for Image. -// We derive from skia::SkiaSinglePlaneImage here because it is possible for +// We derive from skia::SinglePlaneImage here because it is possible for // render tree nodes referencing blitter:Images to be passed into a Skia // software renderer. Thus, SinglePlaneImage is implemented such // that Skia render tree node visitors can also render it. -class SinglePlaneImage : public skia::SkiaSinglePlaneImage { +class SinglePlaneImage : public skia::SinglePlaneImage { public: explicit SinglePlaneImage(scoped_ptr<ImageData> image_data); @@ -76,7 +76,7 @@ SbBlitterSurface surface() const { return surface_; } - // Overrides from skia::SkiaSinglePlaneImage. + // Overrides from skia::SinglePlaneImage. void EnsureInitialized() OVERRIDE; // When GetBitmap() is called on a blitter::SinglePlaneImage for the first
diff --git a/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc b/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc index 1888a53..9af227b 100644 --- a/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc +++ b/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc
@@ -53,7 +53,7 @@ RenderTreeNodeVisitor::RenderTreeNodeVisitor( SbBlitterDevice device, SbBlitterContext context, const RenderState& render_state, - skia::SkiaSoftwareRasterizer* software_rasterizer, + skia::SoftwareRasterizer* software_rasterizer, SurfaceCacheDelegate* surface_cache_delegate, common::SurfaceCache* surface_cache) : software_rasterizer_(software_rasterizer), @@ -167,14 +167,14 @@ } void RenderTreeNodeVisitor::Visit(render_tree::ImageNode* image_node) { - // All Blitter API images derive from SkiaImage (so that they can be + // All Blitter API images derive from skia::Image (so that they can be // compatible with the Skia software renderer), so we start here by casting - // to SkiaImage. - skia::SkiaImage* skia_image = base::polymorphic_downcast<skia::SkiaImage*>( - image_node->data().source.get()); + // to skia::Image. + skia::Image* skia_image = + base::polymorphic_downcast<skia::Image*>(image_node->data().source.get()); const Size& image_size = skia_image->GetSize(); - if (skia_image->GetTypeId() == base::GetTypeId<skia::SkiaMultiPlaneImage>()) { + if (skia_image->GetTypeId() == base::GetTypeId<skia::MultiPlaneImage>()) { // Let software Skia deal with multiplane (e.g. YUV) image rendering. RenderWithSoftwareRenderer(image_node); return;
diff --git a/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.h b/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.h index 16d774b..3370321 100644 --- a/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.h +++ b/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.h
@@ -54,7 +54,7 @@ public: RenderTreeNodeVisitor(SbBlitterDevice device, SbBlitterContext context, const RenderState& render_state, - skia::SkiaSoftwareRasterizer* software_rasterizer, + skia::SoftwareRasterizer* software_rasterizer, SurfaceCacheDelegate* surface_cache_delegate, common::SurfaceCache* surface_cache); @@ -89,7 +89,7 @@ // We maintain an instance of a software skia rasterizer which is used to // render anything that we cannot render via the Blitter API directly. - skia::SkiaSoftwareRasterizer* software_rasterizer_; + skia::SoftwareRasterizer* software_rasterizer_; SbBlitterDevice device_; SbBlitterContext context_;
diff --git a/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.h b/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.h index 874160f..4743332 100644 --- a/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.h +++ b/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.h
@@ -50,7 +50,7 @@ private: backend::GraphicsContextBlitter* context_; - skia::SkiaSoftwareRasterizer skia_rasterizer_; + skia::SoftwareRasterizer skia_rasterizer_; }; } // namespace blitter
diff --git a/src/cobalt/renderer/rasterizer/egl/software_rasterizer.h b/src/cobalt/renderer/rasterizer/egl/software_rasterizer.h index 9330b45..662353c 100644 --- a/src/cobalt/renderer/rasterizer/egl/software_rasterizer.h +++ b/src/cobalt/renderer/rasterizer/egl/software_rasterizer.h
@@ -50,7 +50,7 @@ private: backend::GraphicsContextEGL* context_; - skia::SkiaSoftwareRasterizer skia_rasterizer_; + skia::SoftwareRasterizer skia_rasterizer_; }; } // namespace egl
diff --git a/src/cobalt/renderer/rasterizer/pixel_test.cc b/src/cobalt/renderer/rasterizer/pixel_test.cc index d87d57a..5fde5c2 100644 --- a/src/cobalt/renderer/rasterizer/pixel_test.cc +++ b/src/cobalt/renderer/rasterizer/pixel_test.cc
@@ -43,6 +43,7 @@ #include "testing/gtest/include/gtest/gtest.h" #define BILINEAR_FILTERING_SUPPORTED 1 +#define NV12_TEXTURE_SUPPORTED 1 #if defined(STARBOARD) #if !SB_HAS(BILINEAR_FILTERING_SUPPORT) @@ -51,6 +52,13 @@ #endif #endif +#if defined(STARBOARD) +#if !SB_HAS(NV12_TEXTURE_SUPPORT) +#undef NV12_TEXTURE_SUPPORTED +#define NV12_TEXTURE_SUPPORTED 0 +#endif +#endif + using cobalt::math::Matrix3F; using cobalt::math::PointF; using cobalt::math::RectF; @@ -374,6 +382,7 @@ case render_tree::kPixelFormatY8: case render_tree::kPixelFormatU8: case render_tree::kPixelFormatV8: + case render_tree::kPixelFormatUV8: case render_tree::kPixelFormatInvalid: { NOTREACHED() << "Invalid pixel format."; } @@ -895,6 +904,74 @@ return resource_provider->CreateMultiPlaneImageFromRawMemory( image_memory.Pass(), image_data_descriptor); } + +// The software rasterizer does not support NV12 images. +#if NV12_TEXTURE_SUPPORTED + +// Creates a two plane YUV image where the Y channel is stored as a +// single-channel image plane and the U and V channels are interleaved in a +// second image plane. The NV12 format dictates that the UV plane has the same +// number of columns and half the rows of the Y plane. +scoped_refptr<Image> MakeNV12Image(ResourceProvider* resource_provider, + const Size& image_size) { + // The alpha format doesn't really matter here, but we still need to pick one + // that the resource provider indicates it supports. + render_tree::AlphaFormat alpha_format = + render_tree::kAlphaFormatUnpremultiplied; + if (!resource_provider->AlphaFormatSupported(alpha_format)) { + alpha_format = render_tree::kAlphaFormatPremultiplied; + } + CHECK(resource_provider->AlphaFormatSupported(alpha_format)); + + static const int kMaxBytesUsed = + image_size.width() * image_size.height() * 3 / 2; + + scoped_ptr<RawImageMemory> image_memory = + resource_provider->AllocateRawImageMemory(kMaxBytesUsed, 256); + + // Setup information about the Y plane. + ImageDataDescriptor y_plane_descriptor(image_size, + render_tree::kPixelFormatY8, + alpha_format, image_size.width()); + intptr_t y_plane_memory_offset = 0; + uint8_t* y_plane_memory = image_memory->GetMemory() + y_plane_memory_offset; + float y_plane_inverse_height = 1.0f / y_plane_descriptor.size.height(); + for (int r = 0; r < y_plane_descriptor.size.height(); ++r) { + for (int c = 0; c < y_plane_descriptor.size.width(); ++c) { + y_plane_memory[c] = + static_cast<uint8_t>(255.0f * r * y_plane_inverse_height); + } + y_plane_memory += y_plane_descriptor.pitch_in_bytes; + } + + // Setup information about the UV plane. + ImageDataDescriptor uv_plane_descriptor( + Size(image_size.width() / 2, image_size.height() / 2), + render_tree::kPixelFormatUV8, alpha_format, image_size.width()); + intptr_t uv_plane_memory_offset = + y_plane_memory_offset + + y_plane_descriptor.pitch_in_bytes * y_plane_descriptor.size.height(); + uint8_t* uv_plane_memory = image_memory->GetMemory() + uv_plane_memory_offset; + float uv_plane_inverse_width = 1.0f / uv_plane_descriptor.size.width(); + for (int r = 0; r < uv_plane_descriptor.size.height(); ++r) { + for (int c = 0; c < uv_plane_descriptor.size.width(); ++c) { + uv_plane_memory[2 * c] = + static_cast<uint8_t>(255.0f * c * uv_plane_inverse_width); + uv_plane_memory[2 * c + 1] = + 255 - static_cast<uint8_t>(255.0f * c * uv_plane_inverse_width); + } + uv_plane_memory += uv_plane_descriptor.pitch_in_bytes; + } + + MultiPlaneImageDataDescriptor image_data_descriptor( + render_tree::kMultiPlaneImageFormatYUV2PlaneBT709); + image_data_descriptor.AddPlane(y_plane_memory_offset, y_plane_descriptor); + image_data_descriptor.AddPlane(uv_plane_memory_offset, uv_plane_descriptor); + + return resource_provider->CreateMultiPlaneImageFromRawMemory( + image_memory.Pass(), image_data_descriptor); +} +#endif // #if NV12_TEXTURE_SUPPORTED } // namespace TEST_F(PixelTest, ThreePlaneYUVImageSupport) { @@ -924,6 +1001,37 @@ -half_output_size.height()))); } +// The software rasterizer does not support NV12 images. +#if NV12_TEXTURE_SUPPORTED + +TEST_F(PixelTest, TwoPlaneYUVImageSupport) { + // Tests that an ImageNode hooked up to a 3-plane YUV image works fine. + scoped_refptr<Image> image = + MakeNV12Image(GetResourceProvider(), output_surface_size()); + + TestTree(new ImageNode(image)); +} + +TEST_F(PixelTest, TwoPlaneYUVImageWithDestSizeDifferentFromImage) { + // Tests that an ImageNode hooked up to a 3-plane YUV image works fine. + scoped_refptr<Image> image = + MakeNV12Image(GetResourceProvider(), output_surface_size()); + + TestTree(new ImageNode(image, RectF(100.0f, 100.0f))); +} + +TEST_F(PixelTest, TwoPlaneYUVImageWithTransform) { + SizeF half_output_size = ScaleSize(output_surface_size(), 0.5f, 0.5f); + TestTree(new MatrixTransformNode( + new ImageNode( + MakeNV12Image(GetResourceProvider(), output_surface_size())), + TranslateMatrix(half_output_size.width(), half_output_size.height()) * + ScaleMatrix(0.5f) * RotateMatrix(static_cast<float>(M_PI) / 4) * + TranslateMatrix(-half_output_size.width(), + -half_output_size.height()))); +} +#endif // #if NV12_TEXTURE_SUPPORTED + TEST_F(PixelTest, ImageNodeLocalTransformRotationAndScale) { scoped_refptr<Image> image = CreateColoredCheckersImage(GetResourceProvider(), output_surface_size()); @@ -1386,13 +1494,25 @@ #endif // BILINEAR_FILTERING_SUPPORTED -TEST_F(PixelTest, YUVImagesAreLinearlyInterpolated) { - // Tests that YUV images are bilinearly interpolated. +TEST_F(PixelTest, YUV3PlaneImagesAreLinearlyInterpolated) { + // Tests that three plane YUV images are bilinearly interpolated. scoped_refptr<Image> image = MakeI420Image(GetResourceProvider(), Size(8, 8)); TestTree(new ImageNode(image, RectF(output_surface_size()))); } +// The software rasterizer does not support NV12 images. +#if NV12_TEXTURE_SUPPORTED + +TEST_F(PixelTest, YUV2PlaneImagesAreLinearlyInterpolated) { + // Tests that two plane YUV images are bilinearly interpolated. + scoped_refptr<Image> image = MakeNV12Image(GetResourceProvider(), Size(8, 8)); + + TestTree(new ImageNode(image, RectF(output_surface_size()))); +} + +#endif // #if NV12_TEXTURE_SUPPORTED + TEST_F(PixelTest, VeryLargeOpacityFilterDoesNotOccupyVeryMuchMemory) { // This test ensures that an opacity filter being applied to an extremely // large surface works just fine. This test is itneresting because opacity
diff --git a/src/cobalt/renderer/rasterizer/skia/cobalt_skia_type_conversions.cc b/src/cobalt/renderer/rasterizer/skia/cobalt_skia_type_conversions.cc index 39c12c7..1ca29c1 100644 --- a/src/cobalt/renderer/rasterizer/skia/cobalt_skia_type_conversions.cc +++ b/src/cobalt/renderer/rasterizer/skia/cobalt_skia_type_conversions.cc
@@ -34,6 +34,8 @@ return kAlpha_8_SkColorType; case render_tree::kPixelFormatV8: return kAlpha_8_SkColorType; + case render_tree::kPixelFormatUV8: + return kRGBA_8888_SkColorType; default: DLOG(FATAL) << "Unknown render tree pixel format!"; return kUnknown_SkColorType;
diff --git a/src/cobalt/renderer/rasterizer/skia/font.cc b/src/cobalt/renderer/rasterizer/skia/font.cc index 3e54684..06bbb20 100644 --- a/src/cobalt/renderer/rasterizer/skia/font.cc +++ b/src/cobalt/renderer/rasterizer/skia/font.cc
@@ -49,20 +49,18 @@ } // namespace -SkiaFont::SkiaFont(SkiaTypeface* typeface, SkScalar size) +Font::Font(SkiaTypeface* typeface, SkScalar size) : typeface_(typeface), size_(size) { glyph_bounds_thread_checker_.DetachFromThread(); } -SkTypeface* SkiaFont::GetSkTypeface() const { - return typeface_->GetSkTypeface(); -} +SkTypeface* Font::GetSkTypeface() const { return typeface_->GetSkTypeface(); } -render_tree::TypefaceId SkiaFont::GetTypefaceId() const { +render_tree::TypefaceId Font::GetTypefaceId() const { return typeface_->GetId(); } -render_tree::FontMetrics SkiaFont::GetFontMetrics() const { +render_tree::FontMetrics Font::GetFontMetrics() const { SkPaint paint = GetSkPaint(); SkPaint::FontMetrics font_metrics; @@ -85,11 +83,11 @@ font_metrics.fLeading, x_height); } -render_tree::GlyphIndex SkiaFont::GetGlyphForCharacter(int32 utf32_character) { +render_tree::GlyphIndex Font::GetGlyphForCharacter(int32 utf32_character) { return typeface_->GetGlyphForCharacter(utf32_character); } -const math::RectF& SkiaFont::GetGlyphBounds(render_tree::GlyphIndex glyph) { +const math::RectF& Font::GetGlyphBounds(render_tree::GlyphIndex glyph) { DCHECK(glyph_bounds_thread_checker_.CalledOnValidThread()); // Check to see if the glyph falls within the the first 256 glyphs. These // characters are part of the primary page and are stored within an array as @@ -132,11 +130,11 @@ } } -float SkiaFont::GetGlyphWidth(render_tree::GlyphIndex glyph) { +float Font::GetGlyphWidth(render_tree::GlyphIndex glyph) { return GetGlyphBounds(glyph).width(); } -SkPaint SkiaFont::GetSkPaint() const { +SkPaint Font::GetSkPaint() const { SkPaint paint(GetDefaultSkPaint()); SkAutoTUnref<SkTypeface> typeface(typeface_->GetSkTypeface()); paint.setTypeface(typeface); @@ -144,7 +142,7 @@ return paint; } -const SkPaint& SkiaFont::GetDefaultSkPaint() { +const SkPaint& Font::GetDefaultSkPaint() { return non_trivial_static_fields.Get().default_paint; }
diff --git a/src/cobalt/renderer/rasterizer/skia/font.h b/src/cobalt/renderer/rasterizer/skia/font.h index d6e181c..d0e9ea5 100644 --- a/src/cobalt/renderer/rasterizer/skia/font.h +++ b/src/cobalt/renderer/rasterizer/skia/font.h
@@ -39,9 +39,9 @@ // NOTE: Glyph queries are not thread-safe and should only occur from a single // thread. However, the font can be created on a different thread than the // thread making the glyph queries. -class SkiaFont : public render_tree::Font { +class Font : public render_tree::Font { public: - SkiaFont(SkiaTypeface* typeface, SkScalar size); + Font(SkiaTypeface* typeface, SkScalar size); SkTypeface* GetSkTypeface() const;
diff --git a/src/cobalt/renderer/rasterizer/skia/gl_format_conversions.cc b/src/cobalt/renderer/rasterizer/skia/gl_format_conversions.cc index 70bbd7a..02e1ed8 100644 --- a/src/cobalt/renderer/rasterizer/skia/gl_format_conversions.cc +++ b/src/cobalt/renderer/rasterizer/skia/gl_format_conversions.cc
@@ -36,6 +36,8 @@ return GL_ALPHA; case render_tree::kPixelFormatV8: return GL_ALPHA; + case render_tree::kPixelFormatUV8: + return GL_LUMINANCE_ALPHA; default: { NOTREACHED() << "Unknown format."; } } return GL_RGBA; @@ -49,6 +51,8 @@ return kBGRA_8888_GrPixelConfig; case GL_ALPHA: return kAlpha_8_GrPixelConfig; + case GL_LUMINANCE_ALPHA: + return kRGBA_8888_GrPixelConfig; default: { NOTREACHED() << "Unsupported GL format."; } } return kRGBA_8888_GrPixelConfig;
diff --git a/src/cobalt/renderer/rasterizer/skia/glyph_buffer.cc b/src/cobalt/renderer/rasterizer/skia/glyph_buffer.cc index acbd7a5..a9fc8a1 100644 --- a/src/cobalt/renderer/rasterizer/skia/glyph_buffer.cc +++ b/src/cobalt/renderer/rasterizer/skia/glyph_buffer.cc
@@ -21,11 +21,10 @@ namespace rasterizer { namespace skia { -SkiaGlyphBuffer::SkiaGlyphBuffer(const math::RectF& bounds, - SkTextBlobBuilder* builder) +GlyphBuffer::GlyphBuffer(const math::RectF& bounds, SkTextBlobBuilder* builder) : render_tree::GlyphBuffer(bounds), text_blob_(builder->build()) {} -const SkTextBlob* SkiaGlyphBuffer::GetTextBlob() const { +const SkTextBlob* GlyphBuffer::GetTextBlob() const { return SkSafeRef(text_blob_.get()); }
diff --git a/src/cobalt/renderer/rasterizer/skia/glyph_buffer.h b/src/cobalt/renderer/rasterizer/skia/glyph_buffer.h index b1a39a2..ca1f86d 100644 --- a/src/cobalt/renderer/rasterizer/skia/glyph_buffer.h +++ b/src/cobalt/renderer/rasterizer/skia/glyph_buffer.h
@@ -29,9 +29,9 @@ // Describes a render_tree::GlyphBuffer using Skia. This object contain all of // the information needed by Skia to render glyphs and is both immutable and // thread-safe. -class SkiaGlyphBuffer : public render_tree::GlyphBuffer { +class GlyphBuffer : public render_tree::GlyphBuffer { public: - SkiaGlyphBuffer(const math::RectF& bounds, SkTextBlobBuilder* builder); + GlyphBuffer(const math::RectF& bounds, SkTextBlobBuilder* builder); const SkTextBlob* GetTextBlob() const;
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_image.cc b/src/cobalt/renderer/rasterizer/skia/hardware_image.cc index f45500a..f8096b0 100644 --- a/src/cobalt/renderer/rasterizer/skia/hardware_image.cc +++ b/src/cobalt/renderer/rasterizer/skia/hardware_image.cc
@@ -46,7 +46,7 @@ return gr_context->wrapBackendTexture(desc); } -SkiaHardwareImageData::SkiaHardwareImageData( +HardwareImageData::HardwareImageData( scoped_ptr<backend::TextureDataEGL> texture_data, render_tree::PixelFormat pixel_format, render_tree::AlphaFormat alpha_format) @@ -54,33 +54,31 @@ descriptor_(texture_data_->GetSize(), pixel_format, alpha_format, texture_data_->GetPitchInBytes()) {} -const render_tree::ImageDataDescriptor& SkiaHardwareImageData::GetDescriptor() +const render_tree::ImageDataDescriptor& HardwareImageData::GetDescriptor() const { return descriptor_; } -uint8_t* SkiaHardwareImageData::GetMemory() { - return texture_data_->GetMemory(); -} +uint8_t* HardwareImageData::GetMemory() { return texture_data_->GetMemory(); } -scoped_ptr<backend::TextureDataEGL> SkiaHardwareImageData::PassTextureData() { +scoped_ptr<backend::TextureDataEGL> HardwareImageData::PassTextureData() { return texture_data_.Pass(); } -SkiaHardwareRawImageMemory::SkiaHardwareRawImageMemory( +HardwareRawImageMemory::HardwareRawImageMemory( scoped_ptr<backend::RawTextureMemoryEGL> raw_texture_memory) : raw_texture_memory_(raw_texture_memory.Pass()) {} -size_t SkiaHardwareRawImageMemory::GetSizeInBytes() const { +size_t HardwareRawImageMemory::GetSizeInBytes() const { return raw_texture_memory_->GetSizeInBytes(); } -uint8_t* SkiaHardwareRawImageMemory::GetMemory() { +uint8_t* HardwareRawImageMemory::GetMemory() { return raw_texture_memory_->GetMemory(); } scoped_ptr<backend::RawTextureMemoryEGL> -SkiaHardwareRawImageMemory::PassRawTextureMemory() { +HardwareRawImageMemory::PassRawTextureMemory() { return raw_texture_memory_.Pass(); } @@ -88,26 +86,27 @@ // GetBitmap(), overridden from SkiaImage, will return a reference to a SkBitmap // object that refers to the image's GrTexture. This object should only be // constructed, destructed and used from the same rasterizer thread. -class SkiaHardwareFrontendImage::SkiaHardwareBackendImage { +class HardwareFrontendImage::HardwareBackendImage { public: - SkiaHardwareBackendImage(scoped_ptr<SkiaHardwareImageData> image_data, - backend::GraphicsContextEGL* cobalt_context, - GrContext* gr_context) { + HardwareBackendImage(scoped_ptr<HardwareImageData> image_data, + backend::GraphicsContextEGL* cobalt_context, + GrContext* gr_context) { TRACE_EVENT0("cobalt::renderer", - "SkiaHardwareBackendImage::SkiaHardwareBackendImage()"); + "HardwareBackendImage::HardwareBackendImage()"); scoped_ptr<backend::TextureEGL> texture = cobalt_context->CreateTexture(image_data->PassTextureData()); CommonInitialize(texture.Pass(), gr_context); } - SkiaHardwareBackendImage( - const scoped_refptr<backend::ConstRawTextureMemoryEGL>& - raw_texture_memory, - intptr_t offset, const render_tree::ImageDataDescriptor& descriptor, - backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context) { + HardwareBackendImage(const scoped_refptr<backend::ConstRawTextureMemoryEGL>& + raw_texture_memory, + intptr_t offset, + const render_tree::ImageDataDescriptor& descriptor, + backend::GraphicsContextEGL* cobalt_context, + GrContext* gr_context) { TRACE_EVENT0("cobalt::renderer", - "SkiaHardwareBackendImage::SkiaHardwareBackendImage()"); + "HardwareBackendImage::HardwareBackendImage()"); scoped_ptr<backend::TextureEGL> texture = cobalt_context->CreateTextureFromRawMemory( raw_texture_memory, offset, descriptor.size, @@ -117,9 +116,9 @@ CommonInitialize(texture.Pass(), gr_context); } - ~SkiaHardwareBackendImage() { + ~HardwareBackendImage() { TRACE_EVENT0("cobalt::renderer", - "SkiaHardwareBackendImage::~SkiaHardwareBackendImage()"); + "HardwareBackendImage::~HardwareBackendImage()"); // This object should always be destroyed from the thread that it was // constructed on. DCHECK(thread_checker_.CalledOnValidThread()); @@ -131,11 +130,12 @@ GrContext* gr_context) { DCHECK(thread_checker_.CalledOnValidThread()); TRACE_EVENT0("cobalt::renderer", - "SkiaHardwareBackendImage::CommonInitialize()"); + "HardwareBackendImage::CommonInitialize()"); texture_ = texture.Pass(); gr_texture_.reset( WrapCobaltTextureWithSkiaTexture(gr_context, texture_.get())); + DCHECK(gr_texture_); // Prepare a member SkBitmap that refers to the newly created GrTexture and // will be the object that Skia draw calls will reference when referring @@ -160,22 +160,22 @@ SkBitmap bitmap_; }; -SkiaHardwareFrontendImage::SkiaHardwareFrontendImage( - scoped_ptr<SkiaHardwareImageData> image_data, +HardwareFrontendImage::HardwareFrontendImage( + scoped_ptr<HardwareImageData> image_data, backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context, MessageLoop* rasterizer_message_loop) : size_(image_data->GetDescriptor().size), rasterizer_message_loop_(rasterizer_message_loop) { TRACE_EVENT0("cobalt::renderer", - "SkiaHardwareFrontendImage::SkiaHardwareFrontendImage()"); + "HardwareFrontendImage::HardwareFrontendImage()"); - initialize_backend_image_ = base::Bind( - &SkiaHardwareFrontendImage::InitializeBackendImageFromImageData, - base::Unretained(this), base::Passed(&image_data), cobalt_context, - gr_context); + initialize_backend_image_ = + base::Bind(&HardwareFrontendImage::InitializeBackendImageFromImageData, + base::Unretained(this), base::Passed(&image_data), + cobalt_context, gr_context); } -SkiaHardwareFrontendImage::SkiaHardwareFrontendImage( +HardwareFrontendImage::HardwareFrontendImage( const scoped_refptr<backend::ConstRawTextureMemoryEGL>& raw_texture_memory, intptr_t offset, const render_tree::ImageDataDescriptor& descriptor, backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context, @@ -183,16 +183,16 @@ : size_(descriptor.size), rasterizer_message_loop_(rasterizer_message_loop) { TRACE_EVENT0("cobalt::renderer", - "SkiaHardwareFrontendImage::SkiaHardwareFrontendImage()"); - initialize_backend_image_ = base::Bind( - &SkiaHardwareFrontendImage::InitializeBackendImageFromRawImageData, - base::Unretained(this), raw_texture_memory, offset, descriptor, - cobalt_context, gr_context); + "HardwareFrontendImage::HardwareFrontendImage()"); + initialize_backend_image_ = + base::Bind(&HardwareFrontendImage::InitializeBackendImageFromRawImageData, + base::Unretained(this), raw_texture_memory, offset, descriptor, + cobalt_context, gr_context); } -SkiaHardwareFrontendImage::~SkiaHardwareFrontendImage() { +HardwareFrontendImage::~HardwareFrontendImage() { TRACE_EVENT0("cobalt::renderer", - "SkiaHardwareFrontendImage::~SkiaHardwareFrontendImage()"); + "HardwareFrontendImage::~HardwareFrontendImage()"); // If we are destroying this image from a non-rasterizer thread, we still must // ensure that the |backend_image_| is destroyed from the rasterizer thread, // if |backend_image_| was ever constructed in the first place. @@ -202,7 +202,7 @@ } // else let the scoped pointer clean it up immediately. } -const SkBitmap& SkiaHardwareFrontendImage::GetBitmap() const { +const SkBitmap& HardwareFrontendImage::GetBitmap() const { DCHECK_EQ(rasterizer_message_loop_, MessageLoop::current()); // Forward this call to the backend image. This method must be called from // the rasterizer thread (e.g. during a render tree visitation). The backend @@ -210,7 +210,7 @@ return backend_image_->GetBitmap(); } -void SkiaHardwareFrontendImage::EnsureInitialized() { +void HardwareFrontendImage::EnsureInitialized() { DCHECK_EQ(rasterizer_message_loop_, MessageLoop::current()); if (!initialize_backend_image_.is_null()) { initialize_backend_image_.Run(); @@ -218,25 +218,25 @@ } } -void SkiaHardwareFrontendImage::InitializeBackendImageFromImageData( - scoped_ptr<SkiaHardwareImageData> image_data, +void HardwareFrontendImage::InitializeBackendImageFromImageData( + scoped_ptr<HardwareImageData> image_data, backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context) { DCHECK_EQ(rasterizer_message_loop_, MessageLoop::current()); - backend_image_.reset(new SkiaHardwareBackendImage( - image_data.Pass(), cobalt_context, gr_context)); + backend_image_.reset( + new HardwareBackendImage(image_data.Pass(), cobalt_context, gr_context)); } -void SkiaHardwareFrontendImage::InitializeBackendImageFromRawImageData( +void HardwareFrontendImage::InitializeBackendImageFromRawImageData( const scoped_refptr<backend::ConstRawTextureMemoryEGL>& raw_texture_memory, intptr_t offset, const render_tree::ImageDataDescriptor& descriptor, backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context) { DCHECK_EQ(rasterizer_message_loop_, MessageLoop::current()); - backend_image_.reset(new SkiaHardwareBackendImage( + backend_image_.reset(new HardwareBackendImage( raw_texture_memory, offset, descriptor, cobalt_context, gr_context)); } -SkiaHardwareMultiPlaneImage::SkiaHardwareMultiPlaneImage( - scoped_ptr<SkiaHardwareRawImageMemory> raw_image_memory, +HardwareMultiPlaneImage::HardwareMultiPlaneImage( + scoped_ptr<HardwareRawImageMemory> raw_image_memory, const render_tree::MultiPlaneImageDataDescriptor& descriptor, backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context, MessageLoop* rasterizer_message_loop) @@ -248,16 +248,16 @@ // Construct a single plane image for each plane of this multi plane image. for (int i = 0; i < descriptor.num_planes(); ++i) { - planes_[i] = new SkiaHardwareFrontendImage( + planes_[i] = new HardwareFrontendImage( const_raw_texture_memory, descriptor.GetPlaneOffset(i), descriptor.GetPlaneDescriptor(i), cobalt_context, gr_context, rasterizer_message_loop); } } -SkiaHardwareMultiPlaneImage::~SkiaHardwareMultiPlaneImage() {} +HardwareMultiPlaneImage::~HardwareMultiPlaneImage() {} -void SkiaHardwareMultiPlaneImage::EnsureInitialized() { +void HardwareMultiPlaneImage::EnsureInitialized() { // A multi-plane image is not considered backend-initialized until all its // single-plane images are backend-initialized, thus we ensure that all // the component images are backend-initialized.
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_image.h b/src/cobalt/renderer/rasterizer/skia/hardware_image.h index d222471..15c318e 100644 --- a/src/cobalt/renderer/rasterizer/skia/hardware_image.h +++ b/src/cobalt/renderer/rasterizer/skia/hardware_image.h
@@ -40,11 +40,11 @@ GrContext* gr_context, scoped_ptr<backend::TextureEGL> cobalt_texture); // Forwards ImageData methods on to TextureData methods. -class SkiaHardwareImageData : public render_tree::ImageData { +class HardwareImageData : public render_tree::ImageData { public: - SkiaHardwareImageData(scoped_ptr<backend::TextureDataEGL> texture_data, - render_tree::PixelFormat pixel_format, - render_tree::AlphaFormat alpha_format); + HardwareImageData(scoped_ptr<backend::TextureDataEGL> texture_data, + render_tree::PixelFormat pixel_format, + render_tree::AlphaFormat alpha_format); const render_tree::ImageDataDescriptor& GetDescriptor() const OVERRIDE; uint8_t* GetMemory() OVERRIDE; @@ -56,9 +56,9 @@ render_tree::ImageDataDescriptor descriptor_; }; -class SkiaHardwareRawImageMemory : public render_tree::RawImageMemory { +class HardwareRawImageMemory : public render_tree::RawImageMemory { public: - SkiaHardwareRawImageMemory( + HardwareRawImageMemory( scoped_ptr<backend::RawTextureMemoryEGL> raw_texture_memory); size_t GetSizeInBytes() const OVERRIDE; @@ -74,27 +74,28 @@ // constructed, it also sends a message to the rasterizer's thread to have // a corresponding backend image object constructed with the actual image data. // The frontend image is what is actually returned from a call to -// SkiaHardwareResourceProvider::CreateImage(), but the backend object is what +// HardwareResourceProvider::CreateImage(), but the backend object is what // actually contains the texture data. -class SkiaHardwareFrontendImage : public SkiaSinglePlaneImage { +class HardwareFrontendImage : public SinglePlaneImage { public: - SkiaHardwareFrontendImage(scoped_ptr<SkiaHardwareImageData> image_data, - backend::GraphicsContextEGL* cobalt_context, - GrContext* gr_context, - MessageLoop* rasterizer_message_loop); - SkiaHardwareFrontendImage( - const scoped_refptr<backend::ConstRawTextureMemoryEGL>& - raw_texture_memory, - intptr_t offset, const render_tree::ImageDataDescriptor& descriptor, - backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context, - MessageLoop* rasterizer_message_loop); + HardwareFrontendImage(scoped_ptr<HardwareImageData> image_data, + backend::GraphicsContextEGL* cobalt_context, + GrContext* gr_context, + MessageLoop* rasterizer_message_loop); + HardwareFrontendImage(const scoped_refptr<backend::ConstRawTextureMemoryEGL>& + raw_texture_memory, + intptr_t offset, + const render_tree::ImageDataDescriptor& descriptor, + backend::GraphicsContextEGL* cobalt_context, + GrContext* gr_context, + MessageLoop* rasterizer_message_loop); const math::Size& GetSize() const OVERRIDE { return size_; } // This method must only be called on the rasterizer thread. This should not - // be tricky to enforce since it is declared in SkiaImage, and not Image. + // be tricky to enforce since it is declared in skia::Image, and not Image. // The outside world deals only with Image objects and typically it is only - // the skia render tree visitor that is aware of SkiaImages. Since the + // the skia render tree visitor that is aware of skia::Images. Since the // skia render tree should only be visited on the rasterizer thread, this // restraint should always be satisfied naturally. const SkBitmap& GetBitmap() const OVERRIDE; @@ -102,12 +103,12 @@ void EnsureInitialized() OVERRIDE; private: - ~SkiaHardwareFrontendImage() OVERRIDE; + ~HardwareFrontendImage() OVERRIDE; // The following Initialize functions will construct |backend_image_|, but // only if |backend_image_| is ever needed by the rasterizer thread. void InitializeBackendImageFromImageData( - scoped_ptr<SkiaHardwareImageData> image_data, + scoped_ptr<HardwareImageData> image_data, backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context); void InitializeBackendImageFromRawImageData( const scoped_refptr<backend::ConstRawTextureMemoryEGL>& @@ -121,20 +122,20 @@ // We keep track of a message loop which indicates the loop upon which we // can issue graphics commands. Specifically, this is the message loop - // where all SkiaHardwareBackendImage (described below) logic is executed + // where all HardwareBackendImage (described below) logic is executed // on. MessageLoop* rasterizer_message_loop_; - // The SkiaHardwareBackendImage object is where all our rasterizer thread + // The HardwareBackendImage object is where all our rasterizer thread // specific objects live, such as the backend Skia graphics reference to // the texture object. These items typically must be created, accessed and // destroyed all on the same thread, and so this object's methods should // always be executed on the rasterizer thread. It is constructed when - // the SkiaHardwareFrontendImage is constructed, but destroyed when - // a message sent by SkiaHardwareFrontendImage's destructor is received by + // the HardwareFrontendImage is constructed, but destroyed when + // a message sent by HardwareFrontendImage's destructor is received by // the rasterizer thread. - class SkiaHardwareBackendImage; - scoped_ptr<SkiaHardwareBackendImage> backend_image_; + class HardwareBackendImage; + scoped_ptr<HardwareBackendImage> backend_image_; // This closure binds the backend image construction parameters so that we // can delay construction of it until it is accessed by the rasterizer thread. @@ -144,10 +145,10 @@ }; // Multi-plane images are implemented as collections of single plane images. -class SkiaHardwareMultiPlaneImage : public SkiaMultiPlaneImage { +class HardwareMultiPlaneImage : public MultiPlaneImage { public: - SkiaHardwareMultiPlaneImage( - scoped_ptr<SkiaHardwareRawImageMemory> raw_image_memory, + HardwareMultiPlaneImage( + scoped_ptr<HardwareRawImageMemory> raw_image_memory, const render_tree::MultiPlaneImageDataDescriptor& descriptor, backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context, MessageLoop* rasterizer_message_loop); @@ -166,14 +167,14 @@ void EnsureInitialized() OVERRIDE; private: - ~SkiaHardwareMultiPlaneImage() OVERRIDE; + ~HardwareMultiPlaneImage() OVERRIDE; const math::Size size_; render_tree::MultiPlaneImageFormat format_; // We maintain a single-plane image for each plane of this multi-plane image. - scoped_refptr<SkiaHardwareFrontendImage> + scoped_refptr<HardwareFrontendImage> planes_[render_tree::MultiPlaneImageDataDescriptor::kMaxPlanes]; };
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc b/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc index 696ba9c..51f3f6d 100644 --- a/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc +++ b/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc
@@ -36,17 +36,11 @@ namespace rasterizer { namespace skia { -namespace { - -const int kMaxSkiaCacheResources = 128; -const size_t kMaxSkiaCacheBytes = 4 * 1024 * 1024u; - -} // namespace - -class SkiaHardwareRasterizer::Impl { +class HardwareRasterizer::Impl { public: - explicit Impl(backend::GraphicsContext* graphics_context, - int surface_cache_size_in_bytes); + Impl(backend::GraphicsContext* graphics_context, int skia_cache_size_in_bytes, + int scratch_surface_cache_size_in_bytes, + int surface_cache_size_in_bytes); ~Impl(); void Submit(const scoped_refptr<render_tree::Node>& render_tree, @@ -57,7 +51,7 @@ private: class CachedScratchSurfaceHolder - : public SkiaRenderTreeNodeVisitor::ScratchSurface { + : public RenderTreeNodeVisitor::ScratchSurface { public: CachedScratchSurfaceHolder(ScratchSurfaceCache* cache, const math::Size& size) @@ -71,7 +65,7 @@ }; SkSurface* CreateSkSurface(const math::Size& size); - scoped_ptr<SkiaRenderTreeNodeVisitor::ScratchSurface> CreateScratchSurface( + scoped_ptr<RenderTreeNodeVisitor::ScratchSurface> CreateScratchSurface( const math::Size& size); base::ThreadChecker thread_checker_; @@ -124,12 +118,19 @@ } // namespace -SkiaHardwareRasterizer::Impl::Impl(backend::GraphicsContext* graphics_context, - int surface_cache_size_in_bytes) +HardwareRasterizer::Impl::Impl(backend::GraphicsContext* graphics_context, + int skia_cache_size_in_bytes, + int scratch_surface_cache_size_in_bytes, + int surface_cache_size_in_bytes) : graphics_context_( base::polymorphic_downcast<backend::GraphicsContextEGL*>( graphics_context)) { - TRACE_EVENT0("cobalt::renderer", "SkiaHardwareRasterizer::Impl::Impl()"); + TRACE_EVENT0("cobalt::renderer", "HardwareRasterizer::Impl::Impl()"); + + DLOG(INFO) << "skia_cache_size_in_bytes: " << skia_cache_size_in_bytes; + DLOG(INFO) << "scratch_surface_cache_size_in_bytes: " + << scratch_surface_cache_size_in_bytes; + DLOG(INFO) << "surface_cache_size_in_bytes: " << surface_cache_size_in_bytes; graphics_context_->MakeCurrent(); // Create a GrContext object that wraps the passed in Cobalt GraphicsContext @@ -143,19 +144,21 @@ // rendering shadow effects, gradient effects, and software rendered paths. // As we have our own cache for most resources, set it to a much smaller value // so Skia doesn't use too much GPU memory. - gr_context_->setResourceCacheLimits( - kMaxSkiaCacheResources, kMaxSkiaCacheBytes); + const int kSkiaCacheMaxResources = 128; + gr_context_->setResourceCacheLimits(kSkiaCacheMaxResources, + skia_cache_size_in_bytes); base::Callback<SkSurface*(const math::Size&)> create_sk_surface_function = - base::Bind(&SkiaHardwareRasterizer::Impl::CreateSkSurface, + base::Bind(&HardwareRasterizer::Impl::CreateSkSurface, base::Unretained(this)); - scratch_surface_cache_.emplace(create_sk_surface_function); + scratch_surface_cache_.emplace(create_sk_surface_function, + scratch_surface_cache_size_in_bytes); // Setup a resource provider for resources to be used with a hardware // accelerated Skia rasterizer. resource_provider_.reset( - new SkiaHardwareResourceProvider(graphics_context_, gr_context_)); + new HardwareResourceProvider(graphics_context_, gr_context_)); graphics_context_->ReleaseCurrentContext(); if (surface_cache_size_in_bytes > 0) { @@ -169,7 +172,7 @@ } } -SkiaHardwareRasterizer::Impl::~Impl() { +HardwareRasterizer::Impl::~Impl() { graphics_context_->MakeCurrent(); sk_output_surface_.reset(NULL); surface_cache_ = base::nullopt; @@ -179,7 +182,7 @@ graphics_context_->ReleaseCurrentContext(); } -void SkiaHardwareRasterizer::Impl::Submit( +void HardwareRasterizer::Impl::Submit( const scoped_refptr<render_tree::Node>& render_tree, const scoped_refptr<backend::RenderTarget>& render_target, int options) { DCHECK(thread_checker_.CalledOnValidThread()); @@ -224,11 +227,11 @@ { TRACE_EVENT0("cobalt::renderer", "VisitRenderTree"); // Rasterize the passed in render tree to our hardware render target. - SkiaRenderTreeNodeVisitor::CreateScratchSurfaceFunction + RenderTreeNodeVisitor::CreateScratchSurfaceFunction create_scratch_surface_function = - base::Bind(&SkiaHardwareRasterizer::Impl::CreateScratchSurface, + base::Bind(&HardwareRasterizer::Impl::CreateScratchSurface, base::Unretained(this)); - SkiaRenderTreeNodeVisitor visitor( + RenderTreeNodeVisitor visitor( canvas, &create_scratch_surface_function, surface_cache_delegate_ ? &surface_cache_delegate_.value() : NULL, surface_cache_ ? &surface_cache_.value() : NULL); @@ -243,14 +246,12 @@ graphics_context_->SwapBuffers(render_target_egl); } -render_tree::ResourceProvider* -SkiaHardwareRasterizer::Impl::GetResourceProvider() { +render_tree::ResourceProvider* HardwareRasterizer::Impl::GetResourceProvider() { return resource_provider_.get(); } -SkSurface* SkiaHardwareRasterizer::Impl::CreateSkSurface( - const math::Size& size) { - TRACE_EVENT2("cobalt::renderer", "SkiaHardwareRasterizer::CreateSkSurface()", +SkSurface* HardwareRasterizer::Impl::CreateSkSurface(const math::Size& size) { + TRACE_EVENT2("cobalt::renderer", "HardwareRasterizer::CreateSkSurface()", "width", size.width(), "height", size.height()); // Create a texture of the specified size. Then convert it to a render @@ -284,36 +285,38 @@ return SkSurface::NewRenderTargetDirect(skia_render_target, &surface_props); } -scoped_ptr<SkiaRenderTreeNodeVisitor::ScratchSurface> -SkiaHardwareRasterizer::Impl::CreateScratchSurface(const math::Size& size) { - TRACE_EVENT2("cobalt::renderer", - "SkiaHardwareRasterizer::CreateScratchImage()", "width", - size.width(), "height", size.height()); +scoped_ptr<RenderTreeNodeVisitor::ScratchSurface> +HardwareRasterizer::Impl::CreateScratchSurface(const math::Size& size) { + TRACE_EVENT2("cobalt::renderer", "HardwareRasterizer::CreateScratchImage()", + "width", size.width(), "height", size.height()); scoped_ptr<CachedScratchSurfaceHolder> scratch_surface( new CachedScratchSurfaceHolder(&scratch_surface_cache_.value(), size)); if (scratch_surface->GetSurface()) { - return scratch_surface.PassAs<SkiaRenderTreeNodeVisitor::ScratchSurface>(); + return scratch_surface.PassAs<RenderTreeNodeVisitor::ScratchSurface>(); } else { - return scoped_ptr<SkiaRenderTreeNodeVisitor::ScratchSurface>(); + return scoped_ptr<RenderTreeNodeVisitor::ScratchSurface>(); } } -SkiaHardwareRasterizer::SkiaHardwareRasterizer( - backend::GraphicsContext* graphics_context, int surface_cache_size_in_bytes) - : impl_(new Impl(graphics_context, surface_cache_size_in_bytes)) {} +HardwareRasterizer::HardwareRasterizer( + backend::GraphicsContext* graphics_context, int skia_cache_size_in_bytes, + int scratch_surface_cache_size_in_bytes, int surface_cache_size_in_bytes) + : impl_(new Impl(graphics_context, skia_cache_size_in_bytes, + scratch_surface_cache_size_in_bytes, + surface_cache_size_in_bytes)) {} -SkiaHardwareRasterizer::~SkiaHardwareRasterizer() {} +HardwareRasterizer::~HardwareRasterizer() {} -void SkiaHardwareRasterizer::Submit( +void HardwareRasterizer::Submit( const scoped_refptr<render_tree::Node>& render_tree, const scoped_refptr<backend::RenderTarget>& render_target, int options) { TRACE_EVENT0("cobalt::renderer", "Rasterizer::Submit()"); - TRACE_EVENT0("cobalt::renderer", "SkiaHardwareRasterizer::Submit()"); + TRACE_EVENT0("cobalt::renderer", "HardwareRasterizer::Submit()"); impl_->Submit(render_tree, render_target, options); } -render_tree::ResourceProvider* SkiaHardwareRasterizer::GetResourceProvider() { +render_tree::ResourceProvider* HardwareRasterizer::GetResourceProvider() { return impl_->GetResourceProvider(); }
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.h b/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.h index d0d9d96..8807fc3 100644 --- a/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.h +++ b/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.h
@@ -28,22 +28,32 @@ namespace rasterizer { namespace skia { -// This SkiaHardwareRasterizer class represents a rasterizer that will setup +// This HardwareRasterizer class represents a rasterizer that will setup // a Skia hardware rendering context. When Submit() is called, the passed in // render tree will be rasterized using hardware-accelerated Skia. The -// SkiaHardwareRasterizer must be constructed on the same thread that Submit() +// HardwareRasterizer must be constructed on the same thread that Submit() // is to be called on. -class SkiaHardwareRasterizer : public Rasterizer { +class HardwareRasterizer : public Rasterizer { public: // The passed in render target will be used to determine the dimensions of // the output. The graphics context will be used to issue commands to the GPU - // to blit the final output to the render target. If |surface_cache_size| is - // non-zero, the rasterizer will set itself up with a surface cache such that - // expensive render tree nodes seen multiple times will get saved to offscreen - // surfaces. - explicit SkiaHardwareRasterizer(backend::GraphicsContext* graphics_context, - int surface_cache_size_in_bytes); - virtual ~SkiaHardwareRasterizer(); + // to blit the final output to the render target. + // The value of |skia_cache_size_in_bytes| dictates the maximum amount of + // memory that Skia will use to cache the results of certain effects that take + // a long time to render, such as shadows. The results will be reused across + // submissions. + // The value of |scratch_surface_cache_size_in_bytes| sets an upper limit on + // the number of bytes that can be consumed by the scratch surface cache, + // a facility that allows temporary surfaces to be reused within the + // rasterization of a single frame/submission. + // If |surface_cache_size| is non-zero, the rasterizer will set itself up with + // a surface cache such that expensive render tree nodes seen multiple times + // will get saved to offscreen surfaces. + explicit HardwareRasterizer(backend::GraphicsContext* graphics_context, + int skia_cache_size_in_bytes, + int scratch_surface_cache_size_in_bytes, + int surface_cache_size_in_bytes); + virtual ~HardwareRasterizer(); // Consume the render tree and output the results to the render target passed // into the constructor.
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc index 8dbb7ce..1a1fc84 100644 --- a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc +++ b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc
@@ -41,54 +41,52 @@ namespace rasterizer { namespace skia { -SkiaHardwareResourceProvider::SkiaHardwareResourceProvider( +HardwareResourceProvider::HardwareResourceProvider( backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context) : cobalt_context_(cobalt_context), gr_context_(gr_context), self_message_loop_(MessageLoop::current()) {} -bool SkiaHardwareResourceProvider::PixelFormatSupported( +bool HardwareResourceProvider::PixelFormatSupported( render_tree::PixelFormat pixel_format) { return pixel_format == render_tree::kPixelFormatRGBA8; } -bool SkiaHardwareResourceProvider::AlphaFormatSupported( +bool HardwareResourceProvider::AlphaFormatSupported( render_tree::AlphaFormat alpha_format) { return alpha_format == render_tree::kAlphaFormatPremultiplied; } -scoped_ptr<ImageData> SkiaHardwareResourceProvider::AllocateImageData( +scoped_ptr<ImageData> HardwareResourceProvider::AllocateImageData( const math::Size& size, render_tree::PixelFormat pixel_format, render_tree::AlphaFormat alpha_format) { TRACE_EVENT0("cobalt::renderer", - "SkiaHardwareResourceProvider::AllocateImageData()"); + "HardwareResourceProvider::AllocateImageData()"); DCHECK_EQ(render_tree::kPixelFormatRGBA8, pixel_format) << "Currently, only RGBA8 is supported."; DCHECK(PixelFormatSupported(pixel_format)); DCHECK(AlphaFormatSupported(alpha_format)); - return scoped_ptr<ImageData>(new SkiaHardwareImageData( + return scoped_ptr<ImageData>(new HardwareImageData( cobalt_context_->system_egl()->AllocateTextureData( size, ConvertRenderTreeFormatToGL(pixel_format)), pixel_format, alpha_format)); } -scoped_refptr<Image> SkiaHardwareResourceProvider::CreateImage( +scoped_refptr<render_tree::Image> HardwareResourceProvider::CreateImage( scoped_ptr<ImageData> source_data) { - TRACE_EVENT0("cobalt::renderer", - "SkiaHardwareResourceProvider::CreateImage()"); - scoped_ptr<SkiaHardwareImageData> skia_hardware_source_data( - base::polymorphic_downcast<SkiaHardwareImageData*>( - source_data.release())); + TRACE_EVENT0("cobalt::renderer", "HardwareResourceProvider::CreateImage()"); + scoped_ptr<HardwareImageData> skia_hardware_source_data( + base::polymorphic_downcast<HardwareImageData*>(source_data.release())); const render_tree::ImageDataDescriptor& descriptor = skia_hardware_source_data->GetDescriptor(); DCHECK_EQ(render_tree::kAlphaFormatPremultiplied, descriptor.alpha_format); #if defined(COBALT_BUILD_TYPE_DEBUG) - SkiaImage::DCheckForPremultipliedAlpha( - descriptor.size, descriptor.pitch_in_bytes, descriptor.pixel_format, - skia_hardware_source_data->GetMemory()); + Image::DCheckForPremultipliedAlpha(descriptor.size, descriptor.pitch_in_bytes, + descriptor.pixel_format, + skia_hardware_source_data->GetMemory()); #endif // Construct a frontend image from this data, which internally will send @@ -96,56 +94,58 @@ // backend texture will be constructed, and associated with this frontend // texture through a map that will be accessed when the rasterizer visits // any subsequently submitted render trees referencing the frontend image. - return make_scoped_refptr(new SkiaHardwareFrontendImage( + return make_scoped_refptr(new HardwareFrontendImage( skia_hardware_source_data.Pass(), cobalt_context_, gr_context_, self_message_loop_)); } -scoped_ptr<RawImageMemory> SkiaHardwareResourceProvider::AllocateRawImageMemory( +scoped_ptr<RawImageMemory> HardwareResourceProvider::AllocateRawImageMemory( size_t size_in_bytes, size_t alignment) { TRACE_EVENT0("cobalt::renderer", - "SkiaHardwareResourceProvider::AllocateRawImageMemory()"); - return scoped_ptr<RawImageMemory>(new SkiaHardwareRawImageMemory( + "HardwareResourceProvider::AllocateRawImageMemory()"); + return scoped_ptr<RawImageMemory>(new HardwareRawImageMemory( cobalt_context_->system_egl()->AllocateRawTextureMemory(size_in_bytes, alignment))); } -scoped_refptr<Image> -SkiaHardwareResourceProvider::CreateMultiPlaneImageFromRawMemory( +scoped_refptr<render_tree::Image> +HardwareResourceProvider::CreateMultiPlaneImageFromRawMemory( scoped_ptr<RawImageMemory> raw_image_memory, const render_tree::MultiPlaneImageDataDescriptor& descriptor) { TRACE_EVENT0( "cobalt::renderer", - "SkiaHardwareResourceProvider::CreateMultiPlaneImageFromRawMemory()"); - DCHECK_EQ(render_tree::kMultiPlaneImageFormatYUV3PlaneBT709, - descriptor.image_format()) - << "Currently we only support 3-plane YUV multi plane images."; - DCHECK_EQ(3, descriptor.num_planes()); + "HardwareResourceProvider::CreateMultiPlaneImageFromRawMemory()"); + DCHECK((render_tree::kMultiPlaneImageFormatYUV2PlaneBT709 == + descriptor.image_format() && + 2 == descriptor.num_planes()) || + (render_tree::kMultiPlaneImageFormatYUV3PlaneBT709 == + descriptor.image_format() && + 3 == descriptor.num_planes())) + << "Currently we only support 2-plane or 3-plane YUV multi plane images."; - scoped_ptr<SkiaHardwareRawImageMemory> skia_hardware_raw_image_memory( - base::polymorphic_downcast<SkiaHardwareRawImageMemory*>( + scoped_ptr<HardwareRawImageMemory> skia_hardware_raw_image_memory( + base::polymorphic_downcast<HardwareRawImageMemory*>( raw_image_memory.release())); - return make_scoped_refptr(new SkiaHardwareMultiPlaneImage( + return make_scoped_refptr(new HardwareMultiPlaneImage( skia_hardware_raw_image_memory.Pass(), descriptor, cobalt_context_, gr_context_, self_message_loop_)); } -bool SkiaHardwareResourceProvider::HasLocalFontFamily( +bool HardwareResourceProvider::HasLocalFontFamily( const char* font_family_name) const { TRACE_EVENT0("cobalt::renderer", - "SkiaHardwareResourceProvider::HasLocalFontFamily()"); + "HardwareResourceProvider::HasLocalFontFamily()"); SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault()); SkAutoTUnref<SkFontStyleSet> style_set(fm->matchFamily(font_family_name)); return style_set->count() > 0; } -scoped_refptr<render_tree::Typeface> -SkiaHardwareResourceProvider::GetLocalTypeface( +scoped_refptr<render_tree::Typeface> HardwareResourceProvider::GetLocalTypeface( const char* font_family_name, render_tree::FontStyle font_style) { TRACE_EVENT0("cobalt::renderer", - "SkiaHardwareResourceProvider::GetLocalTypeface()"); + "HardwareResourceProvider::GetLocalTypeface()"); SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault()); SkAutoTUnref<SkTypeface> typeface(fm->matchFamilyStyle( @@ -154,11 +154,11 @@ } scoped_refptr<render_tree::Typeface> -SkiaHardwareResourceProvider::GetCharacterFallbackTypeface( +HardwareResourceProvider::GetCharacterFallbackTypeface( int32 character, render_tree::FontStyle font_style, const std::string& language) { TRACE_EVENT0("cobalt::renderer", - "SkiaHardwareResourceProvider::GetCharacterFallbackTypeface()"); + "HardwareResourceProvider::GetCharacterFallbackTypeface()"); SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault()); SkAutoTUnref<SkTypeface> typeface( @@ -168,11 +168,11 @@ } scoped_refptr<render_tree::Typeface> -SkiaHardwareResourceProvider::CreateTypefaceFromRawData( +HardwareResourceProvider::CreateTypefaceFromRawData( scoped_ptr<render_tree::ResourceProvider::RawTypefaceDataVector> raw_data, std::string* error_string) { TRACE_EVENT0("cobalt::renderer", - "SkiaHardwareResourceProvider::CreateFontFromData()"); + "HardwareResourceProvider::CreateFontFromData()"); if (raw_data == NULL) { *error_string = "No data to process"; @@ -203,7 +203,7 @@ } scoped_refptr<render_tree::GlyphBuffer> -SkiaHardwareResourceProvider::CreateGlyphBuffer( +HardwareResourceProvider::CreateGlyphBuffer( const char16* text_buffer, size_t text_length, const std::string& language, bool is_rtl, render_tree::FontProvider* font_provider) { return text_shaper_.CreateGlyphBuffer(text_buffer, text_length, language, @@ -211,13 +211,13 @@ } scoped_refptr<render_tree::GlyphBuffer> -SkiaHardwareResourceProvider::CreateGlyphBuffer( +HardwareResourceProvider::CreateGlyphBuffer( const std::string& utf8_string, const scoped_refptr<render_tree::Font>& font) { return text_shaper_.CreateGlyphBuffer(utf8_string, font); } -float SkiaHardwareResourceProvider::GetTextWidth( +float HardwareResourceProvider::GetTextWidth( const char16* text_buffer, size_t text_length, const std::string& language, bool is_rtl, render_tree::FontProvider* font_provider, render_tree::FontVector* maybe_used_fonts) {
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h index 4d344c4..aec9c85 100644 --- a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h +++ b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h
@@ -33,10 +33,10 @@ // This class must be thread-safe and capable of creating resources that // are to be consumed by this skia hardware rasterizer. It must be constructed // on the thread that will be visiting submitted render trees. -class SkiaHardwareResourceProvider : public render_tree::ResourceProvider { +class HardwareResourceProvider : public render_tree::ResourceProvider { public: - SkiaHardwareResourceProvider(backend::GraphicsContextEGL* cobalt_context, - GrContext* gr_context); + HardwareResourceProvider(backend::GraphicsContextEGL* cobalt_context, + GrContext* gr_context); bool PixelFormatSupported(render_tree::PixelFormat pixel_format) OVERRIDE; bool AlphaFormatSupported(render_tree::AlphaFormat alpha_format) OVERRIDE;
diff --git a/src/cobalt/renderer/rasterizer/skia/harfbuzz_font.cc b/src/cobalt/renderer/rasterizer/skia/harfbuzz_font.cc index 06389ab..62493f3 100644 --- a/src/cobalt/renderer/rasterizer/skia/harfbuzz_font.cc +++ b/src/cobalt/renderer/rasterizer/skia/harfbuzz_font.cc
@@ -52,7 +52,7 @@ // Outputs the |width| and |extents| of the glyph with index |codepoint| in // |paint|'s font. -void GetGlyphWidthAndExtents(SkiaFont* skia_font, hb_codepoint_t codepoint, +void GetGlyphWidthAndExtents(Font* skia_font, hb_codepoint_t codepoint, hb_position_t* width, hb_glyph_extents_t* extents) { DCHECK_LE(codepoint, std::numeric_limits<uint16_t>::max()); @@ -78,7 +78,7 @@ hb_bool_t GetGlyph(hb_font_t* font, void* data, hb_codepoint_t unicode, hb_codepoint_t variation_selector, hb_codepoint_t* glyph, void* user_data) { - SkiaFont* skia_font = reinterpret_cast<SkiaFont*>(data); + Font* skia_font = reinterpret_cast<Font*>(data); *glyph = skia_font->GetGlyphForCharacter(unicode); return !!*glyph; } @@ -86,7 +86,7 @@ // Returns the horizontal advance value of the |glyph|. hb_position_t GetGlyphHorizontalAdvance(hb_font_t* font, void* data, hb_codepoint_t glyph, void* user_data) { - SkiaFont* skia_font = reinterpret_cast<SkiaFont*>(data); + Font* skia_font = reinterpret_cast<Font*>(data); hb_position_t advance = 0; GetGlyphWidthAndExtents(skia_font, glyph, &advance, 0); @@ -100,7 +100,7 @@ return true; } -hb_position_t GetGlyphKerning(SkiaFont* font_data, hb_codepoint_t first_glyph, +hb_position_t GetGlyphKerning(Font* font_data, hb_codepoint_t first_glyph, hb_codepoint_t second_glyph) { SkAutoTUnref<SkTypeface> typeface(font_data->GetSkTypeface()); const uint16_t glyphs[2] = {static_cast<uint16_t>(first_glyph), @@ -121,7 +121,7 @@ hb_codepoint_t left_glyph, hb_codepoint_t right_glyph, void* user_data) { - SkiaFont* skia_font = reinterpret_cast<SkiaFont*>(data); + Font* skia_font = reinterpret_cast<Font*>(data); return GetGlyphKerning(skia_font, left_glyph, right_glyph); } @@ -136,7 +136,7 @@ // Writes the |extents| of |glyph|. hb_bool_t GetGlyphExtents(hb_font_t* font, void* data, hb_codepoint_t glyph, hb_glyph_extents_t* extents, void* user_data) { - SkiaFont* skia_font = reinterpret_cast<SkiaFont*>(data); + Font* skia_font = reinterpret_cast<Font*>(data); GetGlyphWidthAndExtents(skia_font, glyph, 0, extents); return true; } @@ -222,7 +222,7 @@ } // namespace // Creates a HarfBuzz font from the given Skia font. -hb_font_t* CreateHarfBuzzFont(SkiaFont* skia_font) { +hb_font_t* CreateHarfBuzzFont(Font* skia_font) { static std::map<SkFontID, HarfBuzzFace> face_caches; // Retrieve the typeface from the cache. In the case where it does not already
diff --git a/src/cobalt/renderer/rasterizer/skia/harfbuzz_font.h b/src/cobalt/renderer/rasterizer/skia/harfbuzz_font.h index 689f159..a37e5c1 100644 --- a/src/cobalt/renderer/rasterizer/skia/harfbuzz_font.h +++ b/src/cobalt/renderer/rasterizer/skia/harfbuzz_font.h
@@ -28,9 +28,9 @@ namespace rasterizer { namespace skia { -class SkiaFont; +class Font; -hb_font_t* CreateHarfBuzzFont(SkiaFont* skia_font); +hb_font_t* CreateHarfBuzzFont(Font* skia_font); } // namespace skia } // namespace rasterizer
diff --git a/src/cobalt/renderer/rasterizer/skia/image.cc b/src/cobalt/renderer/rasterizer/skia/image.cc index 850007f..ceaf0c5 100644 --- a/src/cobalt/renderer/rasterizer/skia/image.cc +++ b/src/cobalt/renderer/rasterizer/skia/image.cc
@@ -24,13 +24,15 @@ namespace rasterizer { namespace skia { -void SkiaImage::DCheckForPremultipliedAlpha( - const math::Size& dimensions, int source_pitch_in_bytes, - render_tree::PixelFormat pixel_format, const uint8_t* source_pixels) { - TRACE_EVENT0("cobalt::renderer", "SkiaImage::DCheckForPremultipliedAlpha()"); +void Image::DCheckForPremultipliedAlpha(const math::Size& dimensions, + int source_pitch_in_bytes, + render_tree::PixelFormat pixel_format, + const uint8_t* source_pixels) { + TRACE_EVENT0("cobalt::renderer", "Image::DCheckForPremultipliedAlpha()"); if (pixel_format == render_tree::kPixelFormatY8 || pixel_format == render_tree::kPixelFormatU8 || - pixel_format == render_tree::kPixelFormatV8) { + pixel_format == render_tree::kPixelFormatV8 || + pixel_format == render_tree::kPixelFormatUV8) { // These formats don't have alpha, so they are trivially good to go. return; }
diff --git a/src/cobalt/renderer/rasterizer/skia/image.h b/src/cobalt/renderer/rasterizer/skia/image.h index 839b848..cd2e907 100644 --- a/src/cobalt/renderer/rasterizer/skia/image.h +++ b/src/cobalt/renderer/rasterizer/skia/image.h
@@ -31,7 +31,7 @@ // Introduce a base class for both software and hardware Skia images. They // should both be able to return a SkBitmap that can be used in subsequent // Skia draw calls. -class SkiaImage : public render_tree::Image { +class Image : public render_tree::Image { public: // Ensures that any queued backend initialization of this image object is // completed after this method returns. This can only be called from the @@ -43,7 +43,7 @@ // executed. virtual void EnsureInitialized() = 0; - // Mechanism to allow dynamic type checking on SkiaImage objects. + // Mechanism to allow dynamic type checking on Image objects. virtual base::TypeId GetTypeId() const = 0; // A helper function for DCHECKing that given image data is indeed in @@ -58,25 +58,25 @@ // A single-plane image is an image where all data to describe a single pixel // is stored contiguously. This style of image is by far the most common. -class SkiaSinglePlaneImage : public SkiaImage { +class SinglePlaneImage : public Image { public: virtual const SkBitmap& GetBitmap() const = 0; base::TypeId GetTypeId() const OVERRIDE { - return base::GetTypeId<SkiaSinglePlaneImage>(); + return base::GetTypeId<SinglePlaneImage>(); } }; // A multi-plane image is one where different channels may have different planes // (i.e. sub-images) stored in different regions of memory. A multi-plane // image can be defined in terms of a set of single-plane images. -class SkiaMultiPlaneImage : public SkiaImage { +class MultiPlaneImage : public Image { public: virtual render_tree::MultiPlaneImageFormat GetFormat() const = 0; virtual const SkBitmap& GetBitmap(int plane_index) const = 0; base::TypeId GetTypeId() const OVERRIDE { - return base::GetTypeId<SkiaMultiPlaneImage>(); + return base::GetTypeId<MultiPlaneImage>(); } };
diff --git a/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc b/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc index cd39b91..6c9c5f6 100644 --- a/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc +++ b/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc
@@ -44,6 +44,7 @@ #include "cobalt/renderer/rasterizer/skia/font.h" #include "cobalt/renderer/rasterizer/skia/glyph_buffer.h" #include "cobalt/renderer/rasterizer/skia/image.h" +#include "cobalt/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.h" #include "cobalt/renderer/rasterizer/skia/skia/src/effects/SkYUV2RGBShader.h" #include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/core/SkTypeface.h" @@ -68,7 +69,7 @@ namespace rasterizer { namespace skia { -SkiaRenderTreeNodeVisitor::SkiaRenderTreeNodeVisitor( +RenderTreeNodeVisitor::RenderTreeNodeVisitor( SkCanvas* render_target, const CreateScratchSurfaceFunction* create_scratch_surface_function, SurfaceCacheDelegate* surface_cache_delegate, @@ -84,7 +85,7 @@ // visitor and our canvas. surface_cache_scoped_context_.emplace( surface_cache_delegate_, render_target_, - base::Bind(&SkiaRenderTreeNodeVisitor::SetRenderTarget, + base::Bind(&RenderTreeNodeVisitor::SetRenderTarget, base::Unretained(this))); } } @@ -107,7 +108,7 @@ } } // namespace -void SkiaRenderTreeNodeVisitor::Visit( +void RenderTreeNodeVisitor::Visit( render_tree::CompositionNode* composition_node) { #if ENABLE_RENDER_TREE_VISITOR_TRACING TRACE_EVENT0("cobalt::renderer", "Visit(CompositionNode)"); @@ -221,7 +222,7 @@ } // namespace -void SkiaRenderTreeNodeVisitor::RenderFilterViaOffscreenSurface( +void RenderTreeNodeVisitor::RenderFilterViaOffscreenSurface( const render_tree::FilterNode::Builder& filter_node) { const SkMatrix& total_matrix_skia = render_target_->getTotalMatrix(); math::Matrix3F total_matrix = SkiaMatrixToCobalt(total_matrix_skia); @@ -264,9 +265,9 @@ // Render our source sub-tree into the offscreen surface. { - SkiaRenderTreeNodeVisitor sub_visitor( - canvas, create_scratch_surface_function_, surface_cache_delegate_, - surface_cache_, kType_SubVisitor); + RenderTreeNodeVisitor sub_visitor(canvas, create_scratch_surface_function_, + surface_cache_delegate_, surface_cache_, + kType_SubVisitor); filter_node.source->Accept(&sub_visitor); } @@ -342,7 +343,7 @@ } } // namespace -void SkiaRenderTreeNodeVisitor::Visit(render_tree::FilterNode* filter_node) { +void RenderTreeNodeVisitor::Visit(render_tree::FilterNode* filter_node) { #if ENABLE_RENDER_TREE_VISITOR_TRACING TRACE_EVENT0("cobalt::renderer", "Visit(FilterNode)"); @@ -460,7 +461,7 @@ return paint; } -void RenderSinglePlaneImage(SkiaSinglePlaneImage* single_plane_image, +void RenderSinglePlaneImage(SinglePlaneImage* single_plane_image, SkCanvas* render_target, const math::RectF& destination_rect, const math::Matrix3F* local_transform) { @@ -505,36 +506,51 @@ } } -void RenderMultiPlaneImage(SkiaMultiPlaneImage* multi_plane_image, +void RenderMultiPlaneImage(MultiPlaneImage* multi_plane_image, SkCanvas* render_target, const math::RectF& destination_rect, const math::Matrix3F* local_transform) { - DCHECK_EQ(render_tree::kMultiPlaneImageFormatYUV3PlaneBT709, - multi_plane_image->GetFormat()); - SkMatrix skia_local_transform = CobaltMatrixToSkia(*local_transform); const SkBitmap& y_bitmap = multi_plane_image->GetBitmap(0); + DCHECK(!y_bitmap.isNull()); SkMatrix y_matrix = skia_local_transform; ConvertLocalTransformMatrixToSkiaShaderFormat( math::Size(y_bitmap.width(), y_bitmap.height()), destination_rect, &y_matrix); const SkBitmap& u_bitmap = multi_plane_image->GetBitmap(1); + DCHECK(!u_bitmap.isNull()); SkMatrix u_matrix = skia_local_transform; ConvertLocalTransformMatrixToSkiaShaderFormat( math::Size(u_bitmap.width(), u_bitmap.height()), destination_rect, &u_matrix); - const SkBitmap& v_bitmap = multi_plane_image->GetBitmap(2); - SkMatrix v_matrix = skia_local_transform; - ConvertLocalTransformMatrixToSkiaShaderFormat( - math::Size(v_bitmap.width(), v_bitmap.height()), destination_rect, - &v_matrix); + SkAutoTUnref<SkShader> yuv2rgb_shader; - SkAutoTUnref<SkShader> yuv2rgb_shader( - SkNEW_ARGS(SkYUV2RGBShader, (kRec709_SkYUVColorSpace, y_bitmap, y_matrix, - u_bitmap, u_matrix, v_bitmap, v_matrix))); + switch (multi_plane_image->GetFormat()) { + case render_tree::kMultiPlaneImageFormatYUV2PlaneBT709: + yuv2rgb_shader.reset(SkNEW_ARGS( + SkNV122RGBShader, + (kRec709_SkYUVColorSpace, y_bitmap, y_matrix, u_bitmap, u_matrix))); + break; + case render_tree::kMultiPlaneImageFormatYUV3PlaneBT709: { + const SkBitmap& v_bitmap = multi_plane_image->GetBitmap(2); + DCHECK(!v_bitmap.isNull()); + SkMatrix v_matrix = skia_local_transform; + ConvertLocalTransformMatrixToSkiaShaderFormat( + math::Size(v_bitmap.width(), v_bitmap.height()), destination_rect, + &v_matrix); + yuv2rgb_shader.reset(SkNEW_ARGS( + SkYUV2RGBShader, (kRec709_SkYUVColorSpace, y_bitmap, y_matrix, + u_bitmap, u_matrix, v_bitmap, v_matrix))); + break; + } + default: { + NOTREACHED() << "Unsupported multi plane image format."; + break; + } + } SkPaint paint = CreateSkPaintForImageRendering(); paint.setShader(yuv2rgb_shader); @@ -543,7 +559,7 @@ } // namespace -void SkiaRenderTreeNodeVisitor::Visit(render_tree::ImageNode* image_node) { +void RenderTreeNodeVisitor::Visit(render_tree::ImageNode* image_node) { // The image_node may contain nothing. For example, when it represents a video // element before any frame is decoded. if (!image_node->data().source) { @@ -553,8 +569,8 @@ #if ENABLE_RENDER_TREE_VISITOR_TRACING TRACE_EVENT0("cobalt::renderer", "Visit(ImageNode)"); #endif - SkiaImage* image = - base::polymorphic_downcast<SkiaImage*>(image_node->data().source.get()); + skia::Image* image = + base::polymorphic_downcast<skia::Image*>(image_node->data().source.get()); // Creating an image via a resource provider may simply return a frontend // image object and enqueue the initialization of a backend image (to be @@ -570,16 +586,14 @@ // We issue different skia rasterization commands to render the image // depending on whether it's single or multi planed. - if (image->GetTypeId() == base::GetTypeId<SkiaSinglePlaneImage>()) { - RenderSinglePlaneImage( - base::polymorphic_downcast<SkiaSinglePlaneImage*>(image), - render_target_, image_node->data().destination_rect, - &(image_node->data().local_transform)); - } else if (image->GetTypeId() == base::GetTypeId<SkiaMultiPlaneImage>()) { - RenderMultiPlaneImage( - base::polymorphic_downcast<SkiaMultiPlaneImage*>(image), render_target_, - image_node->data().destination_rect, - &(image_node->data().local_transform)); + if (image->GetTypeId() == base::GetTypeId<SinglePlaneImage>()) { + RenderSinglePlaneImage(base::polymorphic_downcast<SinglePlaneImage*>(image), + render_target_, image_node->data().destination_rect, + &(image_node->data().local_transform)); + } else if (image->GetTypeId() == base::GetTypeId<MultiPlaneImage>()) { + RenderMultiPlaneImage(base::polymorphic_downcast<MultiPlaneImage*>(image), + render_target_, image_node->data().destination_rect, + &(image_node->data().local_transform)); } else { NOTREACHED(); } @@ -589,7 +603,7 @@ #endif } -void SkiaRenderTreeNodeVisitor::Visit( +void RenderTreeNodeVisitor::Visit( render_tree::MatrixTransformNode* matrix_transform_node) { #if ENABLE_RENDER_TREE_VISITOR_TRACING TRACE_EVENT0("cobalt::renderer", "Visit(MatrixTransformNode)"); @@ -621,7 +635,7 @@ #endif } -void SkiaRenderTreeNodeVisitor::Visit( +void RenderTreeNodeVisitor::Visit( render_tree::PunchThroughVideoNode* punch_through_video_node) { #if ENABLE_RENDER_TREE_VISITOR_TRACING TRACE_EVENT0("cobalt::renderer", "Visit(PunchThroughVideoNode)"); @@ -979,7 +993,7 @@ } // namespace -void SkiaRenderTreeNodeVisitor::Visit(render_tree::RectNode* rect_node) { +void RenderTreeNodeVisitor::Visit(render_tree::RectNode* rect_node) { #if ENABLE_RENDER_TREE_VISITOR_TRACING TRACE_EVENT0("cobalt::renderer", "Visit(RectNode)"); #endif @@ -1196,7 +1210,7 @@ } // namespace -void SkiaRenderTreeNodeVisitor::Visit( +void RenderTreeNodeVisitor::Visit( render_tree::RectShadowNode* rect_shadow_node) { #if ENABLE_RENDER_TREE_VISITOR_TRACING TRACE_EVENT0("cobalt::renderer", "Visit(RectShadowNode)"); @@ -1238,10 +1252,10 @@ NOTIMPLEMENTED() << "Cobalt does not yet support text blurs with Gaussian " "sigmas larger than 20."; } else { - SkiaGlyphBuffer* skia_glyph_buffer = - base::polymorphic_downcast<SkiaGlyphBuffer*>(glyph_buffer.get()); + GlyphBuffer* skia_glyph_buffer = + base::polymorphic_downcast<GlyphBuffer*>(glyph_buffer.get()); - SkPaint paint(SkiaFont::GetDefaultSkPaint()); + SkPaint paint(Font::GetDefaultSkPaint()); paint.setARGB(color.a() * 255, color.r() * 255, color.g() * 255, color.b() * 255); @@ -1259,7 +1273,7 @@ } } // namespace -void SkiaRenderTreeNodeVisitor::Visit(render_tree::TextNode* text_node) { +void RenderTreeNodeVisitor::Visit(render_tree::TextNode* text_node) { #if ENABLE_RENDER_TREE_VISITOR_TRACING TRACE_EVENT0("cobalt::renderer", "Visit(TextNode)"); #endif
diff --git a/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.h b/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.h index 96d886e..74f4be2 100644 --- a/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.h +++ b/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.h
@@ -37,7 +37,7 @@ namespace rasterizer { namespace skia { -class SkiaRenderTreeNodeVisitor : public render_tree::NodeVisitor { +class RenderTreeNodeVisitor : public render_tree::NodeVisitor { public: // This callback may be called by the visitor in order to obtain a SkSurface // from which both a SkCanvas can be obtained (for rendering into) and then @@ -58,11 +58,11 @@ }; // The create_scratch_surface_function functor object will be saved within - // SkiaRenderTreeNodeVisitor, so it must outlive the SkiaRenderTreeNodeVisitor + // RenderTreeNodeVisitor, so it must outlive the RenderTreeNodeVisitor // object. If |is_sub_visitor| is set to true, errors will be supported for // certain operations such as punch out alpha textures, as it is unfortunately // difficult to implement them when rendering to a sub-canvas. - SkiaRenderTreeNodeVisitor( + RenderTreeNodeVisitor( SkCanvas* render_target, const CreateScratchSurfaceFunction* create_scratch_surface_function, SurfaceCacheDelegate* surface_cache_delegate, @@ -96,7 +96,7 @@ base::optional<SurfaceCacheDelegate::ScopedContext> surface_cache_scoped_context_; - DISALLOW_COPY_AND_ASSIGN(SkiaRenderTreeNodeVisitor); + DISALLOW_COPY_AND_ASSIGN(RenderTreeNodeVisitor); }; } // namespace skia
diff --git a/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.cc b/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.cc index 1077388..1b62b9c 100644 --- a/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.cc +++ b/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.cc
@@ -29,12 +29,6 @@ namespace { -// We choose this cache size empirically, however exceeding the cache is allowed -// and won't have any detrimental effects, besides the fact that the cache -// won't be fully utilized. It may eventually be nice to allow this to be -// set as a paramter. -const size_t kMaxCacheSizeInBytes = 7 * 1024 * 1024; - // Approximate the memory usage of a given surface size. size_t ApproximateSurfaceMemory(const math::Size& size) { // Here we assume that we use 4 bytes per pixel. @@ -44,8 +38,10 @@ } // namespace ScratchSurfaceCache::ScratchSurfaceCache( - const CreateSkSurfaceFunction& create_sk_surface_function) + const CreateSkSurfaceFunction& create_sk_surface_function, + int cache_capacity_in_bytes) : create_sk_surface_function_(create_sk_surface_function), + cache_capacity_in_bytes_(cache_capacity_in_bytes), surface_memory_(0) {} ScratchSurfaceCache::~ScratchSurfaceCache() { @@ -178,8 +174,9 @@ void ScratchSurfaceCache::Purge() { // Delete surfaces from the front (least recently used) of |unused_surfaces_| // until we have deleted all surfaces or lowered our memory usage to under - // kMaxCacheSizeInBytes. - while (!unused_surfaces_.empty() && surface_memory_ > kMaxCacheSizeInBytes) { + // |cache_capacity_in_bytes_|. + while (!unused_surfaces_.empty() && + surface_memory_ > cache_capacity_in_bytes_) { SkSurface* to_free = unused_surfaces_.front(); surface_memory_ -= ApproximateSurfaceMemory( math::Size(to_free->width(), to_free->height()));
diff --git a/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.h b/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.h index 0e3489c..374cc66 100644 --- a/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.h +++ b/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.h
@@ -46,8 +46,8 @@ public: typedef base::Callback<SkSurface*(const math::Size&)> CreateSkSurfaceFunction; - ScratchSurfaceCache( - const CreateSkSurfaceFunction& create_sk_surface_function); + ScratchSurfaceCache(const CreateSkSurfaceFunction& create_sk_surface_function, + int cache_capacity_in_bytes); ~ScratchSurfaceCache(); private: @@ -70,6 +70,9 @@ // Called to allocate new SkSurfaces. CreateSkSurfaceFunction create_sk_surface_function_; + // The maximum number of surface bytes that can be stored in the cache. + int cache_capacity_in_bytes_; + // We keep track of all surfaces we've handed out using |surface_stack_|. // This is mostly for debug checks to verify that surfaces returned to us // actually did come from us, and that they are returned in the expected
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/config/SkUserConfig.h b/src/cobalt/renderer/rasterizer/skia/skia/config/SkUserConfig.h index 068de0a..5695744 100644 --- a/src/cobalt/renderer/rasterizer/skia/skia/config/SkUserConfig.h +++ b/src/cobalt/renderer/rasterizer/skia/skia/config/SkUserConfig.h
@@ -17,6 +17,10 @@ #ifndef SkUserConfig_DEFINED #define SkUserConfig_DEFINED +#if defined(STARBOARD) +#include "starboard/configuration.h" +#endif + /* SkTypes.h, the root of the public header files, does the following trick: #include <SkPreConfig.h> @@ -233,4 +237,10 @@ // ===== End Cobalt-specific definitions ===== +#if defined(STARBOARD) +#if SB_HAS_QUIRK(GL_NO_CONSTANT_ATTRIBUTE_SUPPORT) +#define GR_GL_NO_CONSTANT_ATTRIBUTES 1 +#endif // SB_HAS_QUIRK(GL_NO_CONSTANT_ATTRIBUTE_SUPPORT) +#endif // defined(STARBOARD) + #endif // SkUserConfig_DEFINED
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/skia.gyp b/src/cobalt/renderer/rasterizer/skia/skia/skia.gyp index 580dc23..08b36f9 100644 --- a/src/cobalt/renderer/rasterizer/skia/skia/skia.gyp +++ b/src/cobalt/renderer/rasterizer/skia/skia/skia.gyp
@@ -56,7 +56,7 @@ 'variables': { 'executable_name': 'filter_fuzz_stub', }, - 'includes': [ '../../../../build/deploy.gypi' ], + 'includes': [ '../../../../../starboard/build/deploy.gypi' ], }, ], }
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/skia_cobalt.gypi b/src/cobalt/renderer/rasterizer/skia/skia/skia_cobalt.gypi index 4acd051..93717ca 100644 --- a/src/cobalt/renderer/rasterizer/skia/skia/skia_cobalt.gypi +++ b/src/cobalt/renderer/rasterizer/skia/skia/skia_cobalt.gypi
@@ -18,6 +18,8 @@ 'sources': [ 'config/SkUserConfig.h', 'egl/src/gpu/cobalt/GrGpuFactory.cc', + 'src/effects/SkNV122RGBShader.cc', + 'src/effects/SkNV122RGBShader.h', 'src/effects/SkYUV2RGBShader.cc', 'src/effects/SkYUV2RGBShader.h', 'src/google_logging.cc',
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.cc b/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.cc new file mode 100644 index 0000000..712252e --- /dev/null +++ b/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.cc
@@ -0,0 +1,245 @@ +/* + * 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/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.h" + +#include <algorithm> + +#include "base/logging.h" +#include "third_party/skia/include/core/SkColorPriv.h" +#include "third_party/skia/include/core/SkShader.h" +#include "third_party/skia/include/core/SkString.h" +#include "third_party/skia/include/core/SkWriteBuffer.h" +#include "third_party/skia/src/core/SkReadBuffer.h" +#include "third_party/skia/src/gpu/effects/GrYUVtoRGBEffect.h" + +SkNV122RGBShader::SkNV122RGBShader(SkYUVColorSpace color_space, + const SkBitmap& y_bitmap, + const SkMatrix& y_matrix, + const SkBitmap& uv_bitmap, + const SkMatrix& uv_matrix) + : color_space_(color_space), + y_bitmap_(y_bitmap), + y_matrix_(y_matrix), + uv_bitmap_(uv_bitmap), + uv_matrix_(uv_matrix) { + DCHECK(!y_bitmap_.isNull()); + DCHECK(!uv_bitmap_.isNull()); + InitializeShaders(); +} + +void SkNV122RGBShader::InitializeShaders() { + y_shader_ = + SkShader::CreateBitmapShader(y_bitmap_, SkShader::kClamp_TileMode, + SkShader::kClamp_TileMode, &y_matrix_); + DCHECK(y_shader_); + + uv_shader_ = + SkShader::CreateBitmapShader(uv_bitmap_, SkShader::kClamp_TileMode, + SkShader::kClamp_TileMode, &uv_matrix_); + DCHECK(uv_shader_); +} + +#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING +SkNV122RGBShader::SkNV122RGBShader(SkReadBuffer& buffer) : INHERITED(buffer) { + color_space_ = static_cast<SkYUVColorSpace>(buffer.readInt()); + buffer.readBitmap(&y_bitmap_); + buffer.readMatrix(&y_matrix_); + buffer.readBitmap(&uv_bitmap_); + buffer.readMatrix(&uv_matrix_); + InitializeShaders(); +} +#endif + +SkNV122RGBShader::~SkNV122RGBShader() { + y_shader_->unref(); + uv_shader_->unref(); +} + +SkFlattenable* SkNV122RGBShader::CreateProc(SkReadBuffer& buffer) { + SkYUVColorSpace color_space = static_cast<SkYUVColorSpace>(buffer.readInt()); + + SkBitmap y_bitmap; + if (!buffer.readBitmap(&y_bitmap)) { + return NULL; + } + y_bitmap.setImmutable(); + SkMatrix y_matrix; + buffer.readMatrix(&y_matrix); + + SkBitmap uv_bitmap; + if (!buffer.readBitmap(&uv_bitmap)) { + return NULL; + } + uv_bitmap.setImmutable(); + SkMatrix uv_matrix; + buffer.readMatrix(&uv_matrix); + + return SkNEW_ARGS(SkNV122RGBShader, + (color_space, y_bitmap, y_matrix, uv_bitmap, uv_matrix)); +} + +void SkNV122RGBShader::flatten(SkWriteBuffer& buffer) const { + buffer.writeInt(color_space_); + buffer.writeBitmap(y_bitmap_); + buffer.writeMatrix(y_matrix_); + buffer.writeBitmap(uv_bitmap_); + buffer.writeMatrix(uv_matrix_); +} + +uint32_t SkNV122RGBShader::NV122RGBShaderContext::getFlags() const { return 0; } + +SkShader::Context* SkNV122RGBShader::onCreateContext(const ContextRec& rec, + void* storage) const { + char* shaderContextStorage = + static_cast<char*>(storage) + sizeof(NV122RGBShaderContext); + SkShader::Context* y_shader_context = + y_shader_->createContext(rec, shaderContextStorage); + DCHECK(y_shader_context); + shaderContextStorage += y_shader_->contextSize(); + SkShader::Context* uv_shader_context = + uv_shader_->createContext(rec, shaderContextStorage); + DCHECK(uv_shader_context); + + return SkNEW_PLACEMENT_ARGS( + storage, NV122RGBShaderContext, + (color_space_, *this, y_shader_context, uv_shader_context, rec)); +} + +size_t SkNV122RGBShader::contextSize() const { + return sizeof(NV122RGBShaderContext) + y_shader_->contextSize() + + uv_shader_->contextSize(); +} + +SkNV122RGBShader::NV122RGBShaderContext::NV122RGBShaderContext( + SkYUVColorSpace color_space, const SkNV122RGBShader& yuv2rgb_shader, + SkShader::Context* y_shader_context, SkShader::Context* uv_shader_context, + const ContextRec& rec) + : INHERITED(yuv2rgb_shader, rec), + color_space_(color_space), + y_shader_context_(y_shader_context), + uv_shader_context_(uv_shader_context) {} + +SkNV122RGBShader::NV122RGBShaderContext::~NV122RGBShaderContext() { + y_shader_context_->~Context(); + uv_shader_context_->~Context(); +} + +void SkNV122RGBShader::NV122RGBShaderContext::shadeSpan(int x, int y, + SkPMColor result[], + int count) { + static const int kPixelCountPerSpan = 64; + SkPMColor y_values[kPixelCountPerSpan]; + SkPMColor uv_values[kPixelCountPerSpan]; + + DCHECK_EQ(kRec709_SkYUVColorSpace, color_space_) + << "Currently we only support the BT.709 YUV colorspace."; + + do { + int count_in_chunk = + count > kPixelCountPerSpan ? kPixelCountPerSpan : count; + + y_shader_context_->shadeSpan(x, y, y_values, count_in_chunk); + uv_shader_context_->shadeSpan(x, y, uv_values, count_in_chunk); + + for (int i = 0; i < count_in_chunk; ++i) { + int32_t y_value = SkColorGetA(y_values[i]) - 16; + int32_t u_value = SkColorGetB(uv_values[i]) - 128; + int32_t v_value = SkColorGetA(uv_values[i]) - 128; + + const float kA = 1.164f; + const float kB = -0.213f; + const float kC = 2.112f; + const float kD = 1.793f; + const float kE = -0.533f; + int32_t r_unclamped = static_cast<int32_t>(kA * y_value + kD * v_value); + int32_t g_unclamped = + static_cast<int32_t>(kA * y_value + kB * u_value + kE * v_value); + int32_t b_unclamped = static_cast<int32_t>(kA * y_value + kC * u_value); + + int32_t r_clamped = + std::min<int32_t>(255, std::max<int32_t>(0, r_unclamped)); + int32_t g_clamped = + std::min<int32_t>(255, std::max<int32_t>(0, g_unclamped)); + int32_t b_clamped = + std::min<int32_t>(255, std::max<int32_t>(0, b_unclamped)); + + result[i] = SkPackARGB32NoCheck(255, r_clamped, g_clamped, b_clamped); + } + result += count_in_chunk; + x += count_in_chunk; + count -= count_in_chunk; + } while (count > 0); +} + +void SkNV122RGBShader::NV122RGBShaderContext::shadeSpan16(int x, int y, + uint16_t result[], + int count) { + NOTREACHED(); +} + +#ifndef SK_IGNORE_TO_STRING +void SkNV122RGBShader::toString(SkString* str) const { + str->append("SkNV122RGBShader: ("); + + str->append("Y Shader: "); + y_shader_->toString(str); + str->append("UV Shader: "); + uv_shader_->toString(str); + + this->INHERITED::toString(str); + + str->append(")"); +} +#endif // SK_IGNORE_TO_STRING + +#if SK_SUPPORT_GPU + +bool SkNV122RGBShader::asFragmentProcessor(GrContext*, const SkPaint& paint, + const SkMatrix* localMatrix, + GrColor*, + GrFragmentProcessor** fp) const { + // Code snippet taken from SkBitmapProcShader::asFragmentProcessor(). + SkMatrix matrix; + matrix.setIDiv(y_bitmap_.width(), y_bitmap_.height()); + + SkMatrix lmInverse; + if (!y_shader_->getLocalMatrix().invert(&lmInverse)) { + return false; + } + if (localMatrix) { + SkMatrix inv; + if (!localMatrix->invert(&inv)) { + return false; + } + lmInverse.postConcat(inv); + } + matrix.preConcat(lmInverse); + + GrTextureParams::FilterMode filter_mode = + paint.getFilterLevel() == SkPaint::kNone_FilterLevel + ? GrTextureParams::kNone_FilterMode + : GrTextureParams::kBilerp_FilterMode; + GrTextureParams texture_params; + texture_params.setFilterMode(filter_mode); + + *fp = GrYUVtoRGBEffect::Create(y_bitmap_.getTexture(), + uv_bitmap_.getTexture(), NULL, matrix, + texture_params, kRec709_SkYUVColorSpace, true); + return true; +} + +#endif // SK_SUPPORT_GPU
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.h b/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.h new file mode 100644 index 0000000..f7d6545 --- /dev/null +++ b/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.h
@@ -0,0 +1,93 @@ +/* + * 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_RENDERER_RASTERIZER_SKIA_SKIA_SRC_EFFECTS_SKNV122RGBSHADER_H_ +#define COBALT_RENDERER_RASTERIZER_SKIA_SKIA_SRC_EFFECTS_SKNV122RGBSHADER_H_ + +#include "SkShader.h" + +class SkNV122RGBShader : public SkShader { + public: + SkNV122RGBShader(SkYUVColorSpace color_space, const SkBitmap& y_bitmap, + const SkMatrix& y_matrix, const SkBitmap& uv_bitmap, + const SkMatrix& uv_matrix); + virtual ~SkNV122RGBShader(); + + virtual size_t contextSize() const SK_OVERRIDE; + + class NV122RGBShaderContext : public SkShader::Context { + public: + // Takes ownership of shaderContext and calls its destructor. + NV122RGBShaderContext(SkYUVColorSpace color_space, + const SkNV122RGBShader& yuv2rgb_shader, + SkShader::Context* y_shader_context, + SkShader::Context* uv_shader_context, + const ContextRec& rec); + virtual ~NV122RGBShaderContext(); + + virtual uint32_t getFlags() const SK_OVERRIDE; + + virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE; + virtual void shadeSpan16(int x, int y, uint16_t[], int count) SK_OVERRIDE; + + virtual void set3DMask(const SkMask* mask) SK_OVERRIDE { + // forward to our proxy + y_shader_context_->set3DMask(mask); + uv_shader_context_->set3DMask(mask); + } + + private: + SkYUVColorSpace color_space_; + + SkShader::Context* y_shader_context_; + SkShader::Context* uv_shader_context_; + + typedef SkShader::Context INHERITED; + }; + +#if SK_SUPPORT_GPU + bool asFragmentProcessor(GrContext*, const SkPaint&, const SkMatrix*, + GrColor*, GrFragmentProcessor**) const SK_OVERRIDE; +#endif + + SK_TO_STRING_OVERRIDE() + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkNV122RGBShader) + + protected: +#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING + explicit SkNV122RGBShader(SkReadBuffer&); +#endif + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; + virtual Context* onCreateContext(const ContextRec&, + void* storage) const SK_OVERRIDE; + + private: + void InitializeShaders(); + + SkYUVColorSpace color_space_; + + SkBitmap y_bitmap_; + SkMatrix y_matrix_; + SkShader* y_shader_; + + SkBitmap uv_bitmap_; + SkMatrix uv_matrix_; + SkShader* uv_shader_; + + typedef SkShader INHERITED; +}; + +#endif // COBALT_RENDERER_RASTERIZER_SKIA_SKIA_SRC_EFFECTS_SKNV122RGBSHADER_H_
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkYUV2RGBShader.cc b/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkYUV2RGBShader.cc index 4635426..aaf6bbe 100644 --- a/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkYUV2RGBShader.cc +++ b/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkYUV2RGBShader.cc
@@ -35,6 +35,9 @@ y_bitmap_(y_bitmap), y_matrix_(y_matrix), u_bitmap_(u_bitmap), u_matrix_(u_matrix), v_bitmap_(v_bitmap), v_matrix_(v_matrix) { + DCHECK(!y_bitmap_.isNull()); + DCHECK(!u_bitmap_.isNull()); + DCHECK(!v_bitmap_.isNull()); InitializeShaders(); } @@ -42,14 +45,17 @@ y_shader_ = SkShader::CreateBitmapShader( y_bitmap_, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &y_matrix_); + DCHECK(y_shader_); u_shader_ = SkShader::CreateBitmapShader( u_bitmap_, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &u_matrix_); + DCHECK(u_shader_); v_shader_ = SkShader::CreateBitmapShader( v_bitmap_, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &v_matrix_); + DCHECK(v_shader_); } #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING @@ -124,12 +130,15 @@ static_cast<char*>(storage) + sizeof(YUV2RGBShaderContext); SkShader::Context* y_shader_context = y_shader_->createContext(rec, shaderContextStorage); + DCHECK(y_shader_context); shaderContextStorage += y_shader_->contextSize(); SkShader::Context* u_shader_context = u_shader_->createContext(rec, shaderContextStorage); + DCHECK(u_shader_context); shaderContextStorage += u_shader_->contextSize(); SkShader::Context* v_shader_context = v_shader_->createContext(rec, shaderContextStorage); + DCHECK(v_shader_context); return SkNEW_PLACEMENT_ARGS( storage, YUV2RGBShaderContext, @@ -262,7 +271,7 @@ *fp = GrYUVtoRGBEffect::Create(y_bitmap_.getTexture(), u_bitmap_.getTexture(), v_bitmap_.getTexture(), matrix, texture_params, - kRec709_SkYUVColorSpace); + kRec709_SkYUVColorSpace, false); return true; }
diff --git a/src/cobalt/renderer/rasterizer/skia/software_image.cc b/src/cobalt/renderer/rasterizer/skia/software_image.cc index 3b87f8d..5f68cde 100644 --- a/src/cobalt/renderer/rasterizer/skia/software_image.cc +++ b/src/cobalt/renderer/rasterizer/skia/software_image.cc
@@ -24,87 +24,115 @@ namespace rasterizer { namespace skia { -SkiaSoftwareImageData::SkiaSoftwareImageData( - const math::Size& size, render_tree::PixelFormat pixel_format, - render_tree::AlphaFormat alpha_format) +SoftwareImageData::SoftwareImageData(const math::Size& size, + render_tree::PixelFormat pixel_format, + render_tree::AlphaFormat alpha_format) : descriptor_(size, pixel_format, alpha_format, size.width() * render_tree::BytesPerPixel(pixel_format)), pixel_data_(new uint8_t[size.height() * descriptor_.pitch_in_bytes]) {} -const render_tree::ImageDataDescriptor& SkiaSoftwareImageData::GetDescriptor() +const render_tree::ImageDataDescriptor& SoftwareImageData::GetDescriptor() const { return descriptor_; } -uint8_t* SkiaSoftwareImageData::GetMemory() { return pixel_data_.get(); } +uint8_t* SoftwareImageData::GetMemory() { return pixel_data_.get(); } -scoped_array<uint8_t> SkiaSoftwareImageData::PassPixelData() { +scoped_array<uint8_t> SoftwareImageData::PassPixelData() { return pixel_data_.Pass(); } -SkiaSoftwareImage::SkiaSoftwareImage( - scoped_ptr<SkiaSoftwareImageData> source_data) { +SoftwareImage::SoftwareImage(scoped_ptr<SoftwareImageData> source_data) { owned_pixel_data_ = source_data->PassPixelData(); Initialize(owned_pixel_data_.get(), source_data->GetDescriptor()); } -SkiaSoftwareImage::SkiaSoftwareImage( +SoftwareImage::SoftwareImage( uint8_t* source_data, const render_tree::ImageDataDescriptor& descriptor) { Initialize(source_data, descriptor); } -void SkiaSoftwareImage::Initialize( +namespace { +// Converts UV8 texture data to an ARGB SkBitmap where the original U channel is +// found in the B channel, the original V channel is found in the A channel, and +// the R and G channels are zeroed out. +void ConvertUV8ToARGBSkBitmap( + uint8_t* source_data, const render_tree::ImageDataDescriptor& descriptor, + SkBitmap* bitmap) { + bitmap->allocN32Pixels(descriptor.size.width(), descriptor.size.height()); + int row_pixels_dest = bitmap->rowBytes() / bitmap->bytesPerPixel(); + + bitmap->lockPixels(); + uint8_t* current_src = source_data; + SkColor* current_dest = static_cast<SkColor*>(bitmap->getPixels()); + for (int row = 0; row < descriptor.size.height(); ++row) { + for (int column = 0; column < descriptor.size.width(); ++column) { + current_dest[column] = SkColorSetARGBMacro( + current_src[column * 2 + 1], 0, 0, current_src[column * 2 + 0]); + } + current_dest += row_pixels_dest; + current_src += descriptor.pitch_in_bytes; + } + bitmap->unlockPixels(); +} +} // namespace + +void SoftwareImage::Initialize( uint8_t* source_data, const render_tree::ImageDataDescriptor& descriptor) { SkAlphaType skia_alpha_format = RenderTreeAlphaFormatToSkia(descriptor.alpha_format); DCHECK_EQ(kPremul_SkAlphaType, skia_alpha_format); - // Convert our incoming pixel data from unpremultiplied alpha to - // premultiplied alpha format, which is what Skia expects. - SkImageInfo premul_image_info = - SkImageInfo::Make(descriptor.size.width(), descriptor.size.height(), - RenderTreeSurfaceFormatToSkia(descriptor.pixel_format), - skia_alpha_format); + size_ = descriptor.size; + if (descriptor.pixel_format == render_tree::kPixelFormatUV8) { + // Convert UV8 to ARGB because Skia does not support any two-channel + // formats. This of course is not efficient, but efficiency in the software + // renderer is not as important as completeness and correctness. + ConvertUV8ToARGBSkBitmap(source_data, descriptor, &bitmap_); + } else { // Check that the incoming pixel data is indeed in premultiplied alpha // format. #if !defined(NDEBUG) - SkiaImage::DCheckForPremultipliedAlpha(descriptor.size, - descriptor.pitch_in_bytes, - descriptor.pixel_format, source_data); + Image::DCheckForPremultipliedAlpha(descriptor.size, + descriptor.pitch_in_bytes, + descriptor.pixel_format, source_data); #endif - bitmap_.installPixels(premul_image_info, source_data, - descriptor.pitch_in_bytes); - - size_ = descriptor.size; + // Convert our incoming pixel data from unpremultiplied alpha to + // premultiplied alpha format, which is what Skia expects. + SkImageInfo premul_image_info = SkImageInfo::Make( + descriptor.size.width(), descriptor.size.height(), + RenderTreeSurfaceFormatToSkia(descriptor.pixel_format), + skia_alpha_format); + bitmap_.installPixels(premul_image_info, source_data, + descriptor.pitch_in_bytes); + } } -SkiaSoftwareRawImageMemory::SkiaSoftwareRawImageMemory(size_t size_in_bytes, - size_t alignment) +SoftwareRawImageMemory::SoftwareRawImageMemory(size_t size_in_bytes, + size_t alignment) : size_in_bytes_(size_in_bytes), pixel_data_( static_cast<uint8_t*>(base::AlignedAlloc(size_in_bytes, alignment))) { } -size_t SkiaSoftwareRawImageMemory::GetSizeInBytes() const { - return size_in_bytes_; -} +size_t SoftwareRawImageMemory::GetSizeInBytes() const { return size_in_bytes_; } -uint8_t* SkiaSoftwareRawImageMemory::GetMemory() { return pixel_data_.get(); } +uint8_t* SoftwareRawImageMemory::GetMemory() { return pixel_data_.get(); } scoped_ptr_malloc<uint8_t, base::ScopedPtrAlignedFree> -SkiaSoftwareRawImageMemory::PassPixelData() { +SoftwareRawImageMemory::PassPixelData() { return pixel_data_.Pass(); } -SkiaSoftwareMultiPlaneImage::SkiaSoftwareMultiPlaneImage( - scoped_ptr<SkiaSoftwareRawImageMemory> raw_image_memory, +SoftwareMultiPlaneImage::SoftwareMultiPlaneImage( + scoped_ptr<SoftwareRawImageMemory> raw_image_memory, const render_tree::MultiPlaneImageDataDescriptor& descriptor) : size_(descriptor.GetPlaneDescriptor(0).size), format_(descriptor.image_format()), owned_pixel_data_(raw_image_memory->PassPixelData()) { for (int i = 0; i < descriptor.num_planes(); ++i) { - planes_[i] = new SkiaSoftwareImage( + planes_[i] = new SoftwareImage( owned_pixel_data_.get() + descriptor.GetPlaneOffset(i), descriptor.GetPlaneDescriptor(i)); }
diff --git a/src/cobalt/renderer/rasterizer/skia/software_image.h b/src/cobalt/renderer/rasterizer/skia/software_image.h index f40a813..37bd1ad 100644 --- a/src/cobalt/renderer/rasterizer/skia/software_image.h +++ b/src/cobalt/renderer/rasterizer/skia/software_image.h
@@ -29,11 +29,11 @@ namespace rasterizer { namespace skia { -class SkiaSoftwareImageData : public render_tree::ImageData { +class SoftwareImageData : public render_tree::ImageData { public: - SkiaSoftwareImageData(const math::Size& size, - render_tree::PixelFormat pixel_format, - render_tree::AlphaFormat alpha_format); + SoftwareImageData(const math::Size& size, + render_tree::PixelFormat pixel_format, + render_tree::AlphaFormat alpha_format); const render_tree::ImageDataDescriptor& GetDescriptor() const OVERRIDE; uint8_t* GetMemory() OVERRIDE; @@ -45,12 +45,11 @@ scoped_array<uint8_t> pixel_data_; }; -class SkiaSoftwareImage : public SkiaSinglePlaneImage { +class SoftwareImage : public SinglePlaneImage { public: - explicit SkiaSoftwareImage( - scoped_ptr<SkiaSoftwareImageData> source_data); - SkiaSoftwareImage(uint8_t* source_data, - const render_tree::ImageDataDescriptor& descriptor); + explicit SoftwareImage(scoped_ptr<SoftwareImageData> source_data); + SoftwareImage(uint8_t* source_data, + const render_tree::ImageDataDescriptor& descriptor); const math::Size& GetSize() const OVERRIDE { return size_; } @@ -67,9 +66,9 @@ math::Size size_; }; -class SkiaSoftwareRawImageMemory : public render_tree::RawImageMemory { +class SoftwareRawImageMemory : public render_tree::RawImageMemory { public: - SkiaSoftwareRawImageMemory(size_t size_in_bytes, size_t alignment); + SoftwareRawImageMemory(size_t size_in_bytes, size_t alignment); size_t GetSizeInBytes() const OVERRIDE; uint8_t* GetMemory() OVERRIDE; @@ -81,10 +80,10 @@ scoped_ptr_malloc<uint8_t, base::ScopedPtrAlignedFree> pixel_data_; }; -class SkiaSoftwareMultiPlaneImage : public SkiaMultiPlaneImage { +class SoftwareMultiPlaneImage : public MultiPlaneImage { public: - SkiaSoftwareMultiPlaneImage( - scoped_ptr<SkiaSoftwareRawImageMemory> raw_image_memory, + SoftwareMultiPlaneImage( + scoped_ptr<SoftwareRawImageMemory> raw_image_memory, const render_tree::MultiPlaneImageDataDescriptor& descriptor); const math::Size& GetSize() const OVERRIDE { return size_; } @@ -104,7 +103,7 @@ scoped_ptr_malloc<uint8_t, base::ScopedPtrAlignedFree> owned_pixel_data_; - scoped_refptr<SkiaSoftwareImage> + scoped_refptr<SoftwareImage> planes_[render_tree::MultiPlaneImageDataDescriptor::kMaxPlanes]; };
diff --git a/src/cobalt/renderer/rasterizer/skia/software_rasterizer.cc b/src/cobalt/renderer/rasterizer/skia/software_rasterizer.cc index 040cc37..208d179 100644 --- a/src/cobalt/renderer/rasterizer/skia/software_rasterizer.cc +++ b/src/cobalt/renderer/rasterizer/skia/software_rasterizer.cc
@@ -37,8 +37,7 @@ SkImageInfo::MakeN32Premul(size.width(), size.height())); } -class SoftwareScratchSurface - : public SkiaRenderTreeNodeVisitor::ScratchSurface { +class SoftwareScratchSurface : public RenderTreeNodeVisitor::ScratchSurface { public: explicit SoftwareScratchSurface(const math::Size& size) : surface_(CreateScratchSkSurface(size)) {} @@ -48,11 +47,11 @@ SkAutoTUnref<SkSurface> surface_; }; -scoped_ptr<SkiaRenderTreeNodeVisitor::ScratchSurface> CreateScratchSurface( +scoped_ptr<RenderTreeNodeVisitor::ScratchSurface> CreateScratchSurface( const math::Size& size) { TRACE_EVENT2("cobalt::renderer", "CreateScratchSurface()", "width", size.width(), "height", size.height()); - return scoped_ptr<SkiaRenderTreeNodeVisitor::ScratchSurface>( + return scoped_ptr<RenderTreeNodeVisitor::ScratchSurface>( new SoftwareScratchSurface(size)); } @@ -60,7 +59,7 @@ } // namespace -class SkiaSoftwareRasterizer::Impl { +class SoftwareRasterizer::Impl { public: explicit Impl(int surface_cache_size); @@ -78,10 +77,9 @@ base::optional<common::SurfaceCache> surface_cache_; }; -SkiaSoftwareRasterizer::Impl::Impl(int surface_cache_size) - : resource_provider_(new SkiaSoftwareResourceProvider()) { - TRACE_EVENT0("cobalt::renderer", - "SkiaSoftwareRasterizer::SkiaSoftwareRasterizer()"); +SoftwareRasterizer::Impl::Impl(int surface_cache_size) + : resource_provider_(new SoftwareResourceProvider()) { + TRACE_EVENT0("cobalt::renderer", "SoftwareRasterizer::SoftwareRasterizer()"); if (surface_cache_size > 0) { // Software surfaces don't have size limits, so this is set to an arbitrary @@ -96,11 +94,11 @@ } } -void SkiaSoftwareRasterizer::Impl::Submit( +void SoftwareRasterizer::Impl::Submit( const scoped_refptr<render_tree::Node>& render_tree, SkCanvas* render_target) { TRACE_EVENT0("cobalt::renderer", "Rasterizer::Submit()"); - TRACE_EVENT0("cobalt::renderer", "SkiaSoftwareRasterizer::Submit()"); + TRACE_EVENT0("cobalt::renderer", "SoftwareRasterizer::Submit()"); // Update our surface cache to do per-frame calculations such as deciding // which render tree nodes are candidates for caching in this upcoming @@ -114,9 +112,9 @@ // Create the rasterizer and setup its render target to the bitmap we have // just created above. - SkiaRenderTreeNodeVisitor::CreateScratchSurfaceFunction + RenderTreeNodeVisitor::CreateScratchSurfaceFunction create_scratch_surface_function = base::Bind(&CreateScratchSurface); - SkiaRenderTreeNodeVisitor visitor( + RenderTreeNodeVisitor visitor( render_target, &create_scratch_surface_function, surface_cache_delegate_ ? &surface_cache_delegate_.value() : NULL, surface_cache_ ? &surface_cache_.value() : NULL); @@ -127,27 +125,25 @@ } } -render_tree::ResourceProvider* -SkiaSoftwareRasterizer::Impl::GetResourceProvider() { - TRACE_EVENT0("cobalt::renderer", - "SkiaSoftwareRasterizer::GetResourceProvider()"); +render_tree::ResourceProvider* SoftwareRasterizer::Impl::GetResourceProvider() { + TRACE_EVENT0("cobalt::renderer", "SoftwareRasterizer::GetResourceProvider()"); return resource_provider_.get(); } -SkiaSoftwareRasterizer::SkiaSoftwareRasterizer(int surface_cache_size) +SoftwareRasterizer::SoftwareRasterizer(int surface_cache_size) : impl_(new Impl(surface_cache_size)) {} -SkiaSoftwareRasterizer::~SkiaSoftwareRasterizer() {} +SoftwareRasterizer::~SoftwareRasterizer() {} // Consume the render tree and output the results to the render target passed // into the constructor. -void SkiaSoftwareRasterizer::Submit( +void SoftwareRasterizer::Submit( const scoped_refptr<render_tree::Node>& render_tree, SkCanvas* render_target) { impl_->Submit(render_tree, render_target); } -render_tree::ResourceProvider* SkiaSoftwareRasterizer::GetResourceProvider() { +render_tree::ResourceProvider* SoftwareRasterizer::GetResourceProvider() { return impl_->GetResourceProvider(); }
diff --git a/src/cobalt/renderer/rasterizer/skia/software_rasterizer.h b/src/cobalt/renderer/rasterizer/skia/software_rasterizer.h index 6d8f24e..7ecaf06 100644 --- a/src/cobalt/renderer/rasterizer/skia/software_rasterizer.h +++ b/src/cobalt/renderer/rasterizer/skia/software_rasterizer.h
@@ -33,12 +33,12 @@ // it can be used within a wrapper class that does implement it. // This class focuses on rendering a render tree to a SkCanvas object, // so a platform-specific rasterizer::Rasterizer implementation could wrap -// this object and after calling SkiaSoftwareRasterizer::Submit(), the wrapper +// this object and after calling SoftwareRasterizer::Submit(), the wrapper // class can send the results to a display or render target. -class SkiaSoftwareRasterizer { +class SoftwareRasterizer { public: - explicit SkiaSoftwareRasterizer(int surface_cache_size); - ~SkiaSoftwareRasterizer(); + explicit SoftwareRasterizer(int surface_cache_size); + ~SoftwareRasterizer(); // Consume the render tree and output the results to the render target passed // into the constructor.
diff --git a/src/cobalt/renderer/rasterizer/skia/software_resource_provider.cc b/src/cobalt/renderer/rasterizer/skia/software_resource_provider.cc index 5277d6b..abe46c6 100644 --- a/src/cobalt/renderer/rasterizer/skia/software_resource_provider.cc +++ b/src/cobalt/renderer/rasterizer/skia/software_resource_provider.cc
@@ -37,80 +37,76 @@ namespace rasterizer { namespace skia { -bool SkiaSoftwareResourceProvider::PixelFormatSupported( +bool SoftwareResourceProvider::PixelFormatSupported( render_tree::PixelFormat pixel_format) { return RenderTreeSurfaceFormatToSkia(pixel_format) == kN32_SkColorType; } -bool SkiaSoftwareResourceProvider::AlphaFormatSupported( +bool SoftwareResourceProvider::AlphaFormatSupported( render_tree::AlphaFormat alpha_format) { return alpha_format == render_tree::kAlphaFormatPremultiplied; } -scoped_ptr<ImageData> SkiaSoftwareResourceProvider::AllocateImageData( +scoped_ptr<ImageData> SoftwareResourceProvider::AllocateImageData( const math::Size& size, render_tree::PixelFormat pixel_format, render_tree::AlphaFormat alpha_format) { TRACE_EVENT0("cobalt::renderer", - "SkiaSoftwareResourceProvider::AllocateImageData()"); + "SoftwareResourceProvider::AllocateImageData()"); DCHECK(PixelFormatSupported(pixel_format)); DCHECK(AlphaFormatSupported(alpha_format)); return scoped_ptr<ImageData>( - new SkiaSoftwareImageData(size, pixel_format, alpha_format)); + new SoftwareImageData(size, pixel_format, alpha_format)); } -scoped_refptr<render_tree::Image> SkiaSoftwareResourceProvider::CreateImage( +scoped_refptr<render_tree::Image> SoftwareResourceProvider::CreateImage( scoped_ptr<ImageData> source_data) { - TRACE_EVENT0("cobalt::renderer", - "SkiaSoftwareResourceProvider::CreateImage()"); - scoped_ptr<SkiaSoftwareImageData> skia_source_data( - base::polymorphic_downcast<SkiaSoftwareImageData*>( - source_data.release())); + TRACE_EVENT0("cobalt::renderer", "SoftwareResourceProvider::CreateImage()"); + scoped_ptr<SoftwareImageData> skia_source_data( + base::polymorphic_downcast<SoftwareImageData*>(source_data.release())); return scoped_refptr<render_tree::Image>( - new SkiaSoftwareImage(skia_source_data.Pass())); + new SoftwareImage(skia_source_data.Pass())); } scoped_ptr<render_tree::RawImageMemory> -SkiaSoftwareResourceProvider::AllocateRawImageMemory(size_t size_in_bytes, - size_t alignment) { +SoftwareResourceProvider::AllocateRawImageMemory(size_t size_in_bytes, + size_t alignment) { TRACE_EVENT0("cobalt::renderer", - "SkiaSoftwareResourceProvider::AllocateRawImageMemory()"); + "SoftwareResourceProvider::AllocateRawImageMemory()"); return scoped_ptr<render_tree::RawImageMemory>( - new SkiaSoftwareRawImageMemory(size_in_bytes, alignment)); + new SoftwareRawImageMemory(size_in_bytes, alignment)); } scoped_refptr<render_tree::Image> -SkiaSoftwareResourceProvider::CreateMultiPlaneImageFromRawMemory( +SoftwareResourceProvider::CreateMultiPlaneImageFromRawMemory( scoped_ptr<render_tree::RawImageMemory> raw_image_memory, const render_tree::MultiPlaneImageDataDescriptor& descriptor) { TRACE_EVENT0( "cobalt::renderer", - "SkiaSoftwareResourceProvider::CreateMultiPlaneImageFromRawMemory()"); + "SoftwareResourceProvider::CreateMultiPlaneImageFromRawMemory()"); - scoped_ptr<SkiaSoftwareRawImageMemory> skia_software_raw_image_memory( - base::polymorphic_downcast<SkiaSoftwareRawImageMemory*>( + scoped_ptr<SoftwareRawImageMemory> skia_software_raw_image_memory( + base::polymorphic_downcast<SoftwareRawImageMemory*>( raw_image_memory.release())); - return make_scoped_refptr(new SkiaSoftwareMultiPlaneImage( + return make_scoped_refptr(new SoftwareMultiPlaneImage( skia_software_raw_image_memory.Pass(), descriptor)); } -bool SkiaSoftwareResourceProvider::HasLocalFontFamily( +bool SoftwareResourceProvider::HasLocalFontFamily( const char* font_family_name) const { TRACE_EVENT0("cobalt::renderer", - "SkiaSoftwareResourceProvider::HasLocalFontFamily()"); + "SoftwareResourceProvider::HasLocalFontFamily()"); SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault()); SkAutoTUnref<SkFontStyleSet> style_set(fm->matchFamily(font_family_name)); return style_set->count() > 0; } -scoped_refptr<render_tree::Typeface> -SkiaSoftwareResourceProvider::GetLocalTypeface( +scoped_refptr<render_tree::Typeface> SoftwareResourceProvider::GetLocalTypeface( const char* font_family_name, render_tree::FontStyle font_style) { - TRACE_EVENT0("cobalt::renderer", - "SkiaSoftwareResourceProvider::GetLocalFont()"); + TRACE_EVENT0("cobalt::renderer", "SoftwareResourceProvider::GetLocalFont()"); SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault()); SkAutoTUnref<SkTypeface> typeface(fm->matchFamilyStyle( @@ -119,11 +115,11 @@ } scoped_refptr<render_tree::Typeface> -SkiaSoftwareResourceProvider::GetCharacterFallbackTypeface( +SoftwareResourceProvider::GetCharacterFallbackTypeface( int32 character, render_tree::FontStyle font_style, const std::string& language) { TRACE_EVENT0("cobalt::renderer", - "SkiaSoftwareResourceProvider::GetCharacterFallbackTypeface()"); + "SoftwareResourceProvider::GetCharacterFallbackTypeface()"); SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault()); SkAutoTUnref<SkTypeface> typeface( @@ -133,11 +129,11 @@ } scoped_refptr<render_tree::Typeface> -SkiaSoftwareResourceProvider::CreateTypefaceFromRawData( +SoftwareResourceProvider::CreateTypefaceFromRawData( scoped_ptr<render_tree::ResourceProvider::RawTypefaceDataVector> raw_data, std::string* error_string) { TRACE_EVENT0("cobalt::renderer", - "SkiaSoftwareResourceProvider::CreateFontFromRawData()"); + "SoftwareResourceProvider::CreateFontFromRawData()"); if (raw_data == NULL) { *error_string = "No data to process"; @@ -168,7 +164,7 @@ } scoped_refptr<render_tree::GlyphBuffer> -SkiaSoftwareResourceProvider::CreateGlyphBuffer( +SoftwareResourceProvider::CreateGlyphBuffer( const char16* text_buffer, size_t text_length, const std::string& language, bool is_rtl, render_tree::FontProvider* font_provider) { return text_shaper_.CreateGlyphBuffer(text_buffer, text_length, language, @@ -176,13 +172,13 @@ } scoped_refptr<render_tree::GlyphBuffer> -SkiaSoftwareResourceProvider::CreateGlyphBuffer( +SoftwareResourceProvider::CreateGlyphBuffer( const std::string& utf8_string, const scoped_refptr<render_tree::Font>& font) { return text_shaper_.CreateGlyphBuffer(utf8_string, font); } -float SkiaSoftwareResourceProvider::GetTextWidth( +float SoftwareResourceProvider::GetTextWidth( const char16* text_buffer, size_t text_length, const std::string& language, bool is_rtl, render_tree::FontProvider* font_provider, render_tree::FontVector* maybe_used_fonts) {
diff --git a/src/cobalt/renderer/rasterizer/skia/software_resource_provider.h b/src/cobalt/renderer/rasterizer/skia/software_resource_provider.h index deb9b79..890f929 100644 --- a/src/cobalt/renderer/rasterizer/skia/software_resource_provider.h +++ b/src/cobalt/renderer/rasterizer/skia/software_resource_provider.h
@@ -29,7 +29,7 @@ // This class must be thread-safe and capable of creating resources that // are to be consumed by this skia software rasterizer. -class SkiaSoftwareResourceProvider : public render_tree::ResourceProvider { +class SoftwareResourceProvider : public render_tree::ResourceProvider { public: bool PixelFormatSupported(render_tree::PixelFormat pixel_format) OVERRIDE; bool AlphaFormatSupported(render_tree::AlphaFormat alpha_format) OVERRIDE;
diff --git a/src/cobalt/renderer/rasterizer/skia/surface_cache_delegate.cc b/src/cobalt/renderer/rasterizer/skia/surface_cache_delegate.cc index 0c293a0..447ab7a 100644 --- a/src/cobalt/renderer/rasterizer/skia/surface_cache_delegate.cc +++ b/src/cobalt/renderer/rasterizer/skia/surface_cache_delegate.cc
@@ -163,11 +163,6 @@ TRACE_EVENT0("cobalt::renderer", "SurfaceCacheDelegate::EndRecording()"); DCHECK(recording_data_); - { - TRACE_EVENT0("cobalt::renderer", "SurfaceCacheDelegate canvas_->flush()"); - canvas_->flush(); - } - set_canvas_function_.Run(recording_data_->original_canvas); canvas_ = recording_data_->original_canvas;
diff --git a/src/cobalt/renderer/rasterizer/skia/text_shaper.cc b/src/cobalt/renderer/rasterizer/skia/text_shaper.cc index b827b56..fab2780 100644 --- a/src/cobalt/renderer/rasterizer/skia/text_shaper.cc +++ b/src/cobalt/renderer/rasterizer/skia/text_shaper.cc
@@ -71,17 +71,17 @@ TextShaper::TextShaper() : local_glyph_array_size_(0), local_text_buffer_size_(0) {} -scoped_refptr<SkiaGlyphBuffer> TextShaper::CreateGlyphBuffer( +scoped_refptr<GlyphBuffer> TextShaper::CreateGlyphBuffer( const char16* text_buffer, size_t text_length, const std::string& language, bool is_rtl, render_tree::FontProvider* font_provider) { math::RectF bounds; SkTextBlobBuilder builder; ShapeText(text_buffer, text_length, language, is_rtl, font_provider, &builder, &bounds, NULL); - return make_scoped_refptr(new SkiaGlyphBuffer(bounds, &builder)); + return make_scoped_refptr(new GlyphBuffer(bounds, &builder)); } -scoped_refptr<SkiaGlyphBuffer> TextShaper::CreateGlyphBuffer( +scoped_refptr<GlyphBuffer> TextShaper::CreateGlyphBuffer( const std::string& utf8_string, const scoped_refptr<render_tree::Font>& font) { string16 utf16_string; @@ -174,7 +174,7 @@ int32 next_character = base::unicode::NormalizeSpaces( base::i18n::UTF16CharIterator(text_buffer, text_length).get()); render_tree::GlyphIndex next_glyph = render_tree::kInvalidGlyphIndex; - SkiaFont* next_font = base::polymorphic_downcast<SkiaFont*>( + Font* next_font = base::polymorphic_downcast<Font*>( font_provider->GetCharacterFont(next_character, &next_glyph).get()); UErrorCode error_code = U_ZERO_ERROR; @@ -189,7 +189,7 @@ unsigned int current_index = 0; unsigned int end_index = text_length; while (current_index < end_index) { - SkiaFont* current_font = next_font; + Font* current_font = next_font; UScriptCode current_script = next_script; // Create an iterator starting at the current index and containing the @@ -219,7 +219,7 @@ continue; } - next_font = base::polymorphic_downcast<SkiaFont*>( + next_font = base::polymorphic_downcast<Font*>( font_provider->GetCharacterFont(next_character, &next_glyph).get()); next_script = uscript_getScript(next_character, &error_code); @@ -398,7 +398,7 @@ } int glyph_count = 0; - SkiaFont* last_font = NULL; + Font* last_font = NULL; // Walk through each character within the run. for (base::i18n::UTF16CharIterator iter(text_buffer, text_length); @@ -422,7 +422,7 @@ } // Look up the font and glyph for the current character. - SkiaFont* current_font = base::polymorphic_downcast<SkiaFont*>( + Font* current_font = base::polymorphic_downcast<Font*>( font_provider->GetCharacterFont(character, &glyph).get()); // If there's a builder (meaning that a glyph buffer is being generated),
diff --git a/src/cobalt/renderer/rasterizer/skia/text_shaper.h b/src/cobalt/renderer/rasterizer/skia/text_shaper.h index 69a936d..a1f6e38 100644 --- a/src/cobalt/renderer/rasterizer/skia/text_shaper.h +++ b/src/cobalt/renderer/rasterizer/skia/text_shaper.h
@@ -43,16 +43,16 @@ class TextShaper { public: // A script run represents a segment of text that can be shaped using a single - // SkiaFont and UScriptCode combination. + // skia::Font and UScriptCode combination. struct ScriptRun { - ScriptRun(SkiaFont* run_font, UScriptCode run_script, + ScriptRun(Font* run_font, UScriptCode run_script, unsigned int run_start_index, unsigned int run_length) : font(run_font), script(run_script), start_index(run_start_index), length(run_length) {} - SkiaFont* font; + Font* font; UScriptCode script; unsigned int start_index; unsigned int length; @@ -69,7 +69,7 @@ // If |is_rtl| is true, then the glyphs in the text buffer will be reversed. // Returns a newly created glyph buffer, which can be used to render the // shaped text. - scoped_refptr<SkiaGlyphBuffer> CreateGlyphBuffer( + scoped_refptr<GlyphBuffer> CreateGlyphBuffer( const char16* text_buffer, size_t text_length, const std::string& language, bool is_rtl, render_tree::FontProvider* font_provider); @@ -78,7 +78,7 @@ // complex, depending on the text provided. // Returns a newly created glyph buffer, which can be used to render the // shaped text. - scoped_refptr<SkiaGlyphBuffer> CreateGlyphBuffer( + scoped_refptr<GlyphBuffer> CreateGlyphBuffer( const std::string& utf8_string, const scoped_refptr<render_tree::Font>& font); @@ -117,9 +117,9 @@ float max_y_; }; - // Shape text relying on SkiaFont and HarfBuzz. + // Shape text relying on skia::Font and HarfBuzz. // Returns the width of the shaped text. - // If |maybe_glyph_buffer| is non-NULL, it is populated with SkiaGlyphBuffer + // If |maybe_glyph_buffer| is non-NULL, it is populated with skia::GlyphBuffer // shaping data. // If |maybe_bounds| is non-NULL, it is populated with the bounds of the // shaped text. @@ -132,7 +132,7 @@ render_tree::FontVector* maybe_used_fonts); // Populate a ScriptRuns object with all runs of text containing a single - // SkiaFont and UScriptCode combination. + // skia::Font and UScriptCode combination. // Returns false if the script run collection fails. bool CollectScriptRuns(const char16* text_buffer, size_t text_length, render_tree::FontProvider* font_provider, @@ -157,7 +157,7 @@ render_tree::FontVector* maybe_used_fonts, float* current_width); - // Shape a simple text run, relying on the SkiaFont objects provided by + // Shape a simple text run, relying on the skia::Font objects provided by // the FontProvider to determine the shaping data. void ShapeSimpleRun(const char16* text_buffer, size_t text_length, render_tree::FontProvider* font_provider,
diff --git a/src/cobalt/renderer/rasterizer/skia/typeface.cc b/src/cobalt/renderer/rasterizer/skia/typeface.cc index 5dea364..bb1d64e 100644 --- a/src/cobalt/renderer/rasterizer/skia/typeface.cc +++ b/src/cobalt/renderer/rasterizer/skia/typeface.cc
@@ -49,7 +49,7 @@ scoped_refptr<render_tree::Font> SkiaTypeface::CreateFontWithSize( float font_size) { - return scoped_refptr<render_tree::Font>(new SkiaFont(this, font_size)); + return scoped_refptr<render_tree::Font>(new Font(this, font_size)); } render_tree::GlyphIndex SkiaTypeface::GetGlyphForCharacter(
diff --git a/src/cobalt/renderer/rasterizer/testdata/TwoPlaneYUVImageSupport-expected.png b/src/cobalt/renderer/rasterizer/testdata/TwoPlaneYUVImageSupport-expected.png new file mode 100644 index 0000000..3df4cdf --- /dev/null +++ b/src/cobalt/renderer/rasterizer/testdata/TwoPlaneYUVImageSupport-expected.png Binary files differ
diff --git a/src/cobalt/renderer/rasterizer/testdata/TwoPlaneYUVImageWithDestSizeDifferentFromImage-expected.png b/src/cobalt/renderer/rasterizer/testdata/TwoPlaneYUVImageWithDestSizeDifferentFromImage-expected.png new file mode 100644 index 0000000..43c761e --- /dev/null +++ b/src/cobalt/renderer/rasterizer/testdata/TwoPlaneYUVImageWithDestSizeDifferentFromImage-expected.png Binary files differ
diff --git a/src/cobalt/renderer/rasterizer/testdata/TwoPlaneYUVImageWithTransform-expected.png b/src/cobalt/renderer/rasterizer/testdata/TwoPlaneYUVImageWithTransform-expected.png new file mode 100644 index 0000000..8f1e33b --- /dev/null +++ b/src/cobalt/renderer/rasterizer/testdata/TwoPlaneYUVImageWithTransform-expected.png Binary files differ
diff --git a/src/cobalt/renderer/rasterizer/testdata/YUV2PlaneImagesAreLinearlyInterpolated-expected.png b/src/cobalt/renderer/rasterizer/testdata/YUV2PlaneImagesAreLinearlyInterpolated-expected.png new file mode 100644 index 0000000..e7d2f2c --- /dev/null +++ b/src/cobalt/renderer/rasterizer/testdata/YUV2PlaneImagesAreLinearlyInterpolated-expected.png Binary files differ
diff --git a/src/cobalt/renderer/rasterizer/testdata/YUVImagesAreLinearlyInterpolated-expected.png b/src/cobalt/renderer/rasterizer/testdata/YUV3PlaneImagesAreLinearlyInterpolated-expected.png similarity index 100% rename from src/cobalt/renderer/rasterizer/testdata/YUVImagesAreLinearlyInterpolated-expected.png rename to src/cobalt/renderer/rasterizer/testdata/YUV3PlaneImagesAreLinearlyInterpolated-expected.png Binary files differ
diff --git a/src/cobalt/renderer/render_tree_pixel_tester.cc b/src/cobalt/renderer/render_tree_pixel_tester.cc index 2ded465..6e6fa75 100644 --- a/src/cobalt/renderer/render_tree_pixel_tester.cc +++ b/src/cobalt/renderer/render_tree_pixel_tester.cc
@@ -71,7 +71,7 @@ // Create the rasterizer using the platform default RenderModule options. RendererModule::Options render_module_options; rasterizer_ = render_module_options.create_rasterizer_function.Run( - graphics_context_.get()); + graphics_context_.get(), render_module_options); } RenderTreePixelTester::~RenderTreePixelTester() {}
diff --git a/src/cobalt/renderer/renderer.gyp b/src/cobalt/renderer/renderer.gyp index ccc8962..657e39e 100644 --- a/src/cobalt/renderer/renderer.gyp +++ b/src/cobalt/renderer/renderer.gyp
@@ -37,6 +37,12 @@ 'copy_font_data.gypi', ], + 'defines': [ + 'COBALT_SKIA_CACHE_SIZE_IN_BYTES=<(skia_cache_size_in_bytes)', + 'COBALT_SCRATCH_SURFACE_CACHE_SIZE_IN_BYTES=<(scratch_surface_cache_size_in_bytes)', + 'COBALT_SURFACE_CACHE_SIZE_IN_BYTES=<(surface_cache_size_in_bytes)', + ], + 'dependencies': [ '<(DEPTH)/cobalt/base/base.gyp:base', '<(DEPTH)/cobalt/math/math.gyp:math', @@ -129,7 +135,7 @@ 'variables': { 'executable_name': 'renderer_test', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, { @@ -155,7 +161,7 @@ 'variables': { 'executable_name': 'renderer_benchmark', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, ], }
diff --git a/src/cobalt/renderer/renderer_module.cc b/src/cobalt/renderer/renderer_module.cc index c5c96fd..5806add 100644 --- a/src/cobalt/renderer/renderer_module.cc +++ b/src/cobalt/renderer/renderer_module.cc
@@ -60,7 +60,8 @@ { TRACE_EVENT0("cobalt::renderer", "new renderer::Pipeline()"); pipeline_ = make_scoped_ptr(new renderer::Pipeline( - base::Bind(options.create_rasterizer_function, graphics_context_.get()), + base::Bind(options.create_rasterizer_function, graphics_context_.get(), + options), display_->GetRenderTarget(), graphics_context_.get())); } }
diff --git a/src/cobalt/renderer/renderer_module.h b/src/cobalt/renderer/renderer_module.h index 3f81dc7..f60a29d 100644 --- a/src/cobalt/renderer/renderer_module.h +++ b/src/cobalt/renderer/renderer_module.h
@@ -34,9 +34,32 @@ Options(); typedef base::Callback<scoped_ptr<rasterizer::Rasterizer>( - backend::GraphicsContext*)> CreateRasterizerCallback; + backend::GraphicsContext*, const Options& options)> + CreateRasterizerCallback; + + // The rasterizer must be created, accessed, and destroyed within the same + // thread, and so to facilitate that a rasterizer factory function must + // be provided here instead of the rasterizer itself. CreateRasterizerCallback create_rasterizer_function; + // Determines the capacity of the scratch surface cache. The scratch + // surface cache facilitates the reuse of temporary offscreen surfaces + // within a single frame. This setting is only relevant when using the + // hardware-accelerated Skia rasterizer. + int scratch_surface_cache_size_in_bytes; + + // Determines the capacity of the skia cache. The Skia cache is maintained + // within Skia and is used to cache the results of complicated effects such + // as shadows, so that Skia draw calls that are used repeatedly across + // frames can be cached into surfaces. This setting is only relevant when + // using the hardware-accelerated Skia rasterizer. + int skia_cache_size_in_bytes; + + // Determines the capacity of the surface cache. The surface cache tracks + // which render tree nodes are being re-used across frames and stores the + // nodes that are most CPU-expensive to render into surfaces. + int surface_cache_size_in_bytes; + private: // Implemented per-platform, and allows each platform to customize // the renderer options.
diff --git a/src/cobalt/renderer/renderer_module_default_options_starboard.cc b/src/cobalt/renderer/renderer_module_default_options_starboard.cc index fdb03b6..50a38f0 100644 --- a/src/cobalt/renderer/renderer_module_default_options_starboard.cc +++ b/src/cobalt/renderer/renderer_module_default_options_starboard.cc
@@ -26,31 +26,34 @@ namespace renderer { namespace { + scoped_ptr<rasterizer::Rasterizer> CreateRasterizer( - backend::GraphicsContext* graphics_context) { - const size_t kSurfaceCacheCapacityInBytes = 0; + backend::GraphicsContext* graphics_context, + const RendererModule::Options& options) { #if COBALT_FORCE_STUB_RASTERIZER return scoped_ptr<rasterizer::Rasterizer>(new rasterizer::stub::Rasterizer()); #else #if SB_HAS(GLES2) #if COBALT_FORCE_SOFTWARE_RASTERIZER return scoped_ptr<rasterizer::Rasterizer>( - new rasterizer::egl::SoftwareRasterizer(graphics_context, - kSurfaceCacheCapacityInBytes)); + new rasterizer::egl::SoftwareRasterizer( + graphics_context, options.surface_cache_size_in_bytes)); #else return scoped_ptr<rasterizer::Rasterizer>( - new rasterizer::skia::SkiaHardwareRasterizer( - graphics_context, kSurfaceCacheCapacityInBytes)); + new rasterizer::skia::HardwareRasterizer( + graphics_context, options.skia_cache_size_in_bytes, + options.scratch_surface_cache_size_in_bytes, + options.surface_cache_size_in_bytes)); #endif // COBALT_FORCE_SOFTWARE_RASTERIZER #elif SB_HAS(BLITTER) #if COBALT_FORCE_SOFTWARE_RASTERIZER return scoped_ptr<rasterizer::Rasterizer>( new rasterizer::blitter::SoftwareRasterizer( - graphics_context, kSurfaceCacheCapacityInBytes)); + graphics_context, options.surface_cache_size_in_bytes)); #else return scoped_ptr<rasterizer::Rasterizer>( new rasterizer::blitter::HardwareRasterizer( - graphics_context, kSurfaceCacheCapacityInBytes)); + graphics_context, options.surface_cache_size_in_bytes)); #endif // COBALT_FORCE_SOFTWARE_RASTERIZER #else #error "Either GLES2 or the Starboard Blitter API must be available." @@ -61,6 +64,12 @@ } // namespace void RendererModule::Options::SetPerPlatformDefaultOptions() { + // Set default options from the current build's Starboard configuration. + surface_cache_size_in_bytes = COBALT_SURFACE_CACHE_SIZE_IN_BYTES; + skia_cache_size_in_bytes = COBALT_SKIA_CACHE_SIZE_IN_BYTES; + scratch_surface_cache_size_in_bytes = + COBALT_SCRATCH_SURFACE_CACHE_SIZE_IN_BYTES; + create_rasterizer_function = base::Bind(&CreateRasterizer); }
diff --git a/src/cobalt/renderer/renderer_module_default_options_win.cc b/src/cobalt/renderer/renderer_module_default_options_win.cc index 2cf8fe3..6b08fc9 100644 --- a/src/cobalt/renderer/renderer_module_default_options_win.cc +++ b/src/cobalt/renderer/renderer_module_default_options_win.cc
@@ -24,21 +24,29 @@ namespace { scoped_ptr<rasterizer::Rasterizer> CreateRasterizer( - backend::GraphicsContext* graphics_context) { - const size_t kSurfaceCacheCapacityInBytes = 0; + backend::GraphicsContext* graphics_context, + const RendererModule::Options& options) { #if COBALT_FORCE_SOFTWARE_RASTERIZER return scoped_ptr<rasterizer::Rasterizer>( - new rasterizer::egl::SoftwareRasterizer(graphics_context, - kSurfaceCacheCapacityInBytes)); + new rasterizer::egl::SoftwareRasterizer( + graphics_context, options.surface_cache_size_in_bytes)); #else return scoped_ptr<rasterizer::Rasterizer>( - new rasterizer::skia::SkiaHardwareRasterizer( - graphics_context, kSurfaceCacheCapacityInBytes)); + new rasterizer::skia::HardwareRasterizer( + graphics_context, options.skia_cache_size_in_bytes, + options.scratch_surface_cache_size_in_bytes, + options.surface_cache_size_in_bytes)); #endif // #if COBALT_FORCE_SOFTWARE_RASTERIZER } } // namespace void RendererModule::Options::SetPerPlatformDefaultOptions() { + // Set default options from the current build's configuration. + surface_cache_size_in_bytes = COBALT_SURFACE_CACHE_SIZE_IN_BYTES; + skia_cache_size_in_bytes = COBALT_SKIA_CACHE_SIZE_IN_BYTES; + scratch_surface_cache_size_in_bytes = + COBALT_SCRATCH_SURFACE_CACHE_SIZE_IN_BYTES; + create_rasterizer_function = base::Bind(&CreateRasterizer); }
diff --git a/src/cobalt/renderer/resource_provider_test.cc b/src/cobalt/renderer/resource_provider_test.cc index 33ff33c..e511354 100644 --- a/src/cobalt/renderer/resource_provider_test.cc +++ b/src/cobalt/renderer/resource_provider_test.cc
@@ -155,7 +155,7 @@ RendererModule::Options render_module_options; scoped_ptr<rasterizer::Rasterizer> rasterizer = render_module_options.create_rasterizer_function.Run( - graphics_context.get()); + graphics_context.get(), render_module_options); // Create a dummy offscreen surface so that we can have a target when we start // a frame with the graphics context. @@ -208,7 +208,7 @@ RendererModule::Options render_module_options; scoped_ptr<rasterizer::Rasterizer> rasterizer = render_module_options.create_rasterizer_function.Run( - graphics_context.get()); + graphics_context.get(), render_module_options); // Create a dummy offscreen surface so that we can have a target when we start // a frame with the graphics context.
diff --git a/src/cobalt/renderer/sandbox/renderer_sandbox_main.cc b/src/cobalt/renderer/sandbox/renderer_sandbox_main.cc index 18606d4..dc54939 100644 --- a/src/cobalt/renderer/sandbox/renderer_sandbox_main.cc +++ b/src/cobalt/renderer/sandbox/renderer_sandbox_main.cc
@@ -38,46 +38,65 @@ const int kViewportWidth = 1920; const int kViewportHeight = 1080; -int SandboxMain(int argc, char** argv) { - MessageLoop message_loop(MessageLoop::TYPE_DEFAULT); +class RendererSandbox { + public: + RendererSandbox(); - cobalt::trace_event::ScopedTraceToFile trace_to_file( - FilePath(FILE_PATH_LITERAL("renderer_sandbox_trace.json"))); + private: + cobalt::trace_event::ScopedTraceToFile trace_to_file_; + base::EventDispatcher event_dispatcher_; + scoped_ptr<SystemWindow> system_window_; + scoped_ptr<cobalt::renderer::RendererModule> renderer_module_; +}; - base::EventDispatcher event_dispatcher; +RendererSandbox::RendererSandbox() + : trace_to_file_( + FilePath(FILE_PATH_LITERAL("renderer_sandbox_trace.json"))) { // Create a system window to use as a render target. - scoped_ptr<SystemWindow> system_window = - cobalt::system_window::CreateSystemWindow( - &event_dispatcher, - cobalt::math::Size(kViewportWidth, kViewportHeight)); + system_window_ = cobalt::system_window::CreateSystemWindow( + &event_dispatcher_, cobalt::math::Size(kViewportWidth, kViewportHeight)); // Construct a renderer module using default options. cobalt::renderer::RendererModule::Options renderer_module_options; - cobalt::renderer::RendererModule renderer_module(system_window.get(), - renderer_module_options); + renderer_module_.reset(new cobalt::renderer::RendererModule( + system_window_.get(), renderer_module_options)); cobalt::math::SizeF output_dimensions( - renderer_module.render_target()->GetSize()); + renderer_module_->render_target()->GetSize()); // Construct our render tree and associated animations to be passed into // the renderer pipeline for display. base::TimeDelta start_time = base::Time::Now() - base::Time::UnixEpoch(); RenderTreeWithAnimations scene = AddBlankBackgroundToScene( CreateAllScenesCombinedScene( - renderer_module.pipeline()->GetResourceProvider(), output_dimensions, - start_time), + renderer_module_->pipeline()->GetResourceProvider(), + output_dimensions, start_time), output_dimensions); // Pass the render tree along with associated animations into the renderer // module to be displayed. - renderer_module.pipeline()->Submit(cobalt::renderer::Submission( + renderer_module_->pipeline()->Submit(cobalt::renderer::Submission( scene.render_tree, scene.animations, start_time)); +} - base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(30)); +RendererSandbox* g_renderer_sandbox = NULL; - return 0; +void StartApplication(int /*argc*/, char** /*argv*/, + const base::Closure& quit_closure) { + DCHECK(!g_renderer_sandbox); + g_renderer_sandbox = new RendererSandbox(); + DCHECK(g_renderer_sandbox); + + MessageLoop::current()->PostDelayedTask(FROM_HERE, quit_closure, + base::TimeDelta::FromSeconds(30)); +} + +void StopApplication() { + DCHECK(g_renderer_sandbox); + delete g_renderer_sandbox; + g_renderer_sandbox = NULL; } } // namespace -COBALT_WRAP_SIMPLE_MAIN(SandboxMain); +COBALT_WRAP_BASE_MAIN(StartApplication, StopApplication);
diff --git a/src/cobalt/renderer/sandbox/sandbox.gyp b/src/cobalt/renderer/sandbox/sandbox.gyp index e16ee63..7cf08e7 100644 --- a/src/cobalt/renderer/sandbox/sandbox.gyp +++ b/src/cobalt/renderer/sandbox/sandbox.gyp
@@ -45,7 +45,7 @@ 'variables': { 'executable_name': 'renderer_sandbox', }, - 'includes': [ '../../build/deploy.gypi' ], + 'includes': [ '../../../starboard/build/deploy.gypi' ], }, { @@ -76,7 +76,7 @@ 'variables': { 'executable_name': 'scaling_text_sandbox', }, - 'includes': [ '../../build/deploy.gypi' ], + 'includes': [ '../../../starboard/build/deploy.gypi' ], }, ], }
diff --git a/src/cobalt/renderer/test/png_utils/png_decode.cc b/src/cobalt/renderer/test/png_utils/png_decode.cc index d582eee..4bf217b 100644 --- a/src/cobalt/renderer/test/png_utils/png_decode.cc +++ b/src/cobalt/renderer/test/png_utils/png_decode.cc
@@ -184,6 +184,7 @@ case render_tree::kPixelFormatY8: case render_tree::kPixelFormatU8: case render_tree::kPixelFormatV8: + case render_tree::kPixelFormatUV8: case render_tree::kPixelFormatInvalid: { NOTREACHED(); } @@ -202,6 +203,7 @@ case render_tree::kPixelFormatY8: case render_tree::kPixelFormatU8: case render_tree::kPixelFormatV8: + case render_tree::kPixelFormatUV8: case render_tree::kPixelFormatInvalid: { NOTREACHED(); }
diff --git a/src/cobalt/samples/samples.gyp b/src/cobalt/samples/samples.gyp index 7928dde..df34d7d 100644 --- a/src/cobalt/samples/samples.gyp +++ b/src/cobalt/samples/samples.gyp
@@ -76,7 +76,7 @@ 'variables': { 'executable_name': 'simple_example', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, # This target will create a test for simple_example. @@ -123,7 +123,7 @@ 'variables': { 'executable_name': 'simple_example_test', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, ], }
diff --git a/src/cobalt/script/javascriptcore/conversion_helpers.h b/src/cobalt/script/javascriptcore/conversion_helpers.h index 6d345b0..4642fc9 100644 --- a/src/cobalt/script/javascriptcore/conversion_helpers.h +++ b/src/cobalt/script/javascriptcore/conversion_helpers.h
@@ -349,6 +349,32 @@ *out_number = static_cast<T>(uint32_value); } +// JSValue -> signed integers > 4 bytes +template <class T> +inline void FromJSValue( + JSC::ExecState* exec_state, JSC::JSValue jsvalue, int conversion_flags, + ExceptionState* out_exception, T* out_number, + typename base::enable_if<std::numeric_limits<T>::is_specialized && + std::numeric_limits<T>::is_integer && + std::numeric_limits<T>::is_signed && + (sizeof(T) > 4), + T>::type* = NULL) { + NOTIMPLEMENTED(); +} + +// JSValue -> unsigned integers > 4 bytes +template <class T> +inline void FromJSValue( + JSC::ExecState* exec_state, JSC::JSValue jsvalue, int conversion_flags, + ExceptionState* out_exception, T* out_number, + typename base::enable_if<std::numeric_limits<T>::is_specialized && + std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed && + (sizeof(T) > 4), + T>::type* = NULL) { + NOTIMPLEMENTED(); +} + // JSValue -> double template <class T> inline void FromJSValue(
diff --git a/src/cobalt/script/javascriptcore/javascriptcore.gyp b/src/cobalt/script/javascriptcore/javascriptcore.gyp index 8dce193..0504492 100644 --- a/src/cobalt/script/javascriptcore/javascriptcore.gyp +++ b/src/cobalt/script/javascriptcore/javascriptcore.gyp
@@ -67,6 +67,11 @@ '<(DEPTH)/cobalt/script/script.gyp:script', '<(DEPTH)/third_party/WebKit/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp:javascriptcore', ], + 'all_dependent_settings': { + 'defines': [ + 'ENGINE_DEFINES_ATTRIBUTES_ON_OBJECT', + ], + }, 'msvs_disabled_warnings': [ # dll-interface warnings. Not easily fixed for template types. 4251,
diff --git a/src/cobalt/script/javascriptcore/jsc_call_frame.cc b/src/cobalt/script/javascriptcore/jsc_call_frame.cc index 3fe27ba..864e8d0 100644 --- a/src/cobalt/script/javascriptcore/jsc_call_frame.cc +++ b/src/cobalt/script/javascriptcore/jsc_call_frame.cc
@@ -107,7 +107,7 @@ } std::string JSCCallFrame::GetFunctionName() { - return call_frame_.functionName().latin1().data(); + return call_frame_.functionName().utf8().data(); } int JSCCallFrame::GetLineNumber() {
diff --git a/src/cobalt/script/javascriptcore/jsc_debugger.cc b/src/cobalt/script/javascriptcore/jsc_debugger.cc index 8508430..9856564 100644 --- a/src/cobalt/script/javascriptcore/jsc_debugger.cc +++ b/src/cobalt/script/javascriptcore/jsc_debugger.cc
@@ -225,7 +225,7 @@ // Script failed to parse. delegate_->OnScriptFailedToParse( scoped_ptr<SourceProvider>(new JSCSourceProvider( - source_provider, error_line, error_message.latin1().data()))); + source_provider, error_line, error_message.utf8().data()))); } }
diff --git a/src/cobalt/script/javascriptcore/jsc_source_provider.cc b/src/cobalt/script/javascriptcore/jsc_source_provider.cc index 1356bf5..836b044 100644 --- a/src/cobalt/script/javascriptcore/jsc_source_provider.cc +++ b/src/cobalt/script/javascriptcore/jsc_source_provider.cc
@@ -81,7 +81,7 @@ } std::string JSCSourceProvider::GetScriptSource() { - return source_provider_->source().latin1().data(); + return source_provider_->source().utf8().data(); } base::optional<std::string> JSCSourceProvider::GetSourceMapUrl() { @@ -98,7 +98,7 @@ } std::string JSCSourceProvider::GetUrl() { - return source_provider_->url().latin1().data(); + return source_provider_->url().utf8().data(); } base::optional<bool> JSCSourceProvider::IsContentScript() {
diff --git a/src/cobalt/script/mozjs/callback_function_conversion.h b/src/cobalt/script/mozjs/callback_function_conversion.h new file mode 100644 index 0000000..1e0966d --- /dev/null +++ b/src/cobalt/script/mozjs/callback_function_conversion.h
@@ -0,0 +1,96 @@ +/* + * 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_SCRIPT_MOZJS_CALLBACK_FUNCTION_CONVERSION_H_ +#define COBALT_SCRIPT_MOZJS_CALLBACK_FUNCTION_CONVERSION_H_ + +#include "base/logging.h" +#include "cobalt/base/polymorphic_downcast.h" +#include "cobalt/script/logging_exception_state.h" +#include "cobalt/script/mozjs/conversion_helpers.h" +#include "cobalt/script/mozjs/mozjs_callback_function.h" +#include "cobalt/script/script_object.h" +#include "third_party/mozjs/js/src/jsapi.h" + +namespace cobalt { +namespace script { +namespace mozjs { + +// CallbackFunction -> JSValue +template <typename Signature> +void ToJSValue( + JSContext* context, + const ScriptObject<CallbackFunction<Signature> >* callback_function, + JS::MutableHandleValue out_value) { + if (!callback_function) { + out_value.set(JS::NullValue()); + return; + } + // Downcast to MozjsUserObjectHolder<T> so we can get the underlying JSObject. + typedef MozjsUserObjectHolder<MozjsCallbackFunction<Signature> > + MozjsUserObjectHolderClass; + const MozjsUserObjectHolderClass* user_object_holder = + base::polymorphic_downcast<const MozjsUserObjectHolderClass*>( + callback_function); + + DCHECK(user_object_holder->js_object()); + out_value.set(OBJECT_TO_JSVAL(user_object_holder->js_object())); +} + +// JSValue -> CallbackFunction +template <typename Signature> +void FromJSValue(JSContext* context, JS::HandleValue value, + int conversion_flags, ExceptionState* exception_state, + MozjsUserObjectHolder<MozjsCallbackFunction<Signature> >* + out_callback_function) { + typedef MozjsUserObjectHolder<MozjsCallbackFunction<Signature> > + MozjsCallbackHolderClass; + + DCHECK_EQ(conversion_flags & ~kConversionFlagsCallbackFunction, 0) + << "Unexpected conversion flags."; + + if (value.isNull()) { + if (!(conversion_flags & kConversionFlagNullable)) { + exception_state->SetSimpleException(ExceptionState::kTypeError, + kNotNullableType); + } + // If it is a nullable type, just return. + return; + } + + // https://www.w3.org/TR/WebIDL/#es-callback-function + // 1. If V is not a Function object, throw a TypeError + JS::RootedObject object(context); + if (value.isObject()) { + object = JSVAL_TO_OBJECT(value); + } + if (!object || !JS_ObjectIsFunction(context, object)) { + exception_state->SetSimpleException(ExceptionState::kTypeError, + "Value is not a function."); + return; + } + + MozjsGlobalObjectProxy* global_object_proxy = + static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context)); + *out_callback_function = MozjsCallbackHolderClass( + object, context, global_object_proxy->wrapper_factory()); +} + +} // namespace mozjs +} // namespace script +} // namespace cobalt + +#endif // COBALT_SCRIPT_MOZJS_CALLBACK_FUNCTION_CONVERSION_H_
diff --git a/src/cobalt/script/mozjs/conversion_helpers.cc b/src/cobalt/script/mozjs/conversion_helpers.cc index 0da571d..c469d26 100644 --- a/src/cobalt/script/mozjs/conversion_helpers.cc +++ b/src/cobalt/script/mozjs/conversion_helpers.cc
@@ -24,7 +24,7 @@ // JSValue -> std::string void FromJSValue(JSContext* context, JS::HandleValue value, - int conversion_flags, MozjsExceptionState* exception_state, + int conversion_flags, ExceptionState* exception_state, std::string* out_string) { DCHECK_EQ(conversion_flags & ~kConversionFlagsString, 0) << "Unexpected conversion flags found: "; @@ -41,20 +41,27 @@ return; } - JSString* string = JS_ValueToString(context, value); + JS::RootedString string(context, JS_ValueToString(context, value)); if (!string) { exception_state->SetSimpleException(ExceptionState::kTypeError, "Not supported type."); return; } - *out_string = std::string(JS_EncodeStringToUTF8(context, string)); + JSAutoByteString auto_byte_string; + char* utf8_chars = auto_byte_string.encodeUtf8(context, string); + if (!utf8_chars) { + exception_state->SetSimpleException(ExceptionState::kTypeError, + "Failed to convert to utf8."); + return; + } + + *out_string = utf8_chars; } // OpaqueHandle -> JSValue void ToJSValue(JSContext* context, const OpaqueHandleHolder* opaque_handle_holder, - MozjsExceptionState* exception_state, JS::MutableHandleValue out_value) { JS::RootedObject js_object(context); if (opaque_handle_holder) { @@ -70,8 +77,8 @@ // JSValue -> OpaqueHandle void FromJSValue(JSContext* context, JS::HandleValue value, - int conversion_flags, MozjsExceptionState* exception_state, - MozjsObjectHandle::HolderType* out_holder) { + int conversion_flags, ExceptionState* exception_state, + MozjsObjectHandleHolder* out_holder) { DCHECK_EQ(conversion_flags & ~kConversionFlagsObject, 0) << "Unexpected conversion flags found."; JS::RootedObject js_object(context); @@ -98,8 +105,8 @@ DCHECK(js_object); MozjsGlobalObjectProxy* global_object_proxy = static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context)); - *out_holder = MozjsObjectHandle::HolderType( - js_object, context, global_object_proxy->wrapper_factory()); + *out_holder = MozjsObjectHandleHolder(js_object, context, + global_object_proxy->wrapper_factory()); } } // namespace mozjs
diff --git a/src/cobalt/script/mozjs/conversion_helpers.h b/src/cobalt/script/mozjs/conversion_helpers.h index defe56f..cf0206e 100644 --- a/src/cobalt/script/mozjs/conversion_helpers.h +++ b/src/cobalt/script/mozjs/conversion_helpers.h
@@ -22,12 +22,18 @@ #include "base/logging.h" #include "base/optional.h" +#include "base/stringprintf.h" #include "cobalt/base/enable_if.h" +#include "cobalt/base/token.h" +#include "cobalt/script/mozjs/mozjs_callback_interface_holder.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" #include "cobalt/script/mozjs/mozjs_object_handle.h" #include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/type_traits.h" +#include "cobalt/script/mozjs/union_type_conversion_forward.h" #include "third_party/mozjs/js/src/jsapi.h" +#include "third_party/mozjs/js/src/jsproxy.h" namespace cobalt { namespace script { @@ -55,19 +61,43 @@ // Valid conversion flags for objects. kConversionFlagsObject = kConversionFlagNullable, + + // Valid conversion flags for callback functions. + kConversionFlagsCallbackFunction = kConversionFlagNullable, + + // Valid conversion flags for callback interfaces. + kConversionFlagsCallbackInterface = kConversionFlagNullable, }; +// std::string -> JSValue +inline void ToJSValue(JSContext* context, const std::string& in_string, + JS::MutableHandleValue out_value) { + JS::RootedString rooted_string( + context, + JS_NewStringCopyN(context, in_string.c_str(), in_string.length())); + out_value.set(JS::StringValue(rooted_string)); +} + +// JSValue -> std::string +void FromJSValue(JSContext* context, JS::HandleValue value, + int conversion_flags, ExceptionState* exception_state, + std::string* out_string); + +// base::Token -> JSValue +inline void ToJSValue(JSContext* context, const base::Token& token, + JS::MutableHandleValue out_value) { + ToJSValue(context, std::string(token.c_str()), out_value); +} + // bool -> JSValue inline void ToJSValue(JSContext* context, bool in_boolean, - MozjsExceptionState* exception_state, JS::MutableHandleValue out_value) { out_value.set(JS::BooleanValue(in_boolean)); } // JSValue -> bool inline void FromJSValue(JSContext* context, JS::HandleValue value, - int conversion_flags, - MozjsExceptionState* exception_state, + int conversion_flags, ExceptionState* exception_state, bool* out_boolean) { DCHECK_EQ(conversion_flags, kNoConversionFlags) << "No conversion flags supported."; @@ -79,8 +109,7 @@ // signed integers <= 4 bytes -> JSValue template <typename T> inline void ToJSValue( - JSContext* context, T in_number, MozjsExceptionState* exception_state, - JS::MutableHandleValue out_value, + JSContext* context, T in_number, JS::MutableHandleValue out_value, typename base::enable_if<std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed && @@ -93,7 +122,7 @@ template <typename T> inline void FromJSValue( JSContext* context, JS::HandleValue value, int conversion_flags, - MozjsExceptionState* exception_state, T* out_number, + ExceptionState* exception_state, T* out_number, typename base::enable_if<std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed && @@ -112,11 +141,53 @@ *out_number = static_cast<T>(out); } +// JSValue -> signed integers > 4 bytes +template <typename T> +inline void FromJSValue( + JSContext* context, JS::HandleValue value, int conversion_flags, + ExceptionState* exception_state, T* out_number, + typename base::enable_if<std::numeric_limits<T>::is_specialized && + std::numeric_limits<T>::is_integer && + std::numeric_limits<T>::is_signed && + (sizeof(T) > 4), + T>::type* = NULL) { + double to_number; + JS::ToNumber(context, value, &to_number); + + std::string value_str; + FromJSValue(context, value, conversion_flags, exception_state, &value_str); + DCHECK_EQ(conversion_flags, kNoConversionFlags) + << "No conversion flags supported."; + DCHECK(out_number); + int64_t out; + // This produces an IDL long long. + JSBool success = JS_ValueToInt64(context, value, &out); + DCHECK(success); + if (!success) { + exception_state->SetSimpleException( + ExceptionState::kTypeError, + "Cannot convert a JavaScript value to int64_t."); + return; + } + *out_number = static_cast<T>(out); +} + +// signed integers > 4 bytes -> JSValue +template <typename T> +inline void ToJSValue( + JSContext* context, T in_number, JS::MutableHandleValue out_value, + typename base::enable_if<std::numeric_limits<T>::is_specialized && + std::numeric_limits<T>::is_integer && + std::numeric_limits<T>::is_signed && + (sizeof(T) > 4), + T>::type* = NULL) { + out_value.set(JS_NumberValue(in_number)); +} + // unsigned integers <= 4 bytes -> JSValue template <typename T> inline void ToJSValue( - JSContext* context, T in_number, MozjsExceptionState* exception_state, - JS::MutableHandleValue out_value, + JSContext* context, T in_number, JS::MutableHandleValue out_value, typename base::enable_if<std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed && @@ -129,7 +200,7 @@ template <typename T> inline void FromJSValue( JSContext* context, JS::HandleValue value, int conversion_flags, - MozjsExceptionState* exception_state, T* out_number, + ExceptionState* exception_state, T* out_number, typename base::enable_if<std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed && @@ -148,11 +219,49 @@ *out_number = static_cast<T>(out); } +// JSValue -> unsigned integers > 4 bytes +template <typename T> +inline void FromJSValue( + JSContext* context, JS::HandleValue value, int conversion_flags, + ExceptionState* exception_state, T* out_number, + typename base::enable_if<std::numeric_limits<T>::is_specialized && + std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed && + (sizeof(T) > 4), + T>::type* = NULL) { + DCHECK_EQ(conversion_flags, kNoConversionFlags) + << "No conversion flags supported."; + DCHECK(out_number); + + uint64_t out; + // This produces and IDL unsigned long long. + JSBool success = JS_ValueToUint64(context, value, &out); + DCHECK(success); + if (!success) { + exception_state->SetSimpleException( + ExceptionState::kTypeError, + "Cannot convert a JavaScript value to uint64_t."); + return; + } + *out_number = static_cast<T>(out); +} + +// unsigned integers > 4 bytes -> JSValue +template <typename T> +inline void ToJSValue( + JSContext* context, T in_number, JS::MutableHandleValue out_value, + typename base::enable_if<std::numeric_limits<T>::is_specialized && + std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed && + (sizeof(T) > 4), + T>::type* = NULL) { + out_value.set(JS_NumberValue(in_number)); +} + // double -> JSValue template <typename T> inline void ToJSValue( - JSContext* context, T in_number, MozjsExceptionState* exception_state, - JS::MutableHandleValue out_value, + JSContext* context, T in_number, JS::MutableHandleValue out_value, typename base::enable_if<std::numeric_limits<T>::is_specialized && !std::numeric_limits<T>::is_integer, T>::type* = NULL) { @@ -163,7 +272,7 @@ template <typename T> inline void FromJSValue( JSContext* context, JS::HandleValue value, int conversion_flags, - MozjsExceptionState* exception_state, T* out_number, + ExceptionState* exception_state, T* out_number, typename base::enable_if<std::numeric_limits<T>::is_specialized && !std::numeric_limits<T>::is_integer, T>::type* = NULL) { @@ -188,31 +297,21 @@ *out_number = double_value; } -// std::string -> JSValue -inline void ToJSValue(JSContext* context, const std::string& in_string, - MozjsExceptionState* exception_state, - JS::MutableHandleValue out_value) { - out_value.set(JS::StringValue( - JS_NewStringCopyN(context, in_string.c_str(), in_string.length()))); -} - // optional<T> -> JSValue template <typename T> inline void ToJSValue(JSContext* context, const base::optional<T>& in_optional, - MozjsExceptionState* exception_state, JS::MutableHandleValue out_value) { if (!in_optional) { out_value.setNull(); return; } - ToJSValue(context, in_optional.value(), exception_state, out_value); + ToJSValue(context, in_optional.value(), out_value); } // JSValue -> optional<T> template <typename T> inline void FromJSValue(JSContext* context, JS::HandleValue value, - int conversion_flags, - MozjsExceptionState* exception_state, + int conversion_flags, ExceptionState* exception_state, base::optional<T>* out_optional) { if (value.isNull()) { *out_optional = base::nullopt; @@ -225,16 +324,10 @@ } } -// JSValue -> std::string -void FromJSValue(JSContext* context, JS::HandleValue value, - int conversion_flags, MozjsExceptionState* exception_state, - std::string* out_string); - -// JSValue -> optional<T> +// JSValue -> optional<std::string> template <> inline void FromJSValue(JSContext* context, JS::HandleValue value, - int conversion_flags, - MozjsExceptionState* exception_state, + int conversion_flags, ExceptionState* exception_state, base::optional<std::string>* out_optional) { if (value.isNull()) { *out_optional = base::nullopt; @@ -253,18 +346,16 @@ // OpaqueHandle -> JSValue void ToJSValue(JSContext* context, const OpaqueHandleHolder* opaque_handle_holder, - MozjsExceptionState* exception_state, JS::MutableHandleValue out_value); // JSValue -> OpaqueHandle void FromJSValue(JSContext* context, JS::HandleValue value, - int conversion_flags, MozjsExceptionState* exception_state, - MozjsObjectHandle::HolderType* out_holder); + int conversion_flags, ExceptionState* exception_state, + MozjsObjectHandleHolder* out_holder); // object -> JSValue -template <class T> +template <typename T> inline void ToJSValue(JSContext* context, const scoped_refptr<T>& in_object, - MozjsExceptionState* exception_state, JS::MutableHandleValue out_value) { if (!in_object) { out_value.setNull(); @@ -274,68 +365,132 @@ MozjsGlobalObjectProxy* global_object_proxy = static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context)); JS::RootedObject object( - context, global_object_proxy->wrapper_factory()->GetWrapper(in_object)); + context, + global_object_proxy->wrapper_factory()->GetWrapperProxy(in_object)); DCHECK(object); out_value.set(OBJECT_TO_JSVAL(object)); } // JSValue -> object -template <class T> +template <typename T> inline void FromJSValue(JSContext* context, JS::HandleValue value, - int conversion_flags, - MozjsExceptionState* exception_state, + int conversion_flags, ExceptionState* exception_state, scoped_refptr<T>* out_object) { DCHECK_EQ(conversion_flags & ~kConversionFlagsObject, 0) << "Unexpected conversion flags found."; - JS::RootedObject js_object(context); - if (value.isNull() && !(conversion_flags & kConversionFlagNullable)) { - exception_state->SetSimpleException(ExceptionState::kTypeError, - kNotNullableType); + if (value.isNull()) { + if (!(conversion_flags & kConversionFlagNullable)) { + exception_state->SetSimpleException(ExceptionState::kTypeError, + kNotNullableType); + } return; } - if (!JS_ValueToObject(context, value, js_object.address())) { exception_state->SetSimpleException( ExceptionState::kTypeError, "Cannot convert a JavaScript value to an object."); return; } - DCHECK(js_object); + if (js::IsProxy(js_object)) { + JS::RootedObject wrapper(context, js::GetProxyTargetObject(js_object)); + MozjsGlobalObjectProxy* global_object_proxy = + static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context)); + const WrapperFactory* wrapper_factory = + global_object_proxy->wrapper_factory(); + if (wrapper_factory->IsWrapper(wrapper)) { + bool object_implements_interface = + wrapper_factory->DoesObjectImplementInterface(js_object, + base::GetTypeId<T>()); + if (!object_implements_interface) { + exception_state->SetSimpleException(ExceptionState::kTypeError, + kDoesNotImplementInterface); + return; + } + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromWrapperObject(wrapper); + *out_object = wrapper_private->wrappable<T>(); + return; + } + } + // This is not a platform object. Return a type error. + exception_state->SetSimpleException(ExceptionState::kTypeError, + kDoesNotImplementInterface); +} + +// CallbackInterface -> JSValue +template <typename T> +inline void ToJSValue(JSContext* context, + const ScriptObject<T>* callback_interface, + JS::MutableHandleValue out_value) { + if (!callback_interface) { + out_value.set(JS::NullValue()); + return; + } + typedef typename CallbackInterfaceTraits<T>::MozjsCallbackInterfaceClass + MozjsCallbackInterfaceClass; + // Downcast to MozjsUserObjectHolder<T> so we can get the underlying JSObject. + typedef MozjsUserObjectHolder<MozjsCallbackInterfaceClass> + MozjsUserObjectHolderClass; + const MozjsUserObjectHolderClass* user_object_holder = + base::polymorphic_downcast<const MozjsUserObjectHolderClass*>( + callback_interface); + + // Shouldn't be NULL. If the callback was NULL then NULL should have been + // passed as an argument into this function. + // Downcast to the corresponding MozjsCallbackInterface type, from which we + // can get the implementing object. + const MozjsCallbackInterfaceClass* mozjs_callback_interface = + base::polymorphic_downcast<const MozjsCallbackInterfaceClass*>( + user_object_holder->GetScriptObject()); + DCHECK(mozjs_callback_interface); + out_value.set(OBJECT_TO_JSVAL(mozjs_callback_interface->handle())); +} + +// JSValue -> CallbackInterface +template <typename T> +inline void FromJSValue( + JSContext* context, JS::HandleValue value, int conversion_flags, + ExceptionState* out_exception, + MozjsCallbackInterfaceHolder<T>* out_callback_interface) { + typedef T MozjsCallbackInterfaceClass; + DCHECK_EQ(conversion_flags & ~kConversionFlagsCallbackFunction, 0) + << "No conversion flags supported."; + if (value.isNull()) { + if (!(conversion_flags & kConversionFlagNullable)) { + out_exception->SetSimpleException(ExceptionState::kTypeError, + kNotNullableType); + } + // If it is a nullable type, just return. + return; + } + + // https://www.w3.org/TR/WebIDL/#es-user-objects + // Any user object can be considered to implement a user interface. Actually + // checking if the correct properties exist will happen when the operation + // on the callback interface is run. + if (!value.isObject()) { + out_exception->SetSimpleException(ExceptionState::kTypeError, + kNotObjectType); + return; + } + MozjsGlobalObjectProxy* global_object_proxy = static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context)); - if (global_object_proxy->wrapper_factory()->IsWrapper(js_object)) { - *out_object = WrapperPrivate::GetWrappable<T>(js_object); - } else { - // This is not a platform object. Return a type error. - exception_state->SetSimpleException(ExceptionState::kTypeError, - kDoesNotImplementInterface); - } -} -// TODO: These will be removed once conversion for all types is implemented. -template <typename T> -void ToJSValue( - JSContext* context, const T& unimplemented, - MozjsExceptionState* exception_state, JS::MutableHandleValue out_value, - typename base::enable_if<!std::numeric_limits<T>::is_specialized>::type* = - NULL) { - NOTIMPLEMENTED(); -} - -template <typename T> -void FromJSValue( - JSContext* context, JS::HandleValue value, int conversion_flags, - MozjsExceptionState* exception_state, T* out_unimplemented, - typename base::enable_if<!std::numeric_limits<T>::is_specialized>::type* = - NULL) { - NOTIMPLEMENTED(); + JS::RootedObject implementing_object(context, JSVAL_TO_OBJECT(value)); + DCHECK(implementing_object); + *out_callback_interface = MozjsCallbackInterfaceHolder<T>( + implementing_object, context, global_object_proxy->wrapper_factory()); } } // namespace mozjs } // namespace script } // namespace cobalt +// Union type conversion is generated by a pump script. +#include "cobalt/script/mozjs/union_type_conversion_impl.h" + #endif // COBALT_SCRIPT_MOZJS_CONVERSION_HELPERS_H_
diff --git a/src/cobalt/script/mozjs/convert_callback_return_value.h b/src/cobalt/script/mozjs/convert_callback_return_value.h new file mode 100644 index 0000000..05c5245 --- /dev/null +++ b/src/cobalt/script/mozjs/convert_callback_return_value.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_SCRIPT_MOZJS_CONVERT_CALLBACK_RETURN_VALUE_H_ +#define COBALT_SCRIPT_MOZJS_CONVERT_CALLBACK_RETURN_VALUE_H_ + +#include "base/logging.h" +#include "cobalt/script/callback_function.h" +#include "cobalt/script/logging_exception_state.h" +#include "cobalt/script/mozjs/conversion_helpers.h" +#include "third_party/mozjs/js/src/jsapi.h" + +namespace cobalt { +namespace script { +namespace mozjs { + +// Helper template functions for Callback functions' return values before being +// returned to Cobalt. +// Converts the return value from JavaScript into the correct Cobalt type, or +// sets the exception bit if conversion fails. +template <typename R> +CallbackResult<R> ConvertCallbackReturnValue(JSContext* context, + JS::HandleValue value) { + // TODO: Pass conversion flags to callback function return value if + // appropriate. + const int kConversionFlags = 0; + CallbackResult<R> callback_result; + LoggingExceptionState exception_state; + FromJSValue(context, value, kConversionFlags, &exception_state, + &callback_result.result); + callback_result.exception = exception_state.is_exception_set(); + return callback_result; +} + +template <> +inline CallbackResult<void> ConvertCallbackReturnValue(JSContext* context, + JS::HandleValue value) { + // No conversion necessary. + return CallbackResult<void>(); +} + +} // namespace mozjs +} // namespace script +} // namespace cobalt + +#endif // COBALT_SCRIPT_MOZJS_CONVERT_CALLBACK_RETURN_VALUE_H_
diff --git a/src/cobalt/script/mozjs/mozjs.gyp b/src/cobalt/script/mozjs/mozjs.gyp index 886887d..58728de 100644 --- a/src/cobalt/script/mozjs/mozjs.gyp +++ b/src/cobalt/script/mozjs/mozjs.gyp
@@ -19,10 +19,14 @@ 'type': 'static_library', 'sources': [ 'conversion_helpers.cc', + 'mozjs_callback_interface.cc', + 'mozjs_debugger.cc', 'mozjs_engine.cc', 'mozjs_exception_state.cc', 'mozjs_global_object_proxy.cc', + 'mozjs_property_enumerator.cc', 'mozjs_source_code.cc', + 'proxy_handler.cc', 'wrapper_factory.cc', 'wrapper_private.cc', ], @@ -30,7 +34,15 @@ '<(DEPTH)/cobalt/script/script.gyp:script', '<(DEPTH)/third_party/mozjs/mozjs.gyp:mozjs_lib', ], + 'defines': [ 'ENGINE_SUPPORTS_INT64', ], + 'all_dependent_settings': { + 'defines': [ + # SpiderMonkey bindings implements indexed deleters. + 'ENGINE_SUPPORTS_INDEXED_DELETERS', + 'ENGINE_SUPPORTS_INT64', ], + }, }, + { # Standalone executable for JS engine 'target_name': 'mozjs',
diff --git a/src/cobalt/script/mozjs/mozjs_callback_function.h b/src/cobalt/script/mozjs/mozjs_callback_function.h index 85ff85e..bcdf94e 100644 --- a/src/cobalt/script/mozjs/mozjs_callback_function.h +++ b/src/cobalt/script/mozjs/mozjs_callback_function.h
@@ -25,6 +25,10 @@ #include "base/logging.h" #include "cobalt/script/callback_function.h" +#include "cobalt/script/mozjs/conversion_helpers.h" +#include "cobalt/script/mozjs/convert_callback_return_value.h" +#include "third_party/mozjs/js/src/jsapi.h" +#include "third_party/mozjs/js/src/jscntxt.h" namespace cobalt { namespace script { @@ -42,65 +46,251 @@ class MozjsCallbackFunction<R(void)> : public CallbackFunction<R(void)> { public: + typedef CallbackFunction<R()> BaseType; + + explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function) + : context_(context), function_(function) { + DCHECK(context_); + DCHECK(JS_ObjectIsFunction(context_, function_)); + } + CallbackResult<R> Run() const OVERRIDE { - NOTIMPLEMENTED(); - return R(); + JSAutoRequest auto_request(context_); + JSAutoCompartment auto_compartment(context_, function_); + + // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions + // Callback 'this' is set to null, unless overridden by other specifications + JS::Value this_value(JS::NullValue()); + JS::RootedValue return_value(context_); + const int kNumArguments = 0; + + JSBool call_result = JS::Call(context_, this_value, function_, 0, NULL, + return_value.address()); + + CallbackResult<R> callback_result; + if (!call_result) { + DLOG(WARNING) << "Exception in callback."; + callback_result.exception = true; + } else { + callback_result = ConvertCallbackReturnValue<R>(context_, return_value); + } + return callback_result; } + + JSObject* handle() const { return function_; } + + private: + JSContext* context_; + mutable JS::Heap<JSObject*> function_; }; template <typename R, typename A1> class MozjsCallbackFunction<R(A1)> : public CallbackFunction<R(A1)> { public: + typedef CallbackFunction<R(A1)> BaseType; + + explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function) + : context_(context), function_(function) { + DCHECK(context_); + DCHECK(JS_ObjectIsFunction(context_, function_)); + } + CallbackResult<R> Run( typename base::internal::CallbackParamTraits<A1>::ForwardType a1) const OVERRIDE { - NOTIMPLEMENTED(); - return R(); + JSAutoRequest auto_request(context_); + JSAutoCompartment auto_compartment(context_, function_); + + // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions + // Callback 'this' is set to null, unless overridden by other specifications + JS::Value this_value(JS::NullValue()); + JS::RootedValue return_value(context_); + const int kNumArguments = 1; + + JS::Value args[1]; + js::SetValueRangeToNull(args, kNumArguments); + js::AutoValueArray auto_array_rooter(context_, args, kNumArguments); + ToJSValue(context_, a1, auto_array_rooter.handleAt(0)); + + JSBool call_result = JS::Call(context_, this_value, function_, + kNumArguments, args, return_value.address()); + + CallbackResult<R> callback_result; + if (!call_result) { + DLOG(WARNING) << "Exception in callback."; + callback_result.exception = true; + } else { + callback_result = ConvertCallbackReturnValue<R>(context_, return_value); + } + return callback_result; } + + JSObject* handle() const { return function_; } + + private: + JSContext* context_; + mutable JS::Heap<JSObject*> function_; }; template <typename R, typename A1, typename A2> class MozjsCallbackFunction<R(A1, A2)> : public CallbackFunction<R(A1, A2)> { public: + typedef CallbackFunction<R(A1, A2)> BaseType; + + explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function) + : context_(context), function_(function) { + DCHECK(context_); + DCHECK(JS_ObjectIsFunction(context_, function_)); + } + CallbackResult<R> Run( typename base::internal::CallbackParamTraits<A1>::ForwardType a1, typename base::internal::CallbackParamTraits<A2>::ForwardType a2) const OVERRIDE { - NOTIMPLEMENTED(); - return R(); + JSAutoRequest auto_request(context_); + JSAutoCompartment auto_compartment(context_, function_); + + // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions + // Callback 'this' is set to null, unless overridden by other specifications + JS::Value this_value(JS::NullValue()); + JS::RootedValue return_value(context_); + const int kNumArguments = 2; + + JS::Value args[2]; + js::SetValueRangeToNull(args, kNumArguments); + js::AutoValueArray auto_array_rooter(context_, args, kNumArguments); + ToJSValue(context_, a1, auto_array_rooter.handleAt(0)); + ToJSValue(context_, a2, auto_array_rooter.handleAt(1)); + + JSBool call_result = JS::Call(context_, this_value, function_, + kNumArguments, args, return_value.address()); + + CallbackResult<R> callback_result; + if (!call_result) { + DLOG(WARNING) << "Exception in callback."; + callback_result.exception = true; + } else { + callback_result = ConvertCallbackReturnValue<R>(context_, return_value); + } + return callback_result; } + + JSObject* handle() const { return function_; } + + private: + JSContext* context_; + mutable JS::Heap<JSObject*> function_; }; template <typename R, typename A1, typename A2, typename A3> class MozjsCallbackFunction<R(A1, A2, A3)> : public CallbackFunction<R(A1, A2, A3)> { public: + typedef CallbackFunction<R(A1, A2, A3)> BaseType; + + explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function) + : context_(context), function_(function) { + DCHECK(context_); + DCHECK(JS_ObjectIsFunction(context_, function_)); + } + CallbackResult<R> Run( typename base::internal::CallbackParamTraits<A1>::ForwardType a1, typename base::internal::CallbackParamTraits<A2>::ForwardType a2, typename base::internal::CallbackParamTraits<A3>::ForwardType a3) const OVERRIDE { - NOTIMPLEMENTED(); - return R(); + JSAutoRequest auto_request(context_); + JSAutoCompartment auto_compartment(context_, function_); + + // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions + // Callback 'this' is set to null, unless overridden by other specifications + JS::Value this_value(JS::NullValue()); + JS::RootedValue return_value(context_); + const int kNumArguments = 3; + + JS::Value args[3]; + js::SetValueRangeToNull(args, kNumArguments); + js::AutoValueArray auto_array_rooter(context_, args, kNumArguments); + ToJSValue(context_, a1, auto_array_rooter.handleAt(0)); + ToJSValue(context_, a2, auto_array_rooter.handleAt(1)); + ToJSValue(context_, a3, auto_array_rooter.handleAt(2)); + + JSBool call_result = JS::Call(context_, this_value, function_, + kNumArguments, args, return_value.address()); + + CallbackResult<R> callback_result; + if (!call_result) { + DLOG(WARNING) << "Exception in callback."; + callback_result.exception = true; + } else { + callback_result = ConvertCallbackReturnValue<R>(context_, return_value); + } + return callback_result; } + + JSObject* handle() const { return function_; } + + private: + JSContext* context_; + mutable JS::Heap<JSObject*> function_; }; template <typename R, typename A1, typename A2, typename A3, typename A4> class MozjsCallbackFunction<R(A1, A2, A3, A4)> : public CallbackFunction<R(A1, A2, A3, A4)> { public: + typedef CallbackFunction<R(A1, A2, A3, A4)> BaseType; + + explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function) + : context_(context), function_(function) { + DCHECK(context_); + DCHECK(JS_ObjectIsFunction(context_, function_)); + } + CallbackResult<R> Run( typename base::internal::CallbackParamTraits<A1>::ForwardType a1, typename base::internal::CallbackParamTraits<A2>::ForwardType a2, typename base::internal::CallbackParamTraits<A3>::ForwardType a3, typename base::internal::CallbackParamTraits<A4>::ForwardType a4) const OVERRIDE { - NOTIMPLEMENTED(); - return R(); + JSAutoRequest auto_request(context_); + JSAutoCompartment auto_compartment(context_, function_); + + // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions + // Callback 'this' is set to null, unless overridden by other specifications + JS::Value this_value(JS::NullValue()); + JS::RootedValue return_value(context_); + const int kNumArguments = 4; + + JS::Value args[4]; + js::SetValueRangeToNull(args, kNumArguments); + js::AutoValueArray auto_array_rooter(context_, args, kNumArguments); + ToJSValue(context_, a1, auto_array_rooter.handleAt(0)); + ToJSValue(context_, a2, auto_array_rooter.handleAt(1)); + ToJSValue(context_, a3, auto_array_rooter.handleAt(2)); + ToJSValue(context_, a4, auto_array_rooter.handleAt(3)); + + JSBool call_result = JS::Call(context_, this_value, function_, + kNumArguments, args, return_value.address()); + + CallbackResult<R> callback_result; + if (!call_result) { + DLOG(WARNING) << "Exception in callback."; + callback_result.exception = true; + } else { + callback_result = ConvertCallbackReturnValue<R>(context_, return_value); + } + return callback_result; } + + JSObject* handle() const { return function_; } + + private: + JSContext* context_; + mutable JS::Heap<JSObject*> function_; }; template <typename R, typename A1, typename A2, typename A3, typename A4, @@ -108,6 +298,14 @@ class MozjsCallbackFunction<R(A1, A2, A3, A4, A5)> : public CallbackFunction<R(A1, A2, A3, A4, A5)> { public: + typedef CallbackFunction<R(A1, A2, A3, A4, A5)> BaseType; + + explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function) + : context_(context), function_(function) { + DCHECK(context_); + DCHECK(JS_ObjectIsFunction(context_, function_)); + } + CallbackResult<R> Run( typename base::internal::CallbackParamTraits<A1>::ForwardType a1, typename base::internal::CallbackParamTraits<A2>::ForwardType a2, @@ -115,9 +313,42 @@ typename base::internal::CallbackParamTraits<A4>::ForwardType a4, typename base::internal::CallbackParamTraits<A5>::ForwardType a5) const OVERRIDE { - NOTIMPLEMENTED(); - return R(); + JSAutoRequest auto_request(context_); + JSAutoCompartment auto_compartment(context_, function_); + + // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions + // Callback 'this' is set to null, unless overridden by other specifications + JS::Value this_value(JS::NullValue()); + JS::RootedValue return_value(context_); + const int kNumArguments = 5; + + JS::Value args[5]; + js::SetValueRangeToNull(args, kNumArguments); + js::AutoValueArray auto_array_rooter(context_, args, kNumArguments); + ToJSValue(context_, a1, auto_array_rooter.handleAt(0)); + ToJSValue(context_, a2, auto_array_rooter.handleAt(1)); + ToJSValue(context_, a3, auto_array_rooter.handleAt(2)); + ToJSValue(context_, a4, auto_array_rooter.handleAt(3)); + ToJSValue(context_, a5, auto_array_rooter.handleAt(4)); + + JSBool call_result = JS::Call(context_, this_value, function_, + kNumArguments, args, return_value.address()); + + CallbackResult<R> callback_result; + if (!call_result) { + DLOG(WARNING) << "Exception in callback."; + callback_result.exception = true; + } else { + callback_result = ConvertCallbackReturnValue<R>(context_, return_value); + } + return callback_result; } + + JSObject* handle() const { return function_; } + + private: + JSContext* context_; + mutable JS::Heap<JSObject*> function_; }; template <typename R, typename A1, typename A2, typename A3, typename A4, @@ -125,6 +356,14 @@ class MozjsCallbackFunction<R(A1, A2, A3, A4, A5, A6)> : public CallbackFunction<R(A1, A2, A3, A4, A5, A6)> { public: + typedef CallbackFunction<R(A1, A2, A3, A4, A5, A6)> BaseType; + + explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function) + : context_(context), function_(function) { + DCHECK(context_); + DCHECK(JS_ObjectIsFunction(context_, function_)); + } + CallbackResult<R> Run( typename base::internal::CallbackParamTraits<A1>::ForwardType a1, typename base::internal::CallbackParamTraits<A2>::ForwardType a2, @@ -133,9 +372,43 @@ typename base::internal::CallbackParamTraits<A5>::ForwardType a5, typename base::internal::CallbackParamTraits<A6>::ForwardType a6) const OVERRIDE { - NOTIMPLEMENTED(); - return R(); + JSAutoRequest auto_request(context_); + JSAutoCompartment auto_compartment(context_, function_); + + // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions + // Callback 'this' is set to null, unless overridden by other specifications + JS::Value this_value(JS::NullValue()); + JS::RootedValue return_value(context_); + const int kNumArguments = 6; + + JS::Value args[6]; + js::SetValueRangeToNull(args, kNumArguments); + js::AutoValueArray auto_array_rooter(context_, args, kNumArguments); + ToJSValue(context_, a1, auto_array_rooter.handleAt(0)); + ToJSValue(context_, a2, auto_array_rooter.handleAt(1)); + ToJSValue(context_, a3, auto_array_rooter.handleAt(2)); + ToJSValue(context_, a4, auto_array_rooter.handleAt(3)); + ToJSValue(context_, a5, auto_array_rooter.handleAt(4)); + ToJSValue(context_, a6, auto_array_rooter.handleAt(5)); + + JSBool call_result = JS::Call(context_, this_value, function_, + kNumArguments, args, return_value.address()); + + CallbackResult<R> callback_result; + if (!call_result) { + DLOG(WARNING) << "Exception in callback."; + callback_result.exception = true; + } else { + callback_result = ConvertCallbackReturnValue<R>(context_, return_value); + } + return callback_result; } + + JSObject* handle() const { return function_; } + + private: + JSContext* context_; + mutable JS::Heap<JSObject*> function_; }; template <typename R, typename A1, typename A2, typename A3, typename A4, @@ -143,6 +416,14 @@ class MozjsCallbackFunction<R(A1, A2, A3, A4, A5, A6, A7)> : public CallbackFunction<R(A1, A2, A3, A4, A5, A6, A7)> { public: + typedef CallbackFunction<R(A1, A2, A3, A4, A5, A6, A7)> BaseType; + + explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function) + : context_(context), function_(function) { + DCHECK(context_); + DCHECK(JS_ObjectIsFunction(context_, function_)); + } + CallbackResult<R> Run( typename base::internal::CallbackParamTraits<A1>::ForwardType a1, typename base::internal::CallbackParamTraits<A2>::ForwardType a2, @@ -152,9 +433,51 @@ typename base::internal::CallbackParamTraits<A6>::ForwardType a6, typename base::internal::CallbackParamTraits<A7>::ForwardType a7) const OVERRIDE { - NOTIMPLEMENTED(); - return R(); + JSAutoRequest auto_request(context_); + JSAutoCompartment auto_compartment(context_, function_); + + // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions + // Callback 'this' is set to null, unless overridden by other specifications + JS::Value this_value(JS::NullValue()); + JS::RootedValue return_value(context_); + const int kNumArguments = 7; + + JS::Value args[7]; + js::SetValueRangeToNull(args, kNumArguments); + js::AutoValueArray auto_array_rooter(context_, args, kNumArguments); + ToJSValue(context_, a1, auto_array_rooter.handleAt(0)); + ToJSValue(context_, a2, auto_array_rooter.handleAt(1)); + ToJSValue(context_, a3, auto_array_rooter.handleAt(2)); + ToJSValue(context_, a4, auto_array_rooter.handleAt(3)); + ToJSValue(context_, a5, auto_array_rooter.handleAt(4)); + ToJSValue(context_, a6, auto_array_rooter.handleAt(5)); + ToJSValue(context_, a7, auto_array_rooter.handleAt(6)); + + JSBool call_result = JS::Call(context_, this_value, function_, + kNumArguments, args, return_value.address()); + + CallbackResult<R> callback_result; + if (!call_result) { + DLOG(WARNING) << "Exception in callback."; + callback_result.exception = true; + } else { + callback_result = ConvertCallbackReturnValue<R>(context_, return_value); + } + return callback_result; } + + JSObject* handle() const { return function_; } + + private: + JSContext* context_; + mutable JS::Heap<JSObject*> function_; +}; + +template <typename Signature> +struct TypeTraits<CallbackFunction<Signature> > { + typedef MozjsUserObjectHolder<MozjsCallbackFunction<Signature> > + ConversionType; + typedef const ScriptObject<CallbackFunction<Signature> >* ReturnType; }; } // namespace mozjs
diff --git a/src/cobalt/script/mozjs/mozjs_callback_function.h.pump b/src/cobalt/script/mozjs/mozjs_callback_function.h.pump index 510a8e4..fb4e78e 100644 --- a/src/cobalt/script/mozjs/mozjs_callback_function.h.pump +++ b/src/cobalt/script/mozjs/mozjs_callback_function.h.pump
@@ -30,6 +30,10 @@ #include "base/logging.h" #include "cobalt/script/callback_function.h" +#include "cobalt/script/mozjs/conversion_helpers.h" +#include "cobalt/script/mozjs/convert_callback_return_value.h" +#include "third_party/mozjs/js/src/jsapi.h" +#include "third_party/mozjs/js/src/jscntxt.h" namespace cobalt { namespace script { @@ -59,17 +63,68 @@ ]] public: + typedef CallbackFunction<R($for ARG , [[A$(ARG)]])> BaseType; + + explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function) + : context_(context), function_(function) { + DCHECK(context_); + DCHECK(JS_ObjectIsFunction(context_, function_)); + } + CallbackResult<R> Run($for ARG , [[ typename base::internal::CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) const OVERRIDE { - NOTIMPLEMENTED(); - return R(); + JSAutoRequest auto_request(context_); + JSAutoCompartment auto_compartment(context_, function_); + + // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions + // Callback 'this' is set to null, unless overridden by other specifications + JS::Value this_value(JS::NullValue()); + JS::RootedValue return_value(context_); + const int kNumArguments = $(ARITY); + + +$if ARITY > 0 [[ + JS::Value args[$(ARITY)]; + js::SetValueRangeToNull(args, kNumArguments); + js::AutoValueArray auto_array_rooter(context_, args, kNumArguments); + $for ARG [[ToJSValue(context_, a$(ARG), auto_array_rooter.handleAt($(ARG - 1))); + ]] + + JSBool call_result = JS::Call(context_, this_value, function_, + kNumArguments, args, return_value.address()); +]] $else [[ + JSBool call_result = JS::Call(context_, this_value, function_, 0, NULL, + return_value.address()); +]] + + + CallbackResult<R> callback_result; + if (!call_result) { + DLOG(WARNING) << "Exception in callback."; + callback_result.exception = true; + } else { + callback_result = ConvertCallbackReturnValue<R>(context_, return_value); + } + return callback_result; } + + JSObject* handle() const { return function_; } + + private: + JSContext* context_; + mutable JS::Heap<JSObject*> function_; }; ]] +template <typename Signature> +struct TypeTraits<CallbackFunction<Signature> > { + typedef MozjsUserObjectHolder<MozjsCallbackFunction<Signature> > ConversionType; + typedef const ScriptObject<CallbackFunction<Signature> >* ReturnType; +}; + } // namespace mozjs } // namespace script } // namespace cobalt
diff --git a/src/cobalt/script/mozjs/mozjs_callback_function_holder.h b/src/cobalt/script/mozjs/mozjs_callback_function_holder.h deleted file mode 100644 index bf1f91a..0000000 --- a/src/cobalt/script/mozjs/mozjs_callback_function_holder.h +++ /dev/null
@@ -1,60 +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_SCRIPT_MOZJS_MOZJS_CALLBACK_FUNCTION_HOLDER_H_ -#define COBALT_SCRIPT_MOZJS_MOZJS_CALLBACK_FUNCTION_HOLDER_H_ - -#include "base/memory/scoped_ptr.h" -#include "cobalt/script/mozjs/mozjs_callback_function.h" -#include "cobalt/script/script_object.h" - -namespace cobalt { -namespace script { -namespace mozjs { - -// Implementation of the ScriptObject interface for JSCCallbackFunctions. -template <typename CallbackFunction> -class MozjsCallbackFunctionHolder : public ScriptObject<CallbackFunction> { - public: - typedef MozjsCallbackFunction<typename CallbackFunction::Signature> - MozjsCallbackFunctionClass; - typedef ScriptObject<CallbackFunction> BaseClass; - - void RegisterOwner(Wrappable* owner) OVERRIDE { NOTIMPLEMENTED(); } - - void DeregisterOwner(Wrappable* owner) OVERRIDE { NOTIMPLEMENTED(); } - - const CallbackFunction* GetScriptObject() const OVERRIDE { - NOTIMPLEMENTED(); - return NULL; - } - - scoped_ptr<BaseClass> MakeCopy() const OVERRIDE { - NOTIMPLEMENTED(); - return scoped_ptr<BaseClass>(); - } - - bool EqualTo(const BaseClass& other) const OVERRIDE { - NOTIMPLEMENTED(); - return false; - } -}; - -} // namespace mozjs -} // namespace script -} // namespace cobalt - -#endif // COBALT_SCRIPT_MOZJS_MOZJS_CALLBACK_FUNCTION_HOLDER_H_
diff --git a/src/cobalt/script/mozjs/mozjs_callback_interface.cc b/src/cobalt/script/mozjs/mozjs_callback_interface.cc new file mode 100644 index 0000000..90aa178 --- /dev/null +++ b/src/cobalt/script/mozjs/mozjs_callback_interface.cc
@@ -0,0 +1,58 @@ +/* + * 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/script/mozjs/mozjs_callback_interface.h" + +#include "base/logging.h" + +namespace cobalt { +namespace script { +namespace mozjs { + +// Helper class to get the actual callable object from a JSObject implementing +// a callback interface. +// Returns true if a callable was found, and false if not. +bool GetCallableForCallbackInterface(JSContext* context, + JS::HandleObject implementing_object, + const char* property_name, + JS::MutableHandleValue out_callable) { + DCHECK(implementing_object); + DCHECK(property_name); + + if (JS_ObjectIsCallable(context, implementing_object)) { + out_callable.set(OBJECT_TO_JSVAL(implementing_object)); + return true; + } + // Implementing object is not callable. Check for a callable property of the + // specified name. + JS::RootedValue property(context); + if (JS_GetProperty(context, implementing_object, property_name, + property.address())) { + if (property.isObject() && + JS_ObjectIsCallable(context, JSVAL_TO_OBJECT(property))) { + out_callable.set(property); + return true; + } + } + + // Implementing object is not callable, nor does it have a callable property + // of the specified name. + return false; +} + +} // namespace mozjs +} // namespace script +} // namespace cobalt
diff --git a/src/cobalt/script/mozjs/mozjs_callback_interface.h b/src/cobalt/script/mozjs/mozjs_callback_interface.h new file mode 100644 index 0000000..321682a --- /dev/null +++ b/src/cobalt/script/mozjs/mozjs_callback_interface.h
@@ -0,0 +1,39 @@ +/* + * 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_SCRIPT_MOZJS_MOZJS_CALLBACK_INTERFACE_H_ +#define COBALT_SCRIPT_MOZJS_MOZJS_CALLBACK_INTERFACE_H_ + +#include "cobalt/script/callback_interface_traits.h" +#include "third_party/mozjs/js/src/jsapi.h" + +namespace cobalt { +namespace script { +namespace mozjs { + +// Helper class to get the actual callable object from a JSObject implementing +// a callback interface. +// Returns true if a callable was found, and false if not. +bool GetCallableForCallbackInterface(JSContext* context, + JS::HandleObject implementing_object, + const char* property_name, + JS::MutableHandleValue out_callable); + +} // namespace mozjs +} // namespace script +} // namespace cobalt + +#endif // COBALT_SCRIPT_MOZJS_MOZJS_CALLBACK_INTERFACE_H_
diff --git a/src/cobalt/script/mozjs/mozjs_callback_interface_holder.h b/src/cobalt/script/mozjs/mozjs_callback_interface_holder.h index d9f09ea..009acd5 100644 --- a/src/cobalt/script/mozjs/mozjs_callback_interface_holder.h +++ b/src/cobalt/script/mozjs/mozjs_callback_interface_holder.h
@@ -18,37 +18,30 @@ #define COBALT_SCRIPT_MOZJS_MOZJS_CALLBACK_INTERFACE_HOLDER_H_ #include "base/memory/scoped_ptr.h" -#include "cobalt/script/script_object.h" +#include "cobalt/script/callback_interface_traits.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/type_traits.h" namespace cobalt { namespace script { namespace mozjs { -template <typename CallbackInterface> -class MozjsCallbackInterfaceHolder : public ScriptObject<CallbackInterface> { +template <typename MozjsCallbackInterface> +class MozjsCallbackInterfaceHolder + : public MozjsUserObjectHolder<MozjsCallbackInterface> { public: - typedef typename CallbackInterfaceTraits< - CallbackInterface>::MozjsCallbackInterfaceClass MozjsCallbackInterface; - typedef ScriptObject<CallbackInterface> BaseClass; + typedef MozjsUserObjectHolder<MozjsCallbackInterface> BaseClass; + MozjsCallbackInterfaceHolder() {} + MozjsCallbackInterfaceHolder(JS::HandleObject object, JSContext* context, + WrapperFactory* wrapper_factory) + : BaseClass(object, context, wrapper_factory) {} +}; - void RegisterOwner(Wrappable* owner) OVERRIDE { NOTIMPLEMENTED(); } - - void DeregisterOwner(Wrappable* owner) OVERRIDE { NOTIMPLEMENTED(); } - - const CallbackInterface* GetScriptObject() const OVERRIDE { - NOTIMPLEMENTED(); - return NULL; - } - - scoped_ptr<ScriptObject<CallbackInterface> > MakeCopy() const OVERRIDE { - NOTIMPLEMENTED(); - return scoped_ptr<ScriptObject<CallbackInterface> >(); - } - - bool EqualTo(const BaseClass& other) const OVERRIDE { - NOTIMPLEMENTED(); - return false; - } +template <typename CallbackInterface> +struct TypeTraits<CallbackInterfaceTraits<CallbackInterface> > { + typedef MozjsCallbackInterfaceHolder<typename CallbackInterfaceTraits< + CallbackInterface>::MozjsCallbackInterfaceClass> ConversionType; + typedef const ScriptObject<CallbackInterface>* ReturnType; }; } // namespace mozjs
diff --git a/src/cobalt/script/mozjs/mozjs_debugger.cc b/src/cobalt/script/mozjs/mozjs_debugger.cc new file mode 100644 index 0000000..e4ae668 --- /dev/null +++ b/src/cobalt/script/mozjs/mozjs_debugger.cc
@@ -0,0 +1,67 @@ +/* + * 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/script/mozjs/mozjs_debugger.h" + +#include "base/logging.h" + +namespace cobalt { +namespace script { + +// Static factory method declared in public interface. +scoped_ptr<ScriptDebugger> ScriptDebugger::CreateDebugger( + GlobalObjectProxy* global_object_proxy, Delegate* delegate) { + return scoped_ptr<ScriptDebugger>( + new mozjs::MozjsDebugger(global_object_proxy, delegate)); +} + +namespace mozjs { + +MozjsDebugger::MozjsDebugger(GlobalObjectProxy* global_object_proxy, + Delegate* delegate) { + NOTIMPLEMENTED(); +} + +MozjsDebugger::~MozjsDebugger() { NOTIMPLEMENTED(); } + +void MozjsDebugger::Attach() { NOTIMPLEMENTED(); } + +void MozjsDebugger::Detach() { NOTIMPLEMENTED(); } + +void MozjsDebugger::Pause() { NOTIMPLEMENTED(); } + +void MozjsDebugger::Resume() { NOTIMPLEMENTED(); } + +void MozjsDebugger::SetBreakpoint(const std::string& script_id, int line_number, + int column_number) { + NOTIMPLEMENTED(); +} + +script::ScriptDebugger::PauseOnExceptionsState +MozjsDebugger::SetPauseOnExceptions(PauseOnExceptionsState state) { + NOTIMPLEMENTED(); + return kNone; +} + +void MozjsDebugger::StepInto() { NOTIMPLEMENTED(); } + +void MozjsDebugger::StepOut() { NOTIMPLEMENTED(); } + +void MozjsDebugger::StepOver() { NOTIMPLEMENTED(); } + +} // namespace mozjs +} // namespace script +} // namespace cobalt
diff --git a/src/cobalt/script/mozjs/mozjs_debugger.h b/src/cobalt/script/mozjs/mozjs_debugger.h new file mode 100644 index 0000000..63fd7f2 --- /dev/null +++ b/src/cobalt/script/mozjs/mozjs_debugger.h
@@ -0,0 +1,50 @@ +/* + * 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_SCRIPT_MOZJS_MOZJS_DEBUGGER_H_ +#define COBALT_SCRIPT_MOZJS_MOZJS_DEBUGGER_H_ + +#include <string> + +#include "cobalt/script/script_debugger.h" + +namespace cobalt { +namespace script { +namespace mozjs { + +class MozjsDebugger : public ScriptDebugger { + public: + MozjsDebugger(GlobalObjectProxy* global_object_proxy, Delegate* delegate); + ~MozjsDebugger() OVERRIDE; + + // Implementation of ScriptDebugger. + void Attach() OVERRIDE; + void Detach() OVERRIDE; + void Pause() OVERRIDE; + void Resume() OVERRIDE; + void SetBreakpoint(const std::string& script_id, int line_number, + int column_number) OVERRIDE; + PauseOnExceptionsState SetPauseOnExceptions( + PauseOnExceptionsState state) OVERRIDE; + void StepInto() OVERRIDE; + void StepOut() OVERRIDE; + void StepOver() OVERRIDE; +}; + +} // namespace mozjs +} // namespace script +} // namespace cobalt + +#endif // COBALT_SCRIPT_MOZJS_MOZJS_DEBUGGER_H_
diff --git a/src/cobalt/script/mozjs/mozjs_exception_state.cc b/src/cobalt/script/mozjs/mozjs_exception_state.cc index 607c123..a4c575b 100644 --- a/src/cobalt/script/mozjs/mozjs_exception_state.cc +++ b/src/cobalt/script/mozjs/mozjs_exception_state.cc
@@ -55,18 +55,15 @@ void MozjsExceptionState::SetSimpleException( SimpleExceptionType simple_exception, const std::string& message) { DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(!is_exception_set_); std::stringstream stream; stream << SimpleExceptionToString(simple_exception) << ": " << message; - // JS_ReportWarning first builds an error message from the given sprintf-style + // JS_ReportError first builds an error message from the given sprintf-style // format string and any additional arguments passed after it. The resulting // error message is passed to the context's JSErrorReporter callback. - JS_ReportWarning(context_, stream.str().c_str()); -} - -bool MozjsExceptionState::IsExceptionSet() { - // TODO: Implement this. - return false; + JS_ReportError(context_, stream.str().c_str()); + is_exception_set_ = true; } } // namespace mozjs
diff --git a/src/cobalt/script/mozjs/mozjs_exception_state.h b/src/cobalt/script/mozjs/mozjs_exception_state.h index af8d13b..4a3c11d 100644 --- a/src/cobalt/script/mozjs/mozjs_exception_state.h +++ b/src/cobalt/script/mozjs/mozjs_exception_state.h
@@ -28,15 +28,17 @@ class MozjsExceptionState : public ExceptionState { public: - explicit MozjsExceptionState(JSContext* context) : context_(context) {} + explicit MozjsExceptionState(JSContext* context) + : is_exception_set_(false), context_(context) {} // ExceptionState interface void SetException(const scoped_refptr<ScriptException>& exception) OVERRIDE; void SetSimpleException(SimpleExceptionType simple_exception, const std::string& message) OVERRIDE; - bool IsExceptionSet(); + bool is_exception_set() const { return is_exception_set_; } private: + bool is_exception_set_; JSContext* context_; base::ThreadChecker thread_checker_; };
diff --git a/src/cobalt/script/mozjs/mozjs_global_object_proxy.cc b/src/cobalt/script/mozjs/mozjs_global_object_proxy.cc index 0f394ef..43c45bc 100644 --- a/src/cobalt/script/mozjs/mozjs_global_object_proxy.cc +++ b/src/cobalt/script/mozjs/mozjs_global_object_proxy.cc
@@ -184,8 +184,9 @@ const scoped_refptr<Wrappable>& impl) { JSAutoRequest auto_request(context_); JSAutoCompartment auto_comparment(context_, global_object_); - JS::RootedObject wrapper(context_, wrapper_factory_->GetWrapper(impl)); - JS::Value wrapper_value = JS::ObjectValue(*wrapper.get()); + JS::RootedObject wrapper_proxy(context_, + wrapper_factory_->GetWrapperProxy(impl)); + JS::Value wrapper_value = OBJECT_TO_JSVAL(wrapper_proxy); bool success = JS_SetProperty(context_, global_object_, identifier.c_str(), &wrapper_value); DCHECK(success);
diff --git a/src/cobalt/script/mozjs/mozjs_object_handle.h b/src/cobalt/script/mozjs/mozjs_object_handle.h index 4c2d5d0..6e59df8 100644 --- a/src/cobalt/script/mozjs/mozjs_object_handle.h +++ b/src/cobalt/script/mozjs/mozjs_object_handle.h
@@ -18,6 +18,7 @@ #include "base/optional.h" #include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/type_traits.h" #include "cobalt/script/opaque_handle.h" #include "third_party/mozjs/js/src/jsapi.h" @@ -31,12 +32,12 @@ // a ScriptObject<OpaqueHandle>. class MozjsObjectHandle : public OpaqueHandle { public: - typedef MozjsUserObjectHolder<MozjsObjectHandle> HolderType; typedef OpaqueHandle BaseType; JSObject* handle() const { return handle_; } private: - explicit MozjsObjectHandle(JS::HandleObject object) : handle_(object) {} + MozjsObjectHandle(JSContext*, JS::HandleObject object) + : handle_(object) {} ~MozjsObjectHandle() {} // Note that this class does not root this JS::Heap<> object. Rooting of this @@ -50,6 +51,12 @@ typedef MozjsUserObjectHolder<MozjsObjectHandle> MozjsObjectHandleHolder; +template <> +struct TypeTraits<OpaqueHandle> { + typedef MozjsObjectHandleHolder ConversionType; + typedef const ScriptObject<OpaqueHandle>* ReturnType; +}; + } // namespace mozjs } // namespace script } // namespace cobalt
diff --git a/src/cobalt/script/mozjs/mozjs_property_enumerator.cc b/src/cobalt/script/mozjs/mozjs_property_enumerator.cc new file mode 100644 index 0000000..10db0b5 --- /dev/null +++ b/src/cobalt/script/mozjs/mozjs_property_enumerator.cc
@@ -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. + */ +#include "cobalt/script/mozjs/mozjs_property_enumerator.h" + +#include "base/logging.h" + +namespace cobalt { +namespace script { +namespace mozjs { + +MozjsPropertyEnumerator::MozjsPropertyEnumerator(JSContext* context, + JS::AutoIdVector* properties) + : context_(context), properties_(properties) {} + +void MozjsPropertyEnumerator::AddProperty(const std::string& property_name) { + JS::RootedString property_string( + context_, JS_NewStringCopyZ(context_, property_name.c_str())); + JS::RootedId id(context_); + if (JS_ValueToId(context_, STRING_TO_JSVAL(property_string), id.address())) { + properties_->append(id); + } else { + NOTREACHED(); + } +} + +} // namespace mozjs +} // namespace script +} // namespace cobalt
diff --git a/src/cobalt/script/mozjs/mozjs_property_enumerator.h b/src/cobalt/script/mozjs/mozjs_property_enumerator.h new file mode 100644 index 0000000..6ad2553 --- /dev/null +++ b/src/cobalt/script/mozjs/mozjs_property_enumerator.h
@@ -0,0 +1,43 @@ +/* + * 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_SCRIPT_MOZJS_MOZJS_PROPERTY_ENUMERATOR_H_ +#define COBALT_SCRIPT_MOZJS_MOZJS_PROPERTY_ENUMERATOR_H_ + +#include <string> + +#include "base/compiler_specific.h" +#include "cobalt/script/property_enumerator.h" +#include "third_party/mozjs/js/src/jsapi.h" + +namespace cobalt { +namespace script { +namespace mozjs { + +class MozjsPropertyEnumerator : public cobalt::script::PropertyEnumerator { + public: + MozjsPropertyEnumerator(JSContext* context, JS::AutoIdVector* properties); + void AddProperty(const std::string& property_name) OVERRIDE; + + private: + JSContext* context_; + JS::AutoIdVector* properties_; +}; + +} // namespace mozjs +} // namespace script +} // namespace cobalt + +#endif // COBALT_SCRIPT_MOZJS_MOZJS_PROPERTY_ENUMERATOR_H_
diff --git a/src/cobalt/script/mozjs/mozjs_user_object_holder.h b/src/cobalt/script/mozjs/mozjs_user_object_holder.h index bcd0cf1..0551bff 100644 --- a/src/cobalt/script/mozjs/mozjs_user_object_holder.h +++ b/src/cobalt/script/mozjs/mozjs_user_object_holder.h
@@ -19,6 +19,7 @@ #include "cobalt/base/polymorphic_downcast.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "cobalt/script/script_object.h" #include "third_party/mozjs/js/src/jsapi.h" namespace cobalt { @@ -39,9 +40,9 @@ MozjsUserObjectHolder() : context_(NULL), wrapper_factory_(NULL) {} - explicit MozjsUserObjectHolder(JS::HandleObject object, JSContext* context, - WrapperFactory* wrapper_factory) - : object_handle_(MozjsUserObjectType(object)), + MozjsUserObjectHolder(JS::HandleObject object, JSContext* context, + WrapperFactory* wrapper_factory) + : object_handle_(MozjsUserObjectType(context, object)), context_(context), wrapper_factory_(wrapper_factory) {}
diff --git a/src/cobalt/script/mozjs/mozjs_wrapper_handle.h b/src/cobalt/script/mozjs/mozjs_wrapper_handle.h index df014d9..3f8ef37 100644 --- a/src/cobalt/script/mozjs/mozjs_wrapper_handle.h +++ b/src/cobalt/script/mozjs/mozjs_wrapper_handle.h
@@ -35,12 +35,12 @@ weak_wrapper_private_ = wrapper_private->AsWeakPtr(); } - static JSObject* GetJSObject(const Wrappable::WeakWrapperHandle* handle) { + static JSObject* GetObjectProxy(const Wrappable::WeakWrapperHandle* handle) { if (handle) { const MozjsWrapperHandle* mozjs_handle = base::polymorphic_downcast<const MozjsWrapperHandle*>(handle); if (mozjs_handle->weak_wrapper_private_) { - return mozjs_handle->weak_wrapper_private_->js_object(); + return mozjs_handle->weak_wrapper_private_->js_object_proxy(); } } return NULL;
diff --git a/src/cobalt/script/mozjs/proxy_handler.cc b/src/cobalt/script/mozjs/proxy_handler.cc new file mode 100644 index 0000000..17849cd --- /dev/null +++ b/src/cobalt/script/mozjs/proxy_handler.cc
@@ -0,0 +1,261 @@ +/* + * 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/script/mozjs/proxy_handler.h" + +#include "cobalt/script/mozjs/conversion_helpers.h" +#include "cobalt/script/mozjs/mozjs_exception_state.h" + +namespace cobalt { +namespace script { +namespace mozjs { + +ProxyHandler::ProxyHandler(const IndexedPropertyHooks& indexed_hooks, + const NamedPropertyHooks& named_hooks) + : js::DirectProxyHandler(NULL), + indexed_property_hooks_(indexed_hooks), + named_property_hooks_(named_hooks) { + // If an interface supports named/indexed properties, they must have a hook to + // check if the name/index is supported and to enumerate the properties. + if (supports_named_properties()) { + DCHECK(named_property_hooks_.is_supported); + DCHECK(named_property_hooks_.enumerate_supported); + } + if (supports_indexed_properties()) { + DCHECK(indexed_property_hooks_.is_supported); + DCHECK(indexed_property_hooks_.enumerate_supported); + } +} + +JSObject* ProxyHandler::NewProxy(JSContext* context, JSObject* object, + JSObject* prototype, JSObject* parent, + ProxyHandler* handler) { + JS::RootedValue as_value(context, OBJECT_TO_JSVAL(object)); + return js::NewProxyObject(context, handler, as_value, prototype, parent); +} + +bool ProxyHandler::getPropertyDescriptor(JSContext* context, + JS::HandleObject proxy, + JS::HandleId id, + JSPropertyDescriptor* descriptor, + unsigned flags) { + // https://www.w3.org/TR/WebIDL/#getownproperty + if (supports_named_properties() || supports_indexed_properties()) { + // Convert the id to a JSValue, so we can easily convert it to Uint32 and + // JSString. + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } + JS::RootedObject object(context, js::GetProxyTargetObject(proxy)); + if (supports_indexed_properties()) { + // If the interface supports indexed properties and this is an array index + // property name, and it is a supported property index. + uint32_t index; + if (IsArrayIndexPropertyName(context, id_value, &index) && + IsSupportedIndex(context, object, index)) { + descriptor->obj = object; + descriptor->attrs = JSPROP_SHARED | JSPROP_INDEX | JSPROP_ENUMERATE; + descriptor->getter = indexed_property_hooks_.getter; + if (indexed_property_hooks_.setter) { + descriptor->setter = indexed_property_hooks_.setter; + } else { + descriptor->attrs |= JSPROP_READONLY; + } + return true; + } + } + if (supports_named_properties()) { + std::string property_name; + MozjsExceptionState exception_state(context); + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, + &property_name); + if (exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } + if (IsNamedPropertyVisible(context, object, property_name)) { + descriptor->obj = object; + descriptor->attrs = JSPROP_SHARED | JSPROP_ENUMERATE; + descriptor->getter = named_property_hooks_.getter; + if (named_property_hooks_.setter) { + descriptor->setter = named_property_hooks_.setter; + } else { + descriptor->attrs |= JSPROP_READONLY; + } + return true; + } + } + } + return js::DirectProxyHandler::getPropertyDescriptor(context, proxy, id, + descriptor, flags); +} + +bool ProxyHandler::delete_(JSContext* context, JS::HandleObject proxy, + JS::HandleId id, bool* succeeded) { + // https://www.w3.org/TR/WebIDL/#delete + if (supports_named_properties() || supports_indexed_properties()) { + // Convert the id to a JSValue, so we can easily convert it to Uint32 and + // JSString. + JS::RootedValue id_value(context); + if (!JS_IdToValue(context, id, id_value.address())) { + NOTREACHED(); + return false; + } + DCHECK(js::IsProxy(proxy)); + JS::RootedObject object(context, js::GetProxyTargetObject(proxy)); + if (supports_indexed_properties()) { + // If the interface supports indexed properties and this is an array index + // property name, and it is a supported property index. + uint32_t index; + // 1. If O supports indexed properties and P is an array index property + // name, + // then: + if (IsArrayIndexPropertyName(context, id_value, &index)) { + if (!IsSupportedIndex(context, object, index)) { + // 1.2. If index is not a supported property index, then return true. + *succeeded = true; + } else if (!indexed_property_hooks_.deleter) { + // 1.3. If O does not implement an interface with an indexed property + // deleter, then Reject. + *succeeded = false; + } else { + *succeeded = indexed_property_hooks_.deleter(context, object, index); + } + return true; + } + } + if (supports_named_properties()) { + std::string property_name; + MozjsExceptionState exception_state(context); + FromJSValue(context, id_value, kNoConversionFlags, &exception_state, + &property_name); + if (exception_state.is_exception_set()) { + // The ID should be an integer or a string, so we shouldn't have any + // exceptions converting to string. + NOTREACHED(); + return false; + } + if (IsNamedPropertyVisible(context, object, property_name)) { + if (!named_property_hooks_.deleter) { + *succeeded = false; + } else { + *succeeded = + named_property_hooks_.deleter(context, object, property_name); + } + return true; + } + } + } + return js::DirectProxyHandler::delete_(context, proxy, id, succeeded); +} + +bool ProxyHandler::enumerate(JSContext* context, JS::HandleObject proxy, + JS::AutoIdVector& properties) { + // https://www.w3.org/TR/WebIDL/#property-enumeration + // Indexed properties go first, then named properties, then everything else. + JS::RootedObject object(context, js::GetProxyTargetObject(proxy)); + if (supports_indexed_properties()) { + indexed_property_hooks_.enumerate_supported(context, object, &properties); + } + if (supports_named_properties()) { + named_property_hooks_.enumerate_supported(context, object, &properties); + } + return js::DirectProxyHandler::enumerate(context, proxy, properties); +} + +bool ProxyHandler::IsSupportedIndex(JSContext* context, JS::HandleObject object, + uint32_t index) { + DCHECK(indexed_property_hooks_.is_supported); + return indexed_property_hooks_.is_supported(context, object, index); +} + +bool ProxyHandler::IsSupportedName(JSContext* context, JS::HandleObject object, + const std::string& name) { + DCHECK(named_property_hooks_.is_supported); + return named_property_hooks_.is_supported(context, object, name); +} + +bool ProxyHandler::IsArrayIndexPropertyName(JSContext* context, + JS::HandleValue property_value, + uint32_t* out_index) { + // https://www.w3.org/TR/WebIDL/#dfn-array-index-property-name + // 1. Let i be ToUint32(P). + uint32_t index; + if (!JS::ToUint32(context, property_value, &index)) { + return false; + } + + // 3. If i = 2^32 - 1, then return false. + if (index == 0xFFFFFFFF) { + return false; + } + + // 2. Let s be ToString(i). + // 3. If s != P then return false. + JSBool are_equal; + JS::RootedString index_as_string( + context, JS_ValueToString(context, UINT_TO_JSVAL(index))); + if (!JS_LooselyEqual(context, JS::StringValue(index_as_string), + property_value, &are_equal) || + !are_equal) { + return false; + } + + // 4. Return true. + *out_index = index; + return true; +} + +bool ProxyHandler::IsNamedPropertyVisible(JSContext* context, + JS::HandleObject object, + const std::string& property_name) { + // Named property visiblity algorithm. + // https://www.w3.org/TR/WebIDL/#dfn-named-property-visibility + + // 1. If P is an unforgeable property name on O, then return false. + // 2. If O implements an interface with an [Unforgeable]-annotated attribute + // whose identifier is P, then return false. + // TODO: Implement Unforgeable extended attribute. + + // 3. If P is not a supported property name of O, then return false. + if (!IsSupportedName(context, object, property_name)) { + return false; + } + + // 4. If O implements an interface that has the [OverrideBuiltins] extended + // attribute, then return true. + // TODO: Implement OverrideBuiltins extended attribute + + // 5. If O has an own property named P, then return false. + // 6~7. ( Walk the prototype chain and if the prootype has P, return false) + + JSBool found_property; + if (!JS_HasProperty(context, object, property_name.c_str(), + &found_property)) { + // An error occurred searching for the property. + NOTREACHED(); + return true; + } + return !found_property; +} + +} // namespace mozjs +} // namespace script +} // namespace cobalt
diff --git a/src/cobalt/script/mozjs/proxy_handler.h b/src/cobalt/script/mozjs/proxy_handler.h new file mode 100644 index 0000000..e6a7c54 --- /dev/null +++ b/src/cobalt/script/mozjs/proxy_handler.h
@@ -0,0 +1,164 @@ +/* + * 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_SCRIPT_MOZJS_PROXY_HANDLER_H_ +#define COBALT_SCRIPT_MOZJS_PROXY_HANDLER_H_ + +#include <string> + +#include "base/compiler_specific.h" +#include "base/logging.h" +#include "third_party/mozjs/js/src/jsapi.h" +#include "third_party/mozjs/js/src/jsproxy.h" + +namespace cobalt { +namespace script { +namespace mozjs { + +// SpiderMonkey has a concept of a Proxy object which is associated with another +// arbitrary object and a js::BaseProxyHandler interface. The handler interface +// provides a number of traps for providing custom implementations of +// fundamental ECMAScript operations such as getPropertyDescriptor. +// +// The implementation of each trap in the js::DirectProxyHandler class simply +// forwards each trap to the target object. +// +// In defining a JSClass a number of function pointers can be set that will +// be called when getting, setting, deleting, etc. a property, but these do not +// map well onto the Web IDL spec for implementing interfaces that support named +// and indexed properties. +// +// See third_party/mozjs/js/src/jsproxy.h for more details. +// +// ProxyHandler provides custom traps for getPropertyDescriptor, delete_, and +// enumerate to implement interfaces that support named and indexed properties. +class ProxyHandler : public js::DirectProxyHandler { + public: + typedef bool (*IsSupportedIndexFunction)(JSContext*, JS::HandleObject, + uint32_t); + typedef bool (*IsSupportedNameFunction)(JSContext*, JS::HandleObject, + const std::string&); + typedef void (*EnumerateSupportedIndexesFunction)(JSContext*, + JS::HandleObject, + JS::AutoIdVector*); + typedef void (*EnumerateSupportedNamesFunction)(JSContext*, JS::HandleObject, + JS::AutoIdVector*); + typedef bool (*IndexedDeleteFunction)(JSContext*, JS::HandleObject, uint32_t); + typedef bool (*NamedDeleteFunction)(JSContext*, JS::HandleObject, + const std::string&); + + // Hooks for interfaces that support indexed properties. + struct IndexedPropertyHooks { + IsSupportedIndexFunction is_supported; + EnumerateSupportedIndexesFunction enumerate_supported; + JSPropertyOp getter; + JSStrictPropertyOp setter; + IndexedDeleteFunction deleter; + }; + + // Hooks for interfaces that support named properties. + struct NamedPropertyHooks { + IsSupportedNameFunction is_supported; + EnumerateSupportedNamesFunction enumerate_supported; + JSPropertyOp getter; + JSStrictPropertyOp setter; + NamedDeleteFunction deleter; + }; + + static JSObject* NewProxy(JSContext* context, JSObject* object, + JSObject* prototype, JSObject* parent, + ProxyHandler* handler); + + // Construct a new ProxyHandler with the provided hooks. + ProxyHandler(const IndexedPropertyHooks& indexed_hooks, + const NamedPropertyHooks& named_hooks); + + // Overridden fundamental traps. + bool getPropertyDescriptor(JSContext* context, JS::HandleObject proxy, + JS::HandleId id, JSPropertyDescriptor* descriptor, + unsigned flags) OVERRIDE; + bool delete_(JSContext* context, JS::HandleObject proxy, JS::HandleId id, + bool* succeeded) OVERRIDE; + bool enumerate(JSContext* context, JS::HandleObject proxy, + JS::AutoIdVector& properties) OVERRIDE; // NOLINT[runtime/references] + + // The derived traps in js::DirectProxyHandler are not implemented in terms of + // the fundamental traps, where the traps in js::BaseProxyHandler are. + // Redefining the derived traps to be in terms of the fundamental traps means + // that we only need to override the fundamental traps when implementing + // custom behavior for i.e. interfaces that support named properties. + bool has(JSContext* context, JS::HandleObject proxy, JS::HandleId id, + bool* bp) OVERRIDE { + return js::BaseProxyHandler::has(context, proxy, id, bp); + } + + bool hasOwn(JSContext* context, JS::HandleObject proxy, JS::HandleId id, + bool* bp) OVERRIDE { + return js::BaseProxyHandler::hasOwn(context, proxy, id, bp); + } + + bool get(JSContext* context, JS::HandleObject proxy, + JS::HandleObject receiver, JS::HandleId id, + JS::MutableHandleValue vp) OVERRIDE { + return js::BaseProxyHandler::get(context, proxy, receiver, id, vp); + } + + bool set(JSContext* context, JS::HandleObject proxy, + JS::HandleObject receiver, JS::HandleId id, bool strict, + JS::MutableHandleValue vp) OVERRIDE { + return js::BaseProxyHandler::set(context, proxy, receiver, id, strict, vp); + } + + bool keys(JSContext* context, JS::HandleObject proxy, + JS::AutoIdVector& props) OVERRIDE { // NOLINT[runtime/references] + return js::BaseProxyHandler::keys(context, proxy, props); + } + + bool iterate(JSContext* context, JS::HandleObject proxy, unsigned flags, + JS::MutableHandleValue vp) OVERRIDE { + return js::BaseProxyHandler::iterate(context, proxy, flags, vp); + } + + private: + bool supports_named_properties() { + return named_property_hooks_.getter != NULL; + } + + bool supports_indexed_properties() { + return indexed_property_hooks_.getter != NULL; + } + + bool IsSupportedIndex(JSContext* context, JS::HandleObject object, + uint32_t index); + + bool IsSupportedName(JSContext* context, JS::HandleObject object, + const std::string& name); + + bool IsArrayIndexPropertyName(JSContext* context, + JS::HandleValue property_value, + uint32_t* out_index); + + bool IsNamedPropertyVisible(JSContext* context, JS::HandleObject object, + const std::string& property_name); + + IndexedPropertyHooks indexed_property_hooks_; + NamedPropertyHooks named_property_hooks_; +}; + +} // namespace mozjs +} // namespace script +} // namespace cobalt + +#endif // COBALT_SCRIPT_MOZJS_PROXY_HANDLER_H_
diff --git a/src/cobalt/script/mozjs/type_traits.h b/src/cobalt/script/mozjs/type_traits.h index 6d17ea3..336db63 100644 --- a/src/cobalt/script/mozjs/type_traits.h +++ b/src/cobalt/script/mozjs/type_traits.h
@@ -17,13 +17,6 @@ #ifndef COBALT_SCRIPT_MOZJS_TYPE_TRAITS_H_ #define COBALT_SCRIPT_MOZJS_TYPE_TRAITS_H_ -#include "cobalt/script/callback_interface_traits.h" -#include "cobalt/script/mozjs/mozjs_callback_function_holder.h" -#include "cobalt/script/mozjs/mozjs_callback_interface_holder.h" -#include "cobalt/script/mozjs/mozjs_object_handle.h" -#include "cobalt/script/opaque_handle.h" -#include "cobalt/script/script_object.h" - namespace cobalt { namespace script { namespace mozjs { @@ -36,24 +29,6 @@ typedef T ReturnType; }; -template <> -struct TypeTraits<OpaqueHandle> { - typedef MozjsObjectHandleHolder ConversionType; - typedef const ScriptObject<OpaqueHandle>* ReturnType; -}; - -template <typename Sig> -struct TypeTraits<CallbackFunction<Sig> > { - typedef MozjsCallbackFunctionHolder<CallbackFunction<Sig> > ConversionType; - typedef const ScriptObject<CallbackFunction<Sig> >* ReturnType; -}; - -template <typename CallbackInterface> -struct TypeTraits<CallbackInterfaceTraits<CallbackInterface> > { - typedef MozjsCallbackInterfaceHolder<CallbackInterface> ConversionType; - typedef const ScriptObject<CallbackInterface>* ReturnType; -}; - } // namespace mozjs } // namespace script } // namespace cobalt
diff --git a/src/cobalt/script/mozjs/union_type_conversion_forward.h b/src/cobalt/script/mozjs/union_type_conversion_forward.h new file mode 100644 index 0000000..c001f65 --- /dev/null +++ b/src/cobalt/script/mozjs/union_type_conversion_forward.h
@@ -0,0 +1,70 @@ +// This file was GENERATED by command: +// pump.py union_type_conversion_forward.h.pump +// DO NOT EDIT BY HAND!!! + +/* + * 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_SCRIPT_MOZJS_UNION_TYPE_CONVERSION_FORWARD_H_ +#define COBALT_SCRIPT_MOZJS_UNION_TYPE_CONVERSION_FORWARD_H_ + +#include "cobalt/script/mozjs/mozjs_exception_state.h" +#include "cobalt/script/mozjs/mozjs_global_object_proxy.h" +#include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/type_traits.h" +#include "cobalt/script/union_type.h" + +// Forward declaration for ToJSValue and FromJSValue for IDL union types. + +namespace cobalt { +namespace script { +namespace mozjs { + +template <typename T1, typename T2> +void ToJSValue(JSContext* context, const script::UnionType2<T1, T2>& in_union, + JS::MutableHandleValue out_value); + +template <typename T1, typename T2> +void FromJSValue(JSContext* context, JS::HandleValue value, + int conversion_flags, ExceptionState* exception_state, + script::UnionType2<T1, T2>* out_union); + +template <typename T1, typename T2, typename T3> +void ToJSValue(JSContext* context, + const script::UnionType3<T1, T2, T3>& in_union, + JS::MutableHandleValue out_value); + +template <typename T1, typename T2, typename T3> +void FromJSValue(JSContext* context, JS::HandleValue value, + int conversion_flags, ExceptionState* exception_state, + script::UnionType3<T1, T2, T3>* out_union); + +template <typename T1, typename T2, typename T3, typename T4> +void ToJSValue(JSContext* context, + const script::UnionType4<T1, T2, T3, T4>& in_union, + JS::MutableHandleValue out_value); + +template <typename T1, typename T2, typename T3, typename T4> +void FromJSValue(JSContext* context, JS::HandleValue value, + int conversion_flags, ExceptionState* exception_state, + script::UnionType4<T1, T2, T3, T4>* out_union); + +} // namespace mozjs +} // namespace script +} // namespace cobalt + +#endif // COBALT_SCRIPT_MOZJS_UNION_TYPE_CONVERSION_FORWARD_H_
diff --git a/src/cobalt/script/mozjs/union_type_conversion_forward.h.pump b/src/cobalt/script/mozjs/union_type_conversion_forward.h.pump new file mode 100644 index 0000000..876b511 --- /dev/null +++ b/src/cobalt/script/mozjs/union_type_conversion_forward.h.pump
@@ -0,0 +1,60 @@ +$$ This is a pump file for generating file templates. Pump is a python +$$ script that is part of the Google Test suite of utilities. Description +$$ can be found here: +$$ +$$ http://code.google.com/p/googletest/wiki/PumpManual +$$ + +$$ Maximum number of different member types in a union. +$var MAX_MEMBERS = 4 +/* + * 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_SCRIPT_MOZJS_UNION_TYPE_CONVERSION_FORWARD_H_ +#define COBALT_SCRIPT_MOZJS_UNION_TYPE_CONVERSION_FORWARD_H_ + +#include "cobalt/script/mozjs/mozjs_exception_state.h" +#include "cobalt/script/mozjs/mozjs_global_object_proxy.h" +#include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/type_traits.h" +#include "cobalt/script/union_type.h" + +// Forward declaration for ToJSValue and FromJSValue for IDL union types. + +namespace cobalt { +namespace script { +namespace mozjs { + +$range NUM_MEMBERS 2..MAX_MEMBERS +$for NUM_MEMBERS [[ +$range TYPE 1..NUM_MEMBERS + +template <$for TYPE , [[typename T$(TYPE)]]> +void ToJSValue(JSContext* context, const script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>& in_union, JS::MutableHandleValue out_value); + +template <$for TYPE , [[typename T$(TYPE)]]> +void FromJSValue(JSContext* context, JS::HandleValue value, + int conversion_flags, ExceptionState* exception_state, + script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>* out_union); + +]] $$ for NUM_MEMBERS + +} // namespace mozjs +} // namespace script +} // namespace cobalt + +#endif // COBALT_SCRIPT_MOZJS_UNION_TYPE_CONVERSION_FORWARD_H_
diff --git a/src/cobalt/script/mozjs/union_type_conversion_impl.h b/src/cobalt/script/mozjs/union_type_conversion_impl.h new file mode 100644 index 0000000..5d0076f --- /dev/null +++ b/src/cobalt/script/mozjs/union_type_conversion_impl.h
@@ -0,0 +1,635 @@ +// This file was GENERATED by command: +// pump.py union_type_conversion_impl.h.pump +// DO NOT EDIT BY HAND!!! + +/* + * 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_SCRIPT_MOZJS_UNION_TYPE_CONVERSION_IMPL_H_ +#define COBALT_SCRIPT_MOZJS_UNION_TYPE_CONVERSION_IMPL_H_ + +#include "cobalt/base/type_id.h" +#include "cobalt/script/mozjs/mozjs_exception_state.h" +#include "cobalt/script/mozjs/mozjs_global_object_proxy.h" +#include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/type_traits.h" +#include "cobalt/script/union_type.h" + +// Conversion to/from JS::Value for IDL union types. + +namespace cobalt { +namespace script { +namespace mozjs { + +template <typename T1, typename T2> +void ToJSValue(JSContext* context, const script::UnionType2<T1, T2>& in_union, + JS::MutableHandleValue out_value) { + if (in_union.template IsType<T1>()) { + ToJSValue(context, in_union.template AsType<T1>(), out_value); + return; + } + if (in_union.template IsType<T2>()) { + ToJSValue(context, in_union.template AsType<T2>(), out_value); + return; + } + NOTREACHED(); + out_value.setUndefined(); +} + +template <typename T1, typename T2> +void FromJSValue(JSContext* context, JS::HandleValue value, + int conversion_flags, ExceptionState* exception_state, + script::UnionType2<T1, T2>* out_union) { + DCHECK_EQ(0, conversion_flags); + // JS -> IDL type conversion procedure described here: + // http://heycam.github.io/webidl/#es-union + + // 1. If the union type includes a nullable type and V is null or undefined, + // then return the IDL value null. + if (value.isNull() || value.isUndefined()) { + // If the type was nullable or undefined, we should have caught that as a + // part of the base::optional<T> conversion. + NOTREACHED(); + return; + } + // Typedef for readability. + typedef ::cobalt::script::internal::UnionTypeTraits<T1> UnionTypeTraitsT1; + typedef ::cobalt::script::internal::UnionTypeTraits<T2> UnionTypeTraitsT2; + + // Forward declare all potential types + T1 t1; + T2 t2; + + // 3.1 If types includes an interface type that V implements, then return the + // IDL value that is a reference to the object V. + // 3.2 If types includes object, then return the IDL value that is a reference + // to the object V. + // + // The specification doesn't dictate what should happen if V implements more + // than one of the interfaces. For example, if V implements interface B and + // interface B inherits from interface A, what happens if both A and B are + // union members? Blink doesn't seem to do anything special for this case. + // Just choose the first interface in the flattened members that matches. + if (value.isObject()) { + JS::RootedObject rooted_object(context); + bool success = JS_ValueToObject(context, value, rooted_object.address()); + DCHECK(success); + MozjsGlobalObjectProxy* global_object_proxy = + static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context)); + const WrapperFactory* wrapper_factory = + global_object_proxy->wrapper_factory(); + if (UnionTypeTraitsT1::is_interface_type && + wrapper_factory->DoesObjectImplementInterface( + rooted_object, UnionTypeTraitsT1::GetTypeID())) { + FromJSValue(context, value, conversion_flags, exception_state, &t1); + *out_union = script::UnionType2<T1, T2>(t1); + return; + } + if (UnionTypeTraitsT2::is_interface_type && + wrapper_factory->DoesObjectImplementInterface( + rooted_object, UnionTypeTraitsT2::GetTypeID())) { + FromJSValue(context, value, conversion_flags, exception_state, &t2); + *out_union = script::UnionType2<T1, T2>(t2); + return; + } + } + + // TODO: Support Date, RegExp, DOMException, Error, ArrayBuffer, DataView, + // TypedArrayName, callback functions, dictionary, array type. + // And sequences if necessary. + + // 14. If V is a Boolean value, then: + // 1. If types includes a boolean, then return the result of converting V + // to boolean. + if (value.isBoolean()) { + if (UnionTypeTraitsT1::is_boolean_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t1); + *out_union = script::UnionType2<T1, T2>(t1); + return; + } + + if (UnionTypeTraitsT2::is_boolean_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t2); + *out_union = script::UnionType2<T1, T2>(t2); + return; + } + } + + // 15. If V is a Number value, then: + // 1. If types includes a numeric type, then return the result of converting + // V to that numeric type. + if (value.isNumber()) { + if (UnionTypeTraitsT1::is_numeric_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t1); + *out_union = script::UnionType2<T1, T2>(t1); + return; + } + + if (UnionTypeTraitsT2::is_numeric_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t2); + *out_union = script::UnionType2<T1, T2>(t2); + return; + } + } + + // 16. If types includes a string type, then return the result of converting V + // to that type. + if (value.isString()) { + if (UnionTypeTraitsT1::is_string_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t1); + *out_union = script::UnionType2<T1, T2>(t1); + return; + } + + if (UnionTypeTraitsT2::is_string_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t2); + *out_union = script::UnionType2<T1, T2>(t2); + return; + } + } + + // 17. If types includes a numeric type, then return the result of converting + // V to that numeric type. + if (UnionTypeTraitsT1::is_numeric_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t1); + *out_union = script::UnionType2<T1, T2>(t1); + return; + } + if (UnionTypeTraitsT2::is_numeric_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t2); + *out_union = script::UnionType2<T1, T2>(t2); + return; + } + // 18. If types includes a boolean, then return the result of converting V to + // boolean. + if (UnionTypeTraitsT1::is_boolean_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t1); + *out_union = script::UnionType2<T1, T2>(t1); + return; + } + if (UnionTypeTraitsT2::is_boolean_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t2); + *out_union = script::UnionType2<T1, T2>(t2); + return; + } + // 19. Throw a TypeError. + exception_state->SetSimpleException( + ExceptionState::kTypeError, "Value is not a member of the union type."); +} + +template <typename T1, typename T2, typename T3> +void ToJSValue(JSContext* context, + const script::UnionType3<T1, T2, T3>& in_union, + JS::MutableHandleValue out_value) { + if (in_union.template IsType<T1>()) { + ToJSValue(context, in_union.template AsType<T1>(), out_value); + return; + } + if (in_union.template IsType<T2>()) { + ToJSValue(context, in_union.template AsType<T2>(), out_value); + return; + } + if (in_union.template IsType<T3>()) { + ToJSValue(context, in_union.template AsType<T3>(), out_value); + return; + } + NOTREACHED(); + out_value.setUndefined(); +} + +template <typename T1, typename T2, typename T3> +void FromJSValue(JSContext* context, JS::HandleValue value, + int conversion_flags, ExceptionState* exception_state, + script::UnionType3<T1, T2, T3>* out_union) { + DCHECK_EQ(0, conversion_flags); + // JS -> IDL type conversion procedure described here: + // http://heycam.github.io/webidl/#es-union + + // 1. If the union type includes a nullable type and V is null or undefined, + // then return the IDL value null. + if (value.isNull() || value.isUndefined()) { + // If the type was nullable or undefined, we should have caught that as a + // part of the base::optional<T> conversion. + NOTREACHED(); + return; + } + // Typedef for readability. + typedef ::cobalt::script::internal::UnionTypeTraits<T1> UnionTypeTraitsT1; + typedef ::cobalt::script::internal::UnionTypeTraits<T2> UnionTypeTraitsT2; + typedef ::cobalt::script::internal::UnionTypeTraits<T3> UnionTypeTraitsT3; + + // Forward declare all potential types + T1 t1; + T2 t2; + T3 t3; + + // 3.1 If types includes an interface type that V implements, then return the + // IDL value that is a reference to the object V. + // 3.2 If types includes object, then return the IDL value that is a reference + // to the object V. + // + // The specification doesn't dictate what should happen if V implements more + // than one of the interfaces. For example, if V implements interface B and + // interface B inherits from interface A, what happens if both A and B are + // union members? Blink doesn't seem to do anything special for this case. + // Just choose the first interface in the flattened members that matches. + if (value.isObject()) { + JS::RootedObject rooted_object(context); + bool success = JS_ValueToObject(context, value, rooted_object.address()); + DCHECK(success); + MozjsGlobalObjectProxy* global_object_proxy = + static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context)); + const WrapperFactory* wrapper_factory = + global_object_proxy->wrapper_factory(); + if (UnionTypeTraitsT1::is_interface_type && + wrapper_factory->DoesObjectImplementInterface( + rooted_object, UnionTypeTraitsT1::GetTypeID())) { + FromJSValue(context, value, conversion_flags, exception_state, &t1); + *out_union = script::UnionType3<T1, T2, T3>(t1); + return; + } + if (UnionTypeTraitsT2::is_interface_type && + wrapper_factory->DoesObjectImplementInterface( + rooted_object, UnionTypeTraitsT2::GetTypeID())) { + FromJSValue(context, value, conversion_flags, exception_state, &t2); + *out_union = script::UnionType3<T1, T2, T3>(t2); + return; + } + if (UnionTypeTraitsT3::is_interface_type && + wrapper_factory->DoesObjectImplementInterface( + rooted_object, UnionTypeTraitsT3::GetTypeID())) { + FromJSValue(context, value, conversion_flags, exception_state, &t3); + *out_union = script::UnionType3<T1, T2, T3>(t3); + return; + } + } + + // TODO: Support Date, RegExp, DOMException, Error, ArrayBuffer, DataView, + // TypedArrayName, callback functions, dictionary, array type. + // And sequences if necessary. + + // 14. If V is a Boolean value, then: + // 1. If types includes a boolean, then return the result of converting V + // to boolean. + if (value.isBoolean()) { + if (UnionTypeTraitsT1::is_boolean_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t1); + *out_union = script::UnionType3<T1, T2, T3>(t1); + return; + } + + if (UnionTypeTraitsT2::is_boolean_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t2); + *out_union = script::UnionType3<T1, T2, T3>(t2); + return; + } + + if (UnionTypeTraitsT3::is_boolean_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t3); + *out_union = script::UnionType3<T1, T2, T3>(t3); + return; + } + } + + // 15. If V is a Number value, then: + // 1. If types includes a numeric type, then return the result of converting + // V to that numeric type. + if (value.isNumber()) { + if (UnionTypeTraitsT1::is_numeric_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t1); + *out_union = script::UnionType3<T1, T2, T3>(t1); + return; + } + + if (UnionTypeTraitsT2::is_numeric_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t2); + *out_union = script::UnionType3<T1, T2, T3>(t2); + return; + } + + if (UnionTypeTraitsT3::is_numeric_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t3); + *out_union = script::UnionType3<T1, T2, T3>(t3); + return; + } + } + + // 16. If types includes a string type, then return the result of converting V + // to that type. + if (value.isString()) { + if (UnionTypeTraitsT1::is_string_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t1); + *out_union = script::UnionType3<T1, T2, T3>(t1); + return; + } + + if (UnionTypeTraitsT2::is_string_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t2); + *out_union = script::UnionType3<T1, T2, T3>(t2); + return; + } + + if (UnionTypeTraitsT3::is_string_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t3); + *out_union = script::UnionType3<T1, T2, T3>(t3); + return; + } + } + + // 17. If types includes a numeric type, then return the result of converting + // V to that numeric type. + if (UnionTypeTraitsT1::is_numeric_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t1); + *out_union = script::UnionType3<T1, T2, T3>(t1); + return; + } + if (UnionTypeTraitsT2::is_numeric_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t2); + *out_union = script::UnionType3<T1, T2, T3>(t2); + return; + } + if (UnionTypeTraitsT3::is_numeric_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t3); + *out_union = script::UnionType3<T1, T2, T3>(t3); + return; + } + // 18. If types includes a boolean, then return the result of converting V to + // boolean. + if (UnionTypeTraitsT1::is_boolean_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t1); + *out_union = script::UnionType3<T1, T2, T3>(t1); + return; + } + if (UnionTypeTraitsT2::is_boolean_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t2); + *out_union = script::UnionType3<T1, T2, T3>(t2); + return; + } + if (UnionTypeTraitsT3::is_boolean_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t3); + *out_union = script::UnionType3<T1, T2, T3>(t3); + return; + } + // 19. Throw a TypeError. + exception_state->SetSimpleException( + ExceptionState::kTypeError, "Value is not a member of the union type."); +} + +template <typename T1, typename T2, typename T3, typename T4> +void ToJSValue(JSContext* context, + const script::UnionType4<T1, T2, T3, T4>& in_union, + JS::MutableHandleValue out_value) { + if (in_union.template IsType<T1>()) { + ToJSValue(context, in_union.template AsType<T1>(), out_value); + return; + } + if (in_union.template IsType<T2>()) { + ToJSValue(context, in_union.template AsType<T2>(), out_value); + return; + } + if (in_union.template IsType<T3>()) { + ToJSValue(context, in_union.template AsType<T3>(), out_value); + return; + } + if (in_union.template IsType<T4>()) { + ToJSValue(context, in_union.template AsType<T4>(), out_value); + return; + } + NOTREACHED(); + out_value.setUndefined(); +} + +template <typename T1, typename T2, typename T3, typename T4> +void FromJSValue(JSContext* context, JS::HandleValue value, + int conversion_flags, ExceptionState* exception_state, + script::UnionType4<T1, T2, T3, T4>* out_union) { + DCHECK_EQ(0, conversion_flags); + // JS -> IDL type conversion procedure described here: + // http://heycam.github.io/webidl/#es-union + + // 1. If the union type includes a nullable type and V is null or undefined, + // then return the IDL value null. + if (value.isNull() || value.isUndefined()) { + // If the type was nullable or undefined, we should have caught that as a + // part of the base::optional<T> conversion. + NOTREACHED(); + return; + } + // Typedef for readability. + typedef ::cobalt::script::internal::UnionTypeTraits<T1> UnionTypeTraitsT1; + typedef ::cobalt::script::internal::UnionTypeTraits<T2> UnionTypeTraitsT2; + typedef ::cobalt::script::internal::UnionTypeTraits<T3> UnionTypeTraitsT3; + typedef ::cobalt::script::internal::UnionTypeTraits<T4> UnionTypeTraitsT4; + + // Forward declare all potential types + T1 t1; + T2 t2; + T3 t3; + T4 t4; + + // 3.1 If types includes an interface type that V implements, then return the + // IDL value that is a reference to the object V. + // 3.2 If types includes object, then return the IDL value that is a reference + // to the object V. + // + // The specification doesn't dictate what should happen if V implements more + // than one of the interfaces. For example, if V implements interface B and + // interface B inherits from interface A, what happens if both A and B are + // union members? Blink doesn't seem to do anything special for this case. + // Just choose the first interface in the flattened members that matches. + if (value.isObject()) { + JS::RootedObject rooted_object(context); + bool success = JS_ValueToObject(context, value, rooted_object.address()); + DCHECK(success); + MozjsGlobalObjectProxy* global_object_proxy = + static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context)); + const WrapperFactory* wrapper_factory = + global_object_proxy->wrapper_factory(); + if (UnionTypeTraitsT1::is_interface_type && + wrapper_factory->DoesObjectImplementInterface( + rooted_object, UnionTypeTraitsT1::GetTypeID())) { + FromJSValue(context, value, conversion_flags, exception_state, &t1); + *out_union = script::UnionType4<T1, T2, T3, T4>(t1); + return; + } + if (UnionTypeTraitsT2::is_interface_type && + wrapper_factory->DoesObjectImplementInterface( + rooted_object, UnionTypeTraitsT2::GetTypeID())) { + FromJSValue(context, value, conversion_flags, exception_state, &t2); + *out_union = script::UnionType4<T1, T2, T3, T4>(t2); + return; + } + if (UnionTypeTraitsT3::is_interface_type && + wrapper_factory->DoesObjectImplementInterface( + rooted_object, UnionTypeTraitsT3::GetTypeID())) { + FromJSValue(context, value, conversion_flags, exception_state, &t3); + *out_union = script::UnionType4<T1, T2, T3, T4>(t3); + return; + } + if (UnionTypeTraitsT4::is_interface_type && + wrapper_factory->DoesObjectImplementInterface( + rooted_object, UnionTypeTraitsT4::GetTypeID())) { + FromJSValue(context, value, conversion_flags, exception_state, &t4); + *out_union = script::UnionType4<T1, T2, T3, T4>(t4); + return; + } + } + + // TODO: Support Date, RegExp, DOMException, Error, ArrayBuffer, DataView, + // TypedArrayName, callback functions, dictionary, array type. + // And sequences if necessary. + + // 14. If V is a Boolean value, then: + // 1. If types includes a boolean, then return the result of converting V + // to boolean. + if (value.isBoolean()) { + if (UnionTypeTraitsT1::is_boolean_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t1); + *out_union = script::UnionType4<T1, T2, T3, T4>(t1); + return; + } + + if (UnionTypeTraitsT2::is_boolean_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t2); + *out_union = script::UnionType4<T1, T2, T3, T4>(t2); + return; + } + + if (UnionTypeTraitsT3::is_boolean_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t3); + *out_union = script::UnionType4<T1, T2, T3, T4>(t3); + return; + } + + if (UnionTypeTraitsT4::is_boolean_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t4); + *out_union = script::UnionType4<T1, T2, T3, T4>(t4); + return; + } + } + + // 15. If V is a Number value, then: + // 1. If types includes a numeric type, then return the result of converting + // V to that numeric type. + if (value.isNumber()) { + if (UnionTypeTraitsT1::is_numeric_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t1); + *out_union = script::UnionType4<T1, T2, T3, T4>(t1); + return; + } + + if (UnionTypeTraitsT2::is_numeric_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t2); + *out_union = script::UnionType4<T1, T2, T3, T4>(t2); + return; + } + + if (UnionTypeTraitsT3::is_numeric_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t3); + *out_union = script::UnionType4<T1, T2, T3, T4>(t3); + return; + } + + if (UnionTypeTraitsT4::is_numeric_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t4); + *out_union = script::UnionType4<T1, T2, T3, T4>(t4); + return; + } + } + + // 16. If types includes a string type, then return the result of converting V + // to that type. + if (value.isString()) { + if (UnionTypeTraitsT1::is_string_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t1); + *out_union = script::UnionType4<T1, T2, T3, T4>(t1); + return; + } + + if (UnionTypeTraitsT2::is_string_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t2); + *out_union = script::UnionType4<T1, T2, T3, T4>(t2); + return; + } + + if (UnionTypeTraitsT3::is_string_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t3); + *out_union = script::UnionType4<T1, T2, T3, T4>(t3); + return; + } + + if (UnionTypeTraitsT4::is_string_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t4); + *out_union = script::UnionType4<T1, T2, T3, T4>(t4); + return; + } + } + + // 17. If types includes a numeric type, then return the result of converting + // V to that numeric type. + if (UnionTypeTraitsT1::is_numeric_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t1); + *out_union = script::UnionType4<T1, T2, T3, T4>(t1); + return; + } + if (UnionTypeTraitsT2::is_numeric_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t2); + *out_union = script::UnionType4<T1, T2, T3, T4>(t2); + return; + } + if (UnionTypeTraitsT3::is_numeric_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t3); + *out_union = script::UnionType4<T1, T2, T3, T4>(t3); + return; + } + if (UnionTypeTraitsT4::is_numeric_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t4); + *out_union = script::UnionType4<T1, T2, T3, T4>(t4); + return; + } + // 18. If types includes a boolean, then return the result of converting V to + // boolean. + if (UnionTypeTraitsT1::is_boolean_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t1); + *out_union = script::UnionType4<T1, T2, T3, T4>(t1); + return; + } + if (UnionTypeTraitsT2::is_boolean_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t2); + *out_union = script::UnionType4<T1, T2, T3, T4>(t2); + return; + } + if (UnionTypeTraitsT3::is_boolean_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t3); + *out_union = script::UnionType4<T1, T2, T3, T4>(t3); + return; + } + if (UnionTypeTraitsT4::is_boolean_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t4); + *out_union = script::UnionType4<T1, T2, T3, T4>(t4); + return; + } + // 19. Throw a TypeError. + exception_state->SetSimpleException( + ExceptionState::kTypeError, "Value is not a member of the union type."); +} + +} // namespace mozjs +} // namespace script +} // namespace cobalt + +#endif // COBALT_SCRIPT_MOZJS_UNION_TYPE_CONVERSION_IMPL_H_
diff --git a/src/cobalt/script/mozjs/union_type_conversion_impl.h.pump b/src/cobalt/script/mozjs/union_type_conversion_impl.h.pump new file mode 100644 index 0000000..046f822 --- /dev/null +++ b/src/cobalt/script/mozjs/union_type_conversion_impl.h.pump
@@ -0,0 +1,205 @@ +$$ This is a pump file for generating file templates. Pump is a python +$$ script that is part of the Google Test suite of utilities. Description +$$ can be found here: +$$ +$$ http://code.google.com/p/googletest/wiki/PumpManual +$$ + +$$ Maximum number of different member types in a union. +$var MAX_MEMBERS = 4 +/* + * 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_SCRIPT_MOZJS_UNION_TYPE_CONVERSION_IMPL_H_ +#define COBALT_SCRIPT_MOZJS_UNION_TYPE_CONVERSION_IMPL_H_ + +#include "cobalt/base/type_id.h" +#include "cobalt/script/mozjs/mozjs_exception_state.h" +#include "cobalt/script/mozjs/mozjs_global_object_proxy.h" +#include "cobalt/script/mozjs/mozjs_object_handle.h" +#include "cobalt/script/mozjs/mozjs_user_object_holder.h" +#include "cobalt/script/mozjs/type_traits.h" +#include "cobalt/script/union_type.h" + +// Conversion to/from JS::Value for IDL union types. + +namespace cobalt { +namespace script { +namespace mozjs { + +$range NUM_MEMBERS 2..MAX_MEMBERS +$for NUM_MEMBERS [[ + +$range TYPE 1..NUM_MEMBERS + +template <$for TYPE , [[typename T$(TYPE)]]> +void ToJSValue(JSContext* context, const script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>& in_union, JS::MutableHandleValue out_value) { +$for TYPE [[ + + if (in_union.template IsType<T$(TYPE)>()) { + ToJSValue(context, in_union.template AsType<T$(TYPE)>(), out_value); + return; + } +]] + + NOTREACHED(); + out_value.setUndefined(); +} + +template <$for TYPE , [[typename T$(TYPE)]]> +void FromJSValue(JSContext* context, JS::HandleValue value, + int conversion_flags, ExceptionState* exception_state, + script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>* out_union) { + DCHECK_EQ(0, conversion_flags); + // JS -> IDL type conversion procedure described here: + // http://heycam.github.io/webidl/#es-union + + // 1. If the union type includes a nullable type and V is null or undefined, + // then return the IDL value null. + if (value.isNull() || value.isUndefined()) { + // If the type was nullable or undefined, we should have caught that as a + // part of the base::optional<T> conversion. + NOTREACHED(); + return; + } + // Typedef for readability. + +$for TYPE [[ + typedef ::cobalt::script::internal::UnionTypeTraits<T$(TYPE)> UnionTypeTraitsT$(TYPE); + +]] + + // Forward declare all potential types + +$for TYPE [[ + T$(TYPE) t$(TYPE); + +]] + + // 3.1 If types includes an interface type that V implements, then return the + // IDL value that is a reference to the object V. + // 3.2 If types includes object, then return the IDL value that is a reference + // to the object V. + // + // The specification doesn't dictate what should happen if V implements more + // than one of the interfaces. For example, if V implements interface B and + // interface B inherits from interface A, what happens if both A and B are + // union members? Blink doesn't seem to do anything special for this case. + // Just choose the first interface in the flattened members that matches. + if (value.isObject()) { + + JS::RootedObject rooted_object(context); + bool success = JS_ValueToObject(context, value, rooted_object.address()); + DCHECK(success); + MozjsGlobalObjectProxy* global_object_proxy = + static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context)); + const WrapperFactory* wrapper_factory = + global_object_proxy->wrapper_factory(); + +$for TYPE [[ + if (UnionTypeTraitsT$(TYPE)::is_interface_type + && wrapper_factory->DoesObjectImplementInterface( + rooted_object, UnionTypeTraitsT$(TYPE)::GetTypeID())) { + FromJSValue(context, value, conversion_flags, exception_state, &t$(TYPE)); + *out_union = script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>(t$(TYPE)); + return; + } + +]] + } + + // TODO: Support Date, RegExp, DOMException, Error, ArrayBuffer, DataView, + // TypedArrayName, callback functions, dictionary, array type. + // And sequences if necessary. + + // 14. If V is a Boolean value, then: + // 1. If types includes a boolean, then return the result of converting V + // to boolean. + if (value.isBoolean()) { +$for TYPE [[ + + if (UnionTypeTraitsT$(TYPE)::is_boolean_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t$(TYPE)); + *out_union = script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>(t$(TYPE)); + return; + } + +]] + } + + // 15. If V is a Number value, then: + // 1. If types includes a numeric type, then return the result of converting + // V to that numeric type. + if (value.isNumber()) { +$for TYPE [[ + + if (UnionTypeTraitsT$(TYPE)::is_numeric_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t$(TYPE)); + *out_union = script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>(t$(TYPE)); + return; + } + +]] + } + + // 16. If types includes a string type, then return the result of converting V + // to that type. + if (value.isString()) { +$for TYPE [[ + + if (UnionTypeTraitsT$(TYPE)::is_string_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t$(TYPE)); + *out_union = script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>(t$(TYPE)); + return; + } + +]] + } + + // 17. If types includes a numeric type, then return the result of converting + // V to that numeric type. +$for TYPE [[ + + if (UnionTypeTraitsT$(TYPE)::is_numeric_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t$(TYPE)); + *out_union = script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>(t$(TYPE)); + return; + } +]] + + // 18. If types includes a boolean, then return the result of converting V to + // boolean. +$for TYPE [[ + + if (UnionTypeTraitsT$(TYPE)::is_boolean_type) { + FromJSValue(context, value, conversion_flags, exception_state, &t$(TYPE)); + *out_union = script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>(t$(TYPE)); + return; + } +]] + + // 19. Throw a TypeError. + exception_state->SetSimpleException( + ExceptionState::kTypeError, "Value is not a member of the union type."); +} + +]] $$ for NUM_MEMBERS + +} // namespace mozjs +} // namespace script +} // namespace cobalt + +#endif // COBALT_SCRIPT_MOZJS_UNION_TYPE_CONVERSION_IMPL_H_
diff --git a/src/cobalt/script/mozjs/wrapper_factory.cc b/src/cobalt/script/mozjs/wrapper_factory.cc index b5c4bad..72b2edb 100644 --- a/src/cobalt/script/mozjs/wrapper_factory.cc +++ b/src/cobalt/script/mozjs/wrapper_factory.cc
@@ -20,37 +20,42 @@ #include "base/lazy_instance.h" #include "cobalt/script/mozjs/mozjs_wrapper_handle.h" #include "cobalt/script/mozjs/wrapper_private.h" +#include "third_party/mozjs/js/src/jsproxy.h" namespace cobalt { namespace script { namespace mozjs { void WrapperFactory::RegisterWrappableType( - base::TypeId wrappable_type, const CreateWrapperFunction& create_function) { - std::pair<CreateWrapperHashMap::iterator, bool> pib = - create_wrapper_functions_.insert( - std::make_pair(wrappable_type, create_function)); + base::TypeId wrappable_type, const CreateWrapperFunction& create_function, + const PrototypeClassFunction& class_function) { + std::pair<WrappableTypeFunctionsHashMap::iterator, bool> pib = + wrappable_type_functions_.insert(std::make_pair( + wrappable_type, + WrappableTypeFunctions(create_function, class_function))); DCHECK(pib.second) << "RegisterWrappableType registered for type more than once."; } -JSObject* WrapperFactory::GetWrapper( +JSObject* WrapperFactory::GetWrapperProxy( const scoped_refptr<Wrappable>& wrappable) const { if (!wrappable) { return NULL; } - JS::RootedObject wrapper(context_, MozjsWrapperHandle::GetJSObject( - GetCachedWrapper(wrappable.get()))); - if (!wrapper) { + JS::RootedObject wrapper_proxy( + context_, + MozjsWrapperHandle::GetObjectProxy(GetCachedWrapper(wrappable.get()))); + if (!wrapper_proxy) { scoped_ptr<Wrappable::WeakWrapperHandle> object_handle = CreateWrapper(wrappable); SetCachedWrapper(wrappable.get(), object_handle.Pass()); - wrapper = - MozjsWrapperHandle::GetJSObject(GetCachedWrapper(wrappable.get())); + wrapper_proxy = + MozjsWrapperHandle::GetObjectProxy(GetCachedWrapper(wrappable.get())); } - DCHECK(wrapper); - return wrapper; + DCHECK(wrapper_proxy); + DCHECK(js::IsProxy(wrapper_proxy)); + return wrapper_proxy; } bool WrapperFactory::IsWrapper(JS::HandleObject wrapper) const { @@ -59,20 +64,44 @@ scoped_ptr<Wrappable::WeakWrapperHandle> WrapperFactory::CreateWrapper( const scoped_refptr<Wrappable>& wrappable) const { - CreateWrapperHashMap::const_iterator it = - create_wrapper_functions_.find(wrappable->GetWrappableType()); - if (it == create_wrapper_functions_.end()) { + WrappableTypeFunctionsHashMap::const_iterator it = + wrappable_type_functions_.find(wrappable->GetWrappableType()); + if (it == wrappable_type_functions_.end()) { NOTREACHED(); return scoped_ptr<Wrappable::WeakWrapperHandle>(); } - JS::RootedObject new_object(context_, it->second.Run(context_, wrappable)); + JS::RootedObject new_proxy( + context_, it->second.create_wrapper.Run(context_, wrappable)); WrapperPrivate* wrapper_private = - reinterpret_cast<WrapperPrivate*>(JS_GetPrivate(new_object)); + WrapperPrivate::GetFromProxyObject(context_, new_proxy); DCHECK(wrapper_private); return make_scoped_ptr<Wrappable::WeakWrapperHandle>( new MozjsWrapperHandle(wrapper_private)); } +bool WrapperFactory::DoesObjectImplementInterface(JSObject* object, + base::TypeId type_id) const { + WrappableTypeFunctionsHashMap::const_iterator it = + wrappable_type_functions_.find(type_id); + if (it == wrappable_type_functions_.end()) { + NOTREACHED(); + return false; + } + const JSClass* proto_class = it->second.prototype_class.Run(context_); + JS::RootedObject object_proto_object(context_); + bool success = + JS_GetPrototype(context_, object, object_proto_object.address()); + bool equality = false; + while (!equality && success && object_proto_object) { + // Get the class of the prototype. + JSClass* object_proto_class = JS_GetClass(object_proto_object); + equality = (object_proto_class == proto_class); + // Get the prototype of the previous prototype. + success = JS_GetPrototype(context_, object_proto_object, + object_proto_object.address()); + } + return equality; +} } // namespace mozjs } // namespace script } // namespace cobalt
diff --git a/src/cobalt/script/mozjs/wrapper_factory.h b/src/cobalt/script/mozjs/wrapper_factory.h index cf54027..828bdac 100644 --- a/src/cobalt/script/mozjs/wrapper_factory.h +++ b/src/cobalt/script/mozjs/wrapper_factory.h
@@ -37,25 +37,39 @@ typedef base::Callback<JSObject*(JSContext*, const scoped_refptr<Wrappable>&)> CreateWrapperFunction; + // Callback to get JSClass* of prototype. + typedef base::Callback<const JSClass*(JSContext*)> PrototypeClassFunction; + explicit WrapperFactory(JSContext* context) : context_(context) {} void RegisterWrappableType(base::TypeId wrappable_type, - const CreateWrapperFunction& create_function); + const CreateWrapperFunction& create_function, + const PrototypeClassFunction& class_function); - // Gets the Wrapper object for this Wrappable. It may create a new Wrapper. - JSObject* GetWrapper(const scoped_refptr<Wrappable>& wrappable) const; - + // Gets the Proxy for the Wrapper object for this Wrappable. It may create a + // new Wrapper and Proxy. + JSObject* GetWrapperProxy(const scoped_refptr<Wrappable>& wrappable) const; // Returns true if this JSObject is a Wrapper object. bool IsWrapper(JS::HandleObject wrapper) const; + bool DoesObjectImplementInterface(JSObject*, base::TypeId) const; + private: + struct WrappableTypeFunctions { + CreateWrapperFunction create_wrapper; + PrototypeClassFunction prototype_class; + WrappableTypeFunctions(const CreateWrapperFunction& create_wrapper, + const PrototypeClassFunction& prototype_class) + : create_wrapper(create_wrapper), prototype_class(prototype_class) {} + }; + scoped_ptr<Wrappable::WeakWrapperHandle> CreateWrapper( const scoped_refptr<Wrappable>& wrappable) const; - typedef base::hash_map<base::TypeId, CreateWrapperFunction> - CreateWrapperHashMap; + typedef base::hash_map<base::TypeId, WrappableTypeFunctions> + WrappableTypeFunctionsHashMap; JSContext* context_; - CreateWrapperHashMap create_wrapper_functions_; + WrappableTypeFunctionsHashMap wrappable_type_functions_; }; } // namespace mozjs
diff --git a/src/cobalt/script/mozjs/wrapper_private.cc b/src/cobalt/script/mozjs/wrapper_private.cc index dad78c9..b7b3443 100644 --- a/src/cobalt/script/mozjs/wrapper_private.cc +++ b/src/cobalt/script/mozjs/wrapper_private.cc
@@ -17,6 +17,7 @@ #include "cobalt/script/mozjs/wrapper_private.h" #include "third_party/mozjs/js/src/jsapi.h" +#include "third_party/mozjs/js/src/jsproxy.h" namespace cobalt { namespace script { @@ -38,26 +39,55 @@ } // static -void WrapperPrivate::AddPrivateData(JS::HandleObject wrapper, +void WrapperPrivate::AddPrivateData(JS::HandleObject wrapper_proxy, const scoped_refptr<Wrappable>& wrappable) { - WrapperPrivate* private_data = new WrapperPrivate(wrappable, wrapper); - JS_SetPrivate(wrapper, private_data); - DCHECK_EQ(JS_GetPrivate(wrapper), private_data); + DCHECK(js::IsProxy(wrapper_proxy)); + WrapperPrivate* private_data = new WrapperPrivate(wrappable, wrapper_proxy); + JSObject* target_object = js::GetProxyTargetObject(wrapper_proxy); + JS_SetPrivate(target_object, private_data); + DCHECK_EQ(JS_GetPrivate(target_object), private_data); } // static WrapperPrivate* WrapperPrivate::GetFromWrappable( const scoped_refptr<Wrappable>& wrappable, JSContext* context, WrapperFactory* wrapper_factory) { - JS::RootedObject wrapper(context, wrapper_factory->GetWrapper(wrappable)); - WrapperPrivate* private_data = - static_cast<WrapperPrivate*>(JS_GetPrivate(wrapper)); + JS::RootedObject wrapper_proxy(context, + wrapper_factory->GetWrapperProxy(wrappable)); + WrapperPrivate* private_data = GetFromProxyObject(context, wrapper_proxy); DCHECK(private_data); DCHECK_EQ(private_data->wrappable_, wrappable); return private_data; } // static +WrapperPrivate* WrapperPrivate::GetFromWrapperObject(JS::HandleObject wrapper) { + DCHECK(!js::IsProxy(wrapper)); + WrapperPrivate* private_data = + static_cast<WrapperPrivate*>(JS_GetPrivate(wrapper)); + DCHECK(private_data); + return private_data; +} + +// static +WrapperPrivate* WrapperPrivate::GetFromProxyObject( + JSContext* context, JS::HandleObject proxy_object) { + DCHECK(js::IsProxy(proxy_object)); + JS::RootedObject target(context, js::GetProxyTargetObject(proxy_object)); + return GetFromWrapperObject(target); +} + +// static +WrapperPrivate* WrapperPrivate::GetFromObject(JSContext* context, + JS::HandleObject object) { + if (js::IsProxy(object)) { + return GetFromProxyObject(context, object); + } else { + return GetFromWrapperObject(object); + } +} + +// static void WrapperPrivate::Finalizer(JSFreeOp* /* free_op */, JSObject* object) { WrapperPrivate* wrapper_private = reinterpret_cast<WrapperPrivate*>(JS_GetPrivate(object)); @@ -78,6 +108,12 @@ } } +WrapperPrivate::WrapperPrivate(const scoped_refptr<Wrappable>& wrappable, + JS::HandleObject wrapper_proxy) + : wrappable_(wrappable), wrapper_proxy_(wrapper_proxy) { + DCHECK(js::IsProxy(wrapper_proxy)); +} + } // namespace mozjs } // namespace script } // namespace cobalt
diff --git a/src/cobalt/script/mozjs/wrapper_private.h b/src/cobalt/script/mozjs/wrapper_private.h index 6352c3a..9bb4219 100644 --- a/src/cobalt/script/mozjs/wrapper_private.h +++ b/src/cobalt/script/mozjs/wrapper_private.h
@@ -34,8 +34,12 @@ // must be destroyed when its JSObject is garbage collected. class WrapperPrivate : public base::SupportsWeakPtr<WrapperPrivate> { public: - const scoped_refptr<Wrappable>& wrappable() const { return wrappable_; } - JSObject* js_object() const { return wrapper_; } + template <typename T> + scoped_refptr<T> wrappable() const { + return base::polymorphic_downcast<T*>(wrappable_.get()); + } + + JSObject* js_object_proxy() const { return wrapper_proxy_; } // Add/Remove a reference to the object. The object will be visited during // garbage collection. @@ -43,7 +47,7 @@ void RemoveReferencedObject(JS::HandleObject referee); // Create a new WrapperPrivate instance and associate it with the wrapper. - static void AddPrivateData(JS::HandleObject wrapper, + static void AddPrivateData(JS::HandleObject wrapper_proxy, const scoped_refptr<Wrappable>& wrappable); // Get the WrapperPrivate associated with the given Wrappable. A new JSObject @@ -52,13 +56,17 @@ const scoped_refptr<Wrappable>& wrappable, JSContext* context, WrapperFactory* wrapper_factory); - template <typename T> - static T* GetWrappable(JS::HandleObject wrapper) { - WrapperPrivate* private_data = - static_cast<WrapperPrivate*>(JS_GetPrivate(wrapper)); - DCHECK(private_data); - return base::polymorphic_downcast<T*>(private_data->wrappable_.get()); - } + // Get the WrapperPrivate instance associated with this Wrapper object. + static WrapperPrivate* GetFromWrapperObject(JS::HandleObject object); + + // Get the WrapperPrivate instance associated with the target of this proxy. + static WrapperPrivate* GetFromProxyObject(JSContext* context, + JS::HandleObject proxy_object); + + // Get the WrapperPrivate instance associated with the object, which may + // be a proxy or a proxy target. + static WrapperPrivate* GetFromObject(JSContext* context, + JS::HandleObject object); // Called when the wrapper object is about to be deleted by the GC. static void Finalizer(JSFreeOp* /* free_op */, JSObject* object); @@ -69,11 +77,10 @@ private: typedef ScopedVector<JS::Heap<JSObject*> > ReferencedObjectVector; WrapperPrivate(const scoped_refptr<Wrappable>& wrappable, - JS::HandleObject wrapper) - : wrappable_(wrappable), wrapper_(wrapper) {} + JS::HandleObject wrapper_proxy); scoped_refptr<Wrappable> wrappable_; - JS::Heap<JSObject*> wrapper_; + JS::Heap<JSObject*> wrapper_proxy_; ReferencedObjectVector referenced_objects_; };
diff --git a/src/cobalt/storage/storage.gyp b/src/cobalt/storage/storage.gyp index 25820d7..599f95a 100644 --- a/src/cobalt/storage/storage.gyp +++ b/src/cobalt/storage/storage.gyp
@@ -89,7 +89,7 @@ 'variables': { 'executable_name': 'storage_test', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, ], }
diff --git a/src/cobalt/storage/storage_manager_test.cc b/src/cobalt/storage/storage_manager_test.cc index 623aa7f..fbd0c9c 100644 --- a/src/cobalt/storage/storage_manager_test.cc +++ b/src/cobalt/storage/storage_manager_test.cc
@@ -50,7 +50,7 @@ CallbackWaiter() : was_called_event_(true, false) {} virtual ~CallbackWaiter() {} bool TimedWait() { - return was_called_event_.TimedWait(base::TimeDelta::FromMilliseconds(500)); + return was_called_event_.TimedWait(base::TimeDelta::FromSeconds(5)); } protected:
diff --git a/src/cobalt/system_window/starboard/system_window.cc b/src/cobalt/system_window/starboard/system_window.cc index 0494e53..111cf8b 100644 --- a/src/cobalt/system_window/starboard/system_window.cc +++ b/src/cobalt/system_window/starboard/system_window.cc
@@ -19,12 +19,19 @@ #include "cobalt/base/event_dispatcher.h" #include "cobalt/system_window/keyboard_event.h" #include "cobalt/system_window/starboard/system_window.h" +#include "starboard/system.h" namespace cobalt { namespace system_window { namespace { SystemWindowStarboard* g_the_window = NULL; + +// Unbound callback handler for SbWindowShowDialog. +void StarboardDialogCallback(SbSystemPlatformErrorResponse response) { + DCHECK(g_the_window); + g_the_window->HandleDialogClose(response); +} } // namespace SystemWindowStarboard::SystemWindowStarboard( @@ -78,6 +85,60 @@ } } +void OnDialogClose(SbSystemPlatformErrorResponse response, void* user_data) { + DCHECK(user_data); + SystemWindowStarboard* system_window = + static_cast<SystemWindowStarboard*>(user_data); + system_window->HandleDialogClose(response); +} + +void SystemWindowStarboard::ShowDialog( + const SystemWindow::DialogOptions& options) { + SbSystemPlatformErrorType error_type; + switch (options.message_code) { + case kDialogConnectionError: + error_type = kSbSystemPlatformErrorTypeConnectionError; + break; + case kDialogUserSignedOut: + error_type = kSbSystemPlatformErrorTypeUserSignedOut; + break; + case kDialogUserAgeRestricted: + error_type = kSbSystemPlatformErrorTypeUserAgeRestricted; + break; + default: + NOTREACHED(); + break; + } + + SbSystemPlatformError handle = + SbSystemRaisePlatformError(error_type, OnDialogClose, this); + if (SbSystemPlatformErrorIsValid(handle)) { + current_dialog_callback_ = options.callback; + } else { + DLOG(WARNING) << "Failed to notify user of error: " + << options.message_code; + } +} + +void SystemWindowStarboard::HandleDialogClose( + SbSystemPlatformErrorResponse response) { + DCHECK(!current_dialog_callback_.is_null()); + switch (response) { + case kSbSystemPlatformErrorResponsePositive: + current_dialog_callback_.Run(kDialogPositiveResponse); + break; + case kSbSystemPlatformErrorResponseNegative: + current_dialog_callback_.Run(kDialogNegativeResponse); + break; + case kSbSystemPlatformErrorResponseCancel: + current_dialog_callback_.Run(kDialogCancelResponse); + break; + default: + DLOG(WARNING) << "Unrecognized dialog response: " << response; + break; + } +} + scoped_ptr<SystemWindow> CreateSystemWindow( base::EventDispatcher* event_dispatcher, const math::Size& window_size) { return scoped_ptr<SystemWindow>(
diff --git a/src/cobalt/system_window/starboard/system_window.h b/src/cobalt/system_window/starboard/system_window.h index 072c481..efc6caa 100644 --- a/src/cobalt/system_window/starboard/system_window.h +++ b/src/cobalt/system_window/starboard/system_window.h
@@ -23,7 +23,7 @@ #include "starboard/event.h" #include "starboard/input.h" #include "starboard/key.h" -#include "starboard/window.h" +#include "starboard/system.h" namespace cobalt { namespace system_window { @@ -43,6 +43,12 @@ // Handles a single Starboard input event, dispatching any appropriate events. void HandleInputEvent(const SbInputData& data); + // Raises a system dialog. + void ShowDialog(const SystemWindow::DialogOptions& options) OVERRIDE; + + // Called when the user closes the dialog. + void HandleDialogClose(SbSystemPlatformErrorResponse response); + private: void UpdateModifiers(SbKey key, bool pressed); KeyboardEvent::Modifiers GetModifiers(); @@ -50,6 +56,9 @@ SbWindow window_; bool key_down_; + + // The current dialog callback. Only one dialog may be open at a time. + DialogCallback current_dialog_callback_; }; // The Starboard Event handler SbHandleEvent should call this function on
diff --git a/src/cobalt/system_window/system_window.h b/src/cobalt/system_window/system_window.h index 272c5c9..4054bc0 100644 --- a/src/cobalt/system_window/system_window.h +++ b/src/cobalt/system_window/system_window.h
@@ -46,21 +46,20 @@ // Type of callback to run when user closes a dialog. typedef base::Callback<void(DialogResponse response)> DialogCallback; - // Type to indicate dialog severity. May be used by the platform-specific - // implementation to control aspects of dialog presentation. - enum DialogSeverity { kDialogInfo, kDialogWarning, kDialogError }; + // Enumeration of possible message codes for a dialog. + enum DialogMessageCode { + kDialogConnectionError, + kDialogUserSignedOut, + kDialogUserAgeRestricted + }; // Options structure for dialog creation. It is expected that each platform // will implement a modal dialog with possible support for: - // A text message. - // An indication of severity: info, warning or error. - // 1-3 buttons, where usually 1 = OK, 2 = Yes/No, 3 = Yes/No/Cancel. + // A message code specifying the text to be displayed, which should be + // localized according to the platform. // A callback indicating the user's response: positive, negative or cancel. struct DialogOptions { - DialogOptions() : severity(kDialogInfo), num_buttons(1) {} - DialogSeverity severity; - int num_buttons; - std::string message; + DialogMessageCode message_code; DialogCallback callback; };
diff --git a/src/cobalt/system_window/system_window_common.cc b/src/cobalt/system_window/system_window_common.cc index 0a2ba8e..50ae183 100644 --- a/src/cobalt/system_window/system_window_common.cc +++ b/src/cobalt/system_window/system_window_common.cc
@@ -25,7 +25,7 @@ void SystemWindow::ShowDialog(const SystemWindow::DialogOptions& options) { NOTIMPLEMENTED() << "System dialog not implemented on this platform"; - DLOG(INFO) << "Message: " << options.message; + DLOG(INFO) << "Message code: " << options.message_code; } } // namespace system_window
diff --git a/src/cobalt/trace_event/trace_event.gyp b/src/cobalt/trace_event/trace_event.gyp index 1b756f6..75d5c82 100644 --- a/src/cobalt/trace_event/trace_event.gyp +++ b/src/cobalt/trace_event/trace_event.gyp
@@ -56,7 +56,7 @@ 'variables': { 'executable_name': 'trace_event_test', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, { @@ -108,7 +108,7 @@ 'variables': { 'executable_name': 'sample_benchmark', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, ], }
diff --git a/src/cobalt/web_animations/web_animations.gyp b/src/cobalt/web_animations/web_animations.gyp index 5be6176..e4544ac 100644 --- a/src/cobalt/web_animations/web_animations.gyp +++ b/src/cobalt/web_animations/web_animations.gyp
@@ -72,7 +72,7 @@ 'variables': { 'executable_name': 'web_animations_test', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, ], }
diff --git a/src/cobalt/webdriver/webdriver.gyp b/src/cobalt/webdriver/webdriver.gyp index 62e974f..558a0ee 100644 --- a/src/cobalt/webdriver/webdriver.gyp +++ b/src/cobalt/webdriver/webdriver.gyp
@@ -131,7 +131,7 @@ 'variables': { 'executable_name': 'webdriver_test', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, {
diff --git a/src/cobalt/xhr/xhr.gyp b/src/cobalt/xhr/xhr.gyp index 8621405..06c24c5 100644 --- a/src/cobalt/xhr/xhr.gyp +++ b/src/cobalt/xhr/xhr.gyp
@@ -58,7 +58,7 @@ 'variables': { 'executable_name': 'xhr_test', }, - 'includes': [ '../build/deploy.gypi' ], + 'includes': [ '../../starboard/build/deploy.gypi' ], }, {
diff --git a/src/crypto/crypto.gyp b/src/crypto/crypto.gyp index f83e290..2b37a30 100644 --- a/src/crypto/crypto.gyp +++ b/src/crypto/crypto.gyp
@@ -389,7 +389,7 @@ 'variables': { 'executable_name': 'crypto_unittests', }, - 'includes': [ '../cobalt/build/deploy.gypi' ], + 'includes': [ '../starboard/build/deploy.gypi' ], }, ], }],
diff --git a/src/glimp/gles/context.cc b/src/glimp/gles/context.cc index a6577ac..a104230 100644 --- a/src/glimp/gles/context.cc +++ b/src/glimp/gles/context.cc
@@ -1208,13 +1208,17 @@ // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glTexImage2D.xml // Note that glimp may not support all possible formats described above. PixelFormat PixelFormatFromGLTypeAndFormat(GLenum format, GLenum type) { - if (type == GL_UNSIGNED_BYTE && format == GL_RGBA) { - return kPixelFormatRGBA8; - } else if (type == GL_UNSIGNED_BYTE && format == GL_ALPHA) { - return kPixelFormatA8; - } else { - return kPixelFormatInvalid; + if (type == GL_UNSIGNED_BYTE) { + switch (format) { + case GL_RGBA: + return kPixelFormatRGBA8; + case GL_ALPHA: + return kPixelFormatA8; + case GL_LUMINANCE_ALPHA: + return kPixelFormatBA8; + } } + return kPixelFormatInvalid; } } // namespace
diff --git a/src/glimp/gles/convert_pixel_data.cc b/src/glimp/gles/convert_pixel_data.cc index 36249eb..7609baa 100644 --- a/src/glimp/gles/convert_pixel_data.cc +++ b/src/glimp/gles/convert_pixel_data.cc
@@ -59,10 +59,14 @@ const uint8_t* source, int num_pixels) { for (int i = 0; i < num_pixels; ++i) { - destination[0] = channel_0_source == -1 ? 0 : source[channel_0_source]; - destination[1] = channel_1_source == -1 ? 0 : source[channel_1_source]; - destination[2] = channel_2_source == -1 ? 0 : source[channel_2_source]; - destination[3] = channel_3_source == -1 ? 0 : source[channel_3_source]; + uint8_t channel_0 = channel_0_source == -1 ? 0 : source[channel_0_source]; + uint8_t channel_1 = channel_1_source == -1 ? 0 : source[channel_1_source]; + uint8_t channel_2 = channel_2_source == -1 ? 0 : source[channel_2_source]; + uint8_t channel_3 = channel_3_source == -1 ? 0 : source[channel_3_source]; + destination[0] = channel_0; + destination[1] = channel_1; + destination[2] = channel_2; + destination[3] = channel_3; destination += 4; source += source_bytes_per_pixel; @@ -81,6 +85,9 @@ } else if (destination_format == kPixelFormatRGBA8 && source_format == kPixelFormatARGB8) { return &RemapPixelChannels<1, 2, 3, 0>; + } else if (destination_format == kPixelFormatRGBA8 && + source_format == kPixelFormatBGRA8) { + return &RemapPixelChannels<2, 1, 0, 3>; } // Only what is currently needed by dependent libraries is supported, so @@ -91,6 +98,36 @@ } // namespace +void ConvertPixelDataInplace(uint8_t* pixels, + int pitch_in_bytes, + PixelFormat destination_format, + PixelFormat source_format, + int width, + int height) { + if (destination_format == source_format) { + return; + } + SB_DCHECK(BytesPerPixel(destination_format) == BytesPerPixel(source_format)); + // The destination format is different from the source format, so we must + // perform a conversion between pixels. + + // First select the function that will reformat the pixels, based on + // the destination and source pixel formats. + ConvertRowFunction convert_row_function = + SelectConvertRowFunction(destination_format, source_format); + SB_DCHECK(convert_row_function) + << "The requested pixel conversion is not yet implemented."; + + // Now, iterate through each row running the selected conversion function on + // each one. + uint8_t* pixel_row = pixels; + for (int row = 0; row < height; ++row) { + convert_row_function(BytesPerPixel(source_format), pixel_row, pixel_row, + width); + pixel_row += pitch_in_bytes; + } +} + void ConvertPixelData(uint8_t* destination, int destination_pitch_in_bytes, PixelFormat destination_format,
diff --git a/src/glimp/gles/convert_pixel_data.h b/src/glimp/gles/convert_pixel_data.h index 8c36212..c11721b 100644 --- a/src/glimp/gles/convert_pixel_data.h +++ b/src/glimp/gles/convert_pixel_data.h
@@ -27,6 +27,15 @@ kPixelDataBigEndian, }; +// Converts pixel data in pixel buffer from the source format into the +// destination format, swizzeling the pixel color components if necessary. +void ConvertPixelDataInplace(uint8_t* pixels, + int pitch_in_bytes, + PixelFormat destination_format, + PixelFormat source_format, + int width, + int height); + // Copies pixel data from the source buffer and format into the destination // buffer and format, swizzeling the pixel color components if necessary. void ConvertPixelData(uint8_t* destination,
diff --git a/src/glimp/gles/pixel_format.cc b/src/glimp/gles/pixel_format.cc index 57bfebe..5c0f76b 100644 --- a/src/glimp/gles/pixel_format.cc +++ b/src/glimp/gles/pixel_format.cc
@@ -27,12 +27,15 @@ 4, // kPixelFormatARGB8 4, // kPixelFormatBGRA8 2, // kPixelFormatRGB565 + 2, // kPixelFormatBA8 1, // kPixelFormatA8 }; } // namespace int BytesPerPixel(PixelFormat format) { + SB_COMPILE_ASSERT(SB_ARRAY_SIZE(kBytesPerPixel) == kPixelFormatNumFormats, + kBytesPerPixel_has_entries_for_each_enum_PixelFormat); return kBytesPerPixel[format]; }
diff --git a/src/glimp/gles/pixel_format.h b/src/glimp/gles/pixel_format.h index dcc597d..7268a75 100644 --- a/src/glimp/gles/pixel_format.h +++ b/src/glimp/gles/pixel_format.h
@@ -31,8 +31,10 @@ kPixelFormatARGB8, kPixelFormatBGRA8, kPixelFormatRGB565, + kPixelFormatBA8, kPixelFormatA8, kPixelFormatInvalid, + kPixelFormatNumFormats = kPixelFormatInvalid }; // Returns the number of bytes per pixel for a given PixelFormat.
diff --git a/src/glimp/shaders/generate_glsl_shader_map.py b/src/glimp/shaders/generate_glsl_shader_map.py index b024b5c..2ce1841 100644 --- a/src/glimp/shaders/generate_glsl_shader_map.py +++ b/src/glimp/shaders/generate_glsl_shader_map.py
@@ -107,13 +107,40 @@ for k, v in hash_to_shader_map.iteritems(): input_file_variable_name = GetBasename(v) generate_map_function_string += ( - ' (*out_map)[%d] = ShaderData(%s, sizeof(%s));\n' % + ' (*out_map)[%uU] = ShaderData(%s, sizeof(%s));\n' % (k, input_file_variable_name, input_file_variable_name)) - generate_map_function_string += '}\n\n' + generate_map_function_string += '}' return generate_map_function_string + +def GetShaderNameFunctionString(hash_to_shader_map): + """Generate C++ code to retrieve the shader name from a GLSL hash. + + Args: + hash_to_shader_map: + A dictionary where the keys are hashes and the values are + platform-specific shader filenames. + Returns: + A string of C++ code that defines a function that returns a string with the + corresponding shader name for the GLSL hash value passed as a parameter. + """ + + get_shader_name_function_string = ( + 'inline const char *GetShaderName(uint32_t hash_value) {\n' + ' switch(hash_value) {\n') + + for k, v in hash_to_shader_map.iteritems(): + input_file_variable_name = GetBasename(v) + get_shader_name_function_string += ( + ' case %uU: return \"%s\";\n' % + (k, input_file_variable_name)) + + get_shader_name_function_string += ' }\n return NULL;\n}' + return get_shader_name_function_string + + HEADER_FILE_TEMPLATE = """ // Copyright 2016 Google Inc. All Rights Reserved. // This file is generated (by glimp/shaders/generate_glsl_shader_map.py). @@ -129,6 +156,11 @@ {data_definitions} {generate_map_function} + +#if !defined(NDEBUG) +{shader_name_function} +#endif + }} // namespace shaders }} // namespace glimp @@ -153,7 +185,9 @@ data_definitions = GetHeaderDataDefinitionString( hash_to_shader_map.values()), generate_map_function = GetGenerateMapFunctionString( - hash_to_shader_map))) + hash_to_shader_map), + shader_name_function = GetShaderNameFunctionString( + hash_to_shader_map))) def AssociateGLSLFilesWithPlatformFiles(all_shaders):
diff --git a/src/media/audio/null_audio_streamer.cc b/src/media/audio/null_audio_streamer.cc index 2e3468a..0937b17 100644 --- a/src/media/audio/null_audio_streamer.cc +++ b/src/media/audio/null_audio_streamer.cc
@@ -41,7 +41,7 @@ ShellAudioStreamer::Config NullAudioStreamer::GetConfig() const { // Reasonable looking settings. const uint32 initial_rebuffering_frames_per_channel = - mp4::AAC::kSamplesPerFrame * 32; + mp4::AAC::kFramesPerAccessUnit * 32; const uint32 sink_buffer_size_in_frames_per_channel = initial_rebuffering_frames_per_channel * 8; const uint32 max_hardware_channels = 2;
diff --git a/src/media/audio/shell_audio_sink.cc b/src/media/audio/shell_audio_sink.cc index be1a8d9..e46d3f7 100644 --- a/src/media/audio/shell_audio_sink.cc +++ b/src/media/audio/shell_audio_sink.cc
@@ -227,7 +227,7 @@ // Number of ms of buffered playback remaining uint32_t buffered_time = (*total_frames * 1000 / audio_parameters_.sample_rate()); - if (free_frames >= mp4::AAC::kSamplesPerFrame) { + if (free_frames >= mp4::AAC::kFramesPerAccessUnit) { SetupRenderAudioBus(); int frames_rendered = @@ -238,7 +238,7 @@ // +ve value indicates number of samples in a successful read // TODO: We cannot guarantee this on platforms that use a resampler. Check // if it is possible to move the resample into the streamer. - // DCHECK_EQ(frames_rendered, mp4::AAC::kSamplesPerFrame); + // DCHECK_EQ(frames_rendered, mp4::AAC::kFramesPerAccessUnit); render_frame_cursor_ += frames_rendered; *total_frames += frames_rendered; free_frames -= frames_rendered; @@ -247,7 +247,7 @@ render_callback_->Render(NULL, buffered_time); } - bool buffer_full = free_frames < mp4::AAC::kSamplesPerFrame; + bool buffer_full = free_frames < mp4::AAC::kFramesPerAccessUnit; DCHECK_LE(*total_frames, static_cast<uint32>(std::numeric_limits<int32>::max())); bool rebuffer_threshold_reached = @@ -266,7 +266,7 @@ #endif // #if defined(OS_STARBOARD) #if defined(MEDIA_UNDERFLOW_DETECTED_BY_AUDIO_SINK) - const size_t kUnderflowThreshold = mp4::AAC::kSamplesPerFrame / 2; + const size_t kUnderflowThreshold = mp4::AAC::kFramesPerAccessUnit / 2; if (*total_frames < kUnderflowThreshold) { if (!rebuffering_) { rebuffering_ = true; @@ -313,7 +313,7 @@ // check for buffer wraparound, hopefully rare int render_frame_position = render_frame_cursor_ % settings_.per_channel_frames(audio_bus_.get()); - int requested_frames = mp4::AAC::kSamplesPerFrame; + int requested_frames = mp4::AAC::kFramesPerAccessUnit; if (render_frame_position + requested_frames > settings_.per_channel_frames(audio_bus_.get())) { requested_frames =
diff --git a/src/media/audio/shell_audio_sink_unittest.cc b/src/media/audio/shell_audio_sink_unittest.cc index 6860ffe..60995c1 100644 --- a/src/media/audio/shell_audio_sink_unittest.cc +++ b/src/media/audio/shell_audio_sink_unittest.cc
@@ -33,7 +33,7 @@ using namespace testing; const uint32 kMaxHardwareChannelsStereo = 2; -const size_t kSamplesPerFrame = media::mp4::AAC::kSamplesPerFrame; +const size_t kFramesPerAccessUnit = media::mp4::AAC::kFramesPerAccessUnit; bool operator==(const media::AudioParameters& params1, const media::AudioParameters& params2) { @@ -483,8 +483,8 @@ for (int i = 0; i < 10; ++i) { // Try to get 1024 frames but don't give it any data EXPECT_CALL(render_callback_, Render(_, _)) - .WillOnce( - VerifyAudioBusFrameCount(config, init_params, kSamplesPerFrame)); + .WillOnce(VerifyAudioBusFrameCount(config, init_params, + kFramesPerAccessUnit)); EXPECT_FALSE(sink_->PullFrames(NULL, NULL)); // Ok, now give it 1024 frames @@ -494,8 +494,8 @@ // Try to get another 1024 frames but don't give it any data EXPECT_CALL(render_callback_, Render(_, _)) - .WillOnce( - VerifyAudioBusFrameCount(config, init_params, kSamplesPerFrame)); + .WillOnce(VerifyAudioBusFrameCount(config, init_params, + kFramesPerAccessUnit)); EXPECT_FALSE(sink_->PullFrames(NULL, NULL)); // Ok, now give it 480 frames
diff --git a/src/media/audio/shell_audio_streamer.h b/src/media/audio/shell_audio_streamer.h index b6caca7..ca529b3 100644 --- a/src/media/audio/shell_audio_streamer.h +++ b/src/media/audio/shell_audio_streamer.h
@@ -91,11 +91,13 @@ max_hardware_channels_(max_hardware_channels), bytes_per_sample_(bytes_per_sample), native_output_sample_rate_(native_output_sample_rate) { - const size_t kSamplesPerFrame = mp4::AAC::kSamplesPerFrame; + const size_t kFramesPerAccessUnit = mp4::AAC::kFramesPerAccessUnit; DCHECK_LE(initial_rebuffering_frames_per_channel, sink_buffer_size_in_frames_per_channel); - DCHECK_EQ(initial_rebuffering_frames_per_channel % kSamplesPerFrame, 0); - DCHECK_EQ(sink_buffer_size_in_frames_per_channel % kSamplesPerFrame, 0); + DCHECK_EQ(initial_rebuffering_frames_per_channel % kFramesPerAccessUnit, + 0); + DCHECK_EQ(sink_buffer_size_in_frames_per_channel % kFramesPerAccessUnit, + 0); } bool interleaved() const {
diff --git a/src/media/audio/shell_audio_streamer_linux.cc b/src/media/audio/shell_audio_streamer_linux.cc index 7852ec7..cd35b97 100644 --- a/src/media/audio/shell_audio_streamer_linux.cc +++ b/src/media/audio/shell_audio_streamer_linux.cc
@@ -58,7 +58,7 @@ ShellAudioStreamer::Config ShellAudioStreamerLinux::GetConfig() const { const uint32 initial_rebuffering_frames_per_channel = - mp4::AAC::kSamplesPerFrame * 32; + mp4::AAC::kFramesPerAccessUnit * 32; const uint32 sink_buffer_size_in_frames_per_channel = initial_rebuffering_frames_per_channel * 8; const uint32 max_hardware_channels = 2;
diff --git a/src/media/base/decoder_buffer_pool.h b/src/media/base/decoder_buffer_pool.h index f278f39..2b2636b 100644 --- a/src/media/base/decoder_buffer_pool.h +++ b/src/media/base/decoder_buffer_pool.h
@@ -35,7 +35,7 @@ public: static const uint32 kMaxAudioChannels = 8; // We support 7.1 at most. static const uint32 kMaxSamplesPerBuffer = - mp4::AAC::kSamplesPerFrame * kMaxAudioChannels; + mp4::AAC::kFramesPerAccessUnit * kMaxAudioChannels; static const size_t kBufferCount = 48; DecoderBufferPool(uint32 sample_size_in_bytes);
diff --git a/src/media/base/shell_video_data_allocator.cc b/src/media/base/shell_video_data_allocator.cc index 8e24adb..e47e518 100644 --- a/src/media/base/shell_video_data_allocator.cc +++ b/src/media/base/shell_video_data_allocator.cc
@@ -22,15 +22,16 @@ ShellVideoDataAllocator::YV12Param::YV12Param(int decoded_width, int decoded_height, - const gfx::Rect& visible_rect) + const gfx::Rect& visible_rect, + uint8* data) : decoded_width_(decoded_width), decoded_height_(decoded_height), visible_rect_(visible_rect), - y_pitch_(0), - uv_pitch_(0), - y_data_(NULL), - u_data_(NULL), - v_data_(NULL) {} + y_pitch_(decoded_width), + uv_pitch_(decoded_width / 2), + y_data_(data), + u_data_(y_data_ + y_pitch_ * decoded_height_), + v_data_(u_data_ + uv_pitch_ * decoded_height_ / 2) {} ShellVideoDataAllocator::YV12Param::YV12Param(int width, int height,
diff --git a/src/media/base/shell_video_data_allocator.h b/src/media/base/shell_video_data_allocator.h index 1a61a06..ca164a2 100644 --- a/src/media/base/shell_video_data_allocator.h +++ b/src/media/base/shell_video_data_allocator.h
@@ -47,7 +47,8 @@ public: YV12Param(int decoded_width, int decoded_height, - const gfx::Rect& visible_rect); + const gfx::Rect& visible_rect, + uint8* data); // Create with data pointer to individual planes. All pointers should be in // the same memory block controlled by the accompanied FrameBuffer passed to
diff --git a/src/media/base/video_resolution.h b/src/media/base/video_resolution.h new file mode 100644 index 0000000..714cca1 --- /dev/null +++ b/src/media/base/video_resolution.h
@@ -0,0 +1,54 @@ +/* + * 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 MEDIA_BASE_VIDEO_RESOLUTION_H_ +#define MEDIA_BASE_VIDEO_RESOLUTION_H_ + +#include "media/base/media_export.h" +#include "ui/gfx/size.h" + +namespace media { + +// Enumerates the various representations of the resolution of videos. Note +// that except |kVideoResolutionInvalid|, all other values are guaranteed to be +// in the same order as its (width, height) pair. +enum VideoResolution { + kVideoResolution1080p, // 1920 x 1080 + kVideoResolution2k, // 2560 x 1440 + kVideoResolution4k, // 3840 x 2160 + kVideoResolutionInvalid +}; + +inline VideoResolution GetVideoResolution(int width, int height) { + if (width <= 1920 && height <= 1080) { + return kVideoResolution1080p; + } + if (width <= 2560 && height <= 1440) { + return kVideoResolution2k; + } + if (width <= 3840 && height <= 2160) { + return kVideoResolution4k; + } + return kVideoResolutionInvalid; +} + +inline VideoResolution GetVideoResolution(const gfx::Size& size) { + return GetVideoResolution(size.width(), size.height()); +} + +} // namespace media + +#endif // MEDIA_BASE_VIDEO_RESOLUTION_H_
diff --git a/src/media/filters/shell_audio_decoder_impl.cc b/src/media/filters/shell_audio_decoder_impl.cc index a38259a..2141df3 100644 --- a/src/media/filters/shell_audio_decoder_impl.cc +++ b/src/media/filters/shell_audio_decoder_impl.cc
@@ -30,7 +30,7 @@ using base::Time; using base::TimeDelta; -const size_t kSamplesPerFrame = mp4::AAC::kSamplesPerFrame; +const size_t kFramesPerAccessUnit = mp4::AAC::kFramesPerAccessUnit; namespace { @@ -334,7 +334,7 @@ "ShellAudioDecoderImpl::DecodeBuffer() data decoded.", "timestamp", buffer->GetTimestamp().InMicroseconds()); DCHECK_EQ(buffer->GetDataSize(), - kSamplesPerFrame * bits_per_channel() / 8 * num_channels_); + kFramesPerAccessUnit * bits_per_channel() / 8 * num_channels_); PipelineStatistics statistics; statistics.audio_bytes_decoded = buffer->GetDataSize();
diff --git a/src/media/filters/shell_audio_renderer_impl.cc b/src/media/filters/shell_audio_renderer_impl.cc index a6cc8ac..81b5115 100644 --- a/src/media/filters/shell_audio_renderer_impl.cc +++ b/src/media/filters/shell_audio_renderer_impl.cc
@@ -247,10 +247,10 @@ decrypting_demuxer_stream_ = decrypting_demuxer_stream; // construct audio parameters for the sink - audio_parameters_ = - AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, - decoder_->samples_per_second(), - decoder_->bits_per_channel(), mp4::AAC::kSamplesPerFrame); + audio_parameters_ = AudioParameters( + AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, + decoder_->samples_per_second(), decoder_->bits_per_channel(), + mp4::AAC::kFramesPerAccessUnit); state_ = kPaused; @@ -486,16 +486,16 @@ if (end_of_stream_state_ == kWaitingForEOS) { // Normal decode event rendered_timestamp_ = buffered_timestamp_; - frames_rendered = mp4::AAC::kSamplesPerFrame; + frames_rendered = mp4::AAC::kFramesPerAccessUnit; } if (end_of_stream_state_ == kReceivedEOS) { end_of_stream_state_ = kRenderedEOS; } if (end_of_stream_state_ == kRenderedEOS) { const int bytes_per_sample = audio_parameters_.bits_per_sample() / 8; - // TODO: Change this to DCHECK_LE and fill only kSamplesPerFrame + // TODO: Change this to DCHECK_LE and fill only kFramesPerAccessUnit // instead of dest->frames() once we support Read with arbitrary size. - DCHECK_EQ(mp4::AAC::kSamplesPerFrame * bytes_per_sample * + DCHECK_EQ(mp4::AAC::kFramesPerAccessUnit * bytes_per_sample * audio_parameters_.channels(), dest->frames() * dest->channels() * sizeof(float)); // Write zeros (silence) to each channel @@ -505,8 +505,8 @@ dest->frames() * sizeof(float); // NOLINT(runtime/sizeof) memset(channel_data, 0, num_bytes); } - frames_rendered = mp4::AAC::kSamplesPerFrame; - uint64_t silence_ms = mp4::AAC::kSamplesPerFrame * 1000 / + frames_rendered = mp4::AAC::kFramesPerAccessUnit; + uint64_t silence_ms = mp4::AAC::kFramesPerAccessUnit * 1000 / audio_parameters_.sample_rate(); silence_rendered_ += base::TimeDelta::FromMilliseconds(silence_ms); }
diff --git a/src/media/filters/shell_flv_parser.cc b/src/media/filters/shell_flv_parser.cc index d5b3e23..5d517ad 100644 --- a/src/media/filters/shell_flv_parser.cc +++ b/src/media/filters/shell_flv_parser.cc
@@ -111,6 +111,10 @@ } } + if (duration_.InMilliseconds() == 0) { + return false; + } + // We may have a valid duration by now and the reader may know the // length of the file in bytes, see if we can extrapolate a bitrate from // this. @@ -250,13 +254,14 @@ bool ShellFLVParser::ParseNextTag() { uint8 tag_buffer[kTagDownloadSize]; - int bytes_read = 0; - if (!at_end_of_file_) { - // get previous tag size and header for next one - bytes_read = - reader_->BlockingRead(tag_offset_, kTagDownloadSize, tag_buffer); + if (at_end_of_file_) { + return false; } + // get previous tag size and header for next one + int bytes_read = + reader_->BlockingRead(tag_offset_, kTagDownloadSize, tag_buffer); + // if that was the last tag in the stream detect the EOS and return. This // is where normal termination of an FLV stream will occur. if (bytes_read < kTagDownloadSize) {
diff --git a/src/media/filters/shell_mp4_map.cc b/src/media/filters/shell_mp4_map.cc index a65e2c7..1d8b8d6 100644 --- a/src/media/filters/shell_mp4_map.cc +++ b/src/media/filters/shell_mp4_map.cc
@@ -959,9 +959,8 @@ } } } - DCHECK_GE(sample_number, stss_last_keyframe_); - DCHECK_LT(sample_number, stss_next_keyframe_); - return true; + return sample_number >= stss_last_keyframe_ && + sample_number < stss_next_keyframe_; } // The stts table has the following per-entry layout:
diff --git a/src/media/filters/shell_mp4_parser.cc b/src/media/filters/shell_mp4_parser.cc index b72f183..20ea082 100644 --- a/src/media/filters/shell_mp4_parser.cc +++ b/src/media/filters/shell_mp4_parser.cc
@@ -139,7 +139,10 @@ base::TimeDelta timestamp; base::TimeDelta duration; if (type == DemuxerStream::AUDIO) { - DCHECK_NE(audio_time_scale_hz_, 0); + if (audio_time_scale_hz_ == 0) { + DLOG(ERROR) << "|audio_time_scale_hz_| cannot be 0."; + return NULL; + } if (!audio_map_->GetSize(audio_sample_, size) || !audio_map_->GetOffset(audio_sample_, offset) || !audio_map_->GetDuration(audio_sample_, duration_ticks) || @@ -183,6 +186,10 @@ first_audio_hole_ = timestamp + duration; } } else if (type == DemuxerStream::VIDEO) { + if (video_time_scale_hz_ == 0) { + DLOG(ERROR) << "|video_time_scale_hz_| cannot be 0."; + return NULL; + } if (!video_map_->GetSize(video_sample_, size) || !video_map_->GetOffset(video_sample_, offset) || !video_map_->GetDuration(video_sample_, duration_ticks) || @@ -197,7 +204,6 @@ } } video_sample_++; - DCHECK_NE(video_time_scale_hz_, 0); timestamp = TicksToTime(timestamp_ticks, video_time_scale_hz_); duration = TicksToTime(duration_ticks, video_time_scale_hz_); // due to b-frames it's much more likely we'll encounter discontinuous @@ -221,8 +227,14 @@ } bool ShellMP4Parser::SeekTo(base::TimeDelta timestamp) { - DCHECK_NE(video_time_scale_hz_, 0); - DCHECK_NE(audio_time_scale_hz_, 0); + if (audio_time_scale_hz_ == 0 || video_time_scale_hz_ == 0) { + DLOG_IF(ERROR, audio_time_scale_hz_ == 0) + << "|audio_time_scale_hz_| cannot be 0."; + DLOG_IF(ERROR, video_time_scale_hz_ == 0) + << "|video_time_scale_hz_| cannot be 0."; + return false; + } + // get video timestamp in video time units uint64 video_ticks = TimeToTicks(timestamp, video_time_scale_hz_); // find nearest keyframe from map, make it our next video sample @@ -682,7 +694,7 @@ return false; } uint32 time_scale_hz = endian_util::load_uint32_big_endian(mvhd + 12); - if (!time_scale_hz) { + if (time_scale_hz == 0) { DLOG(WARNING) << "got 0 time scale for mvhd"; return false; } @@ -698,12 +710,20 @@ base::TimeDelta ShellMP4Parser::TicksToTime(uint64 ticks, uint32 time_scale_hz) { DCHECK_NE(time_scale_hz, 0); + + if (time_scale_hz == 0) { + return base::TimeDelta::FromSeconds(0); + } return base::TimeDelta::FromMicroseconds((ticks * 1000000ULL) / time_scale_hz); } uint64 ShellMP4Parser::TimeToTicks(base::TimeDelta time, uint32 time_scale_hz) { - DCHECK(time_scale_hz); + DCHECK_NE(time_scale_hz, 0); + + if (time_scale_hz == 0) { + return 0; + } return (time.InMicroseconds() * time_scale_hz) / 1000000ULL; }
diff --git a/src/media/filters/shell_raw_audio_decoder_linux.cc b/src/media/filters/shell_raw_audio_decoder_linux.cc index 1316040..40785c5 100644 --- a/src/media/filters/shell_raw_audio_decoder_linux.cc +++ b/src/media/filters/shell_raw_audio_decoder_linux.cc
@@ -311,7 +311,7 @@ if (decoded_audio_size > 0) { // Copy the audio samples into an output buffer. - int buffer_size = kSampleSizeInBytes * mp4::AAC::kSamplesPerFrame * + int buffer_size = kSampleSizeInBytes * mp4::AAC::kFramesPerAccessUnit * codec_context_->channels; output = decoder_buffer_pool_.Allocate(buffer_size); DCHECK(output); @@ -319,7 +319,7 @@ // requirement. This should eventually be lifted. ResampleToInterleavedFloat( codec_context_->sample_fmt, codec_context_->channel_layout, - samples_per_second_, mp4::AAC::kSamplesPerFrame, + samples_per_second_, mp4::AAC::kFramesPerAccessUnit, av_frame_->extended_data, reinterpret_cast<uint8*>(output->GetWritableData())); output->SetTimestamp(output_timestamp_helper_->GetTimestamp());
diff --git a/src/media/filters/shell_raw_audio_decoder_stub.cc b/src/media/filters/shell_raw_audio_decoder_stub.cc index 1b903d4..6231cc2 100644 --- a/src/media/filters/shell_raw_audio_decoder_stub.cc +++ b/src/media/filters/shell_raw_audio_decoder_stub.cc
@@ -77,7 +77,7 @@ } decoded_buffer_size_ = - kSampleSizeInBytes * channel_count * mp4::AAC::kSamplesPerFrame; + kSampleSizeInBytes * channel_count * mp4::AAC::kFramesPerAccessUnit; return true; }
diff --git a/src/media/filters/shell_raw_video_decoder_linux.cc b/src/media/filters/shell_raw_video_decoder_linux.cc index 5d873a4..703ac46 100644 --- a/src/media/filters/shell_raw_video_decoder_linux.cc +++ b/src/media/filters/shell_raw_video_decoder_linux.cc
@@ -225,7 +225,8 @@ // It is worth revisiting if we are going to release Linux as a production // platform. YV12Param param(av_frame_->width, av_frame_->height, - gfx::Rect(av_frame_->width, av_frame_->height)); + gfx::Rect(av_frame_->width, av_frame_->height), + frame_buffer->data()); // We have to make a copy of the frame buffer as the frame buffer retrieved // from |av_frame_->opaque| may still be used by Ffmpeg. size_t yv12_frame_size =
diff --git a/src/media/filters/shell_raw_video_decoder_stub.cc b/src/media/filters/shell_raw_video_decoder_stub.cc index 9226792..333cdec 100644 --- a/src/media/filters/shell_raw_video_decoder_stub.cc +++ b/src/media/filters/shell_raw_video_decoder_stub.cc
@@ -53,7 +53,7 @@ scoped_refptr<FrameBuffer> frame_buffer = allocator_->AllocateFrameBuffer(yuv_size, 1); YV12Param param(natural_size_.width(), natural_size_.height(), - gfx::Rect(natural_size_)); + gfx::Rect(natural_size_), frame_buffer->data()); scoped_refptr<VideoFrame> frame = allocator_->CreateYV12Frame(frame_buffer, param, buffer->GetTimestamp()); decode_cb.Run(FRAME_DECODED, frame);
diff --git a/src/media/filters/shell_video_decoder_impl.cc b/src/media/filters/shell_video_decoder_impl.cc index a9555fd..96e24b7 100644 --- a/src/media/filters/shell_video_decoder_impl.cc +++ b/src/media/filters/shell_video_decoder_impl.cc
@@ -69,8 +69,8 @@ VideoDecoderConfig decoder_config; decoder_config.CopyFrom(demuxer_stream_->video_decoder_config()); - DLOG(INFO) << "Configuration at Start: " - << decoder_config.AsHumanReadableString(); + LOG(INFO) << "Configuration at Start: " + << decoder_config.AsHumanReadableString(); raw_decoder_ = raw_video_decoder_factory_->Create( decoder_config, demuxer_stream_->GetDecryptor(), @@ -175,8 +175,8 @@ if (demuxer_status == DemuxerStream::kConfigChanged) { VideoDecoderConfig decoder_config; decoder_config.CopyFrom(demuxer_stream_->video_decoder_config()); - DLOG(INFO) << "Configuration Changed: " - << decoder_config.AsHumanReadableString(); + LOG(INFO) << "Configuration Changed: " + << decoder_config.AsHumanReadableString(); // One side effect of asking for the video configuration is that // the MediaSource demuxer stack uses that request to determine // that the video decoder has updated its configuration.
diff --git a/src/media/media.gyp b/src/media/media.gyp index e020dc1..c2faa35 100644 --- a/src/media/media.gyp +++ b/src/media/media.gyp
@@ -609,8 +609,11 @@ 'filters/shell_raw_video_decoder_ps4.h', 'filters/shell_raw_vp9_decoder_ps4.cc', 'filters/shell_raw_vp9_decoder_ps4.h', + 'filters/videodec2_working_memory_ps4.cc', + 'filters/videodec2_working_memory_ps4.h', ], 'dependencies' : [ + '<(DEPTH)/nb/nb.gyp:nb', '<(DEPTH)/third_party/libvpx_gpu/libvpx_gpu.gyp:libvpx_gpu', ], }],
diff --git a/src/media/mp4/aac.h b/src/media/mp4/aac.h index 1dc1b70..1f581e5 100644 --- a/src/media/mp4/aac.h +++ b/src/media/mp4/aac.h
@@ -23,6 +23,10 @@ // for more details. class MEDIA_EXPORT AAC { public: + // Size in bytes of the ADTS header added by ConvertEsdsToADTS(). + static const size_t kADTSHeaderSize = 7; + static const size_t kFramesPerAccessUnit = 1024; + AAC(); ~AAC(); @@ -50,10 +54,6 @@ const std::vector<uint8>& raw_data() const { return raw_data_; } #endif // COBALT_WIN - // Size in bytes of the ADTS header added by ConvertEsdsToADTS(). - static const size_t kADTSHeaderSize = 7; - static const size_t kSamplesPerFrame = 1024; - private: bool SkipDecoderGASpecificConfig(BitReader* bit_reader) const; bool SkipErrorSpecificConfig() const;
diff --git a/src/media/player/mime_util.cc b/src/media/player/mime_util.cc index 2d1d9ee..86b0a5b 100644 --- a/src/media/player/mime_util.cc +++ b/src/media/player/mime_util.cc
@@ -451,9 +451,14 @@ #if defined(__LB_ANDROID__) // Assume Android supports everything. { "video/webm", "vorbis,vp8,vp8.0,vp9" }, { "audio/webm", "vorbis" }, -#elif defined(ENABLE_WEB_VP9) - {"video/webm", "vp9"}, - {"audio/webm", ""}, +#elif defined(OS_STARBOARD) +#if SB_HAS(MEDIA_WEBM_VP9_SUPPORT) + {"video/webm", "vp9"}, + {"audio/webm", ""}, +#else // SB_HAS(MEDIA_WEBM_VP9_SUPPORT) + {"video/webm", ""}, + {"audio/webm", ""}, +#endif // SB_HAS(MEDIA_WEBM_VP9_SUPPORT) #elif defined(__LB_SHELL__) || defined(COBALT) // No other platforms support webm. { "video/webm", "" },
diff --git a/src/nb/fixed_no_free_allocator.cc b/src/nb/fixed_no_free_allocator.cc index 062f17c..3722da6 100644 --- a/src/nb/fixed_no_free_allocator.cc +++ b/src/nb/fixed_no_free_allocator.cc
@@ -34,6 +34,11 @@ uint8_t* aligned_next_memory = AsPointer(AlignUp(AsInteger(next_memory_), alignment)); + if (aligned_next_memory + size < aligned_next_memory) { + // "aligned_next_memory + size" overflows. + return NULL; + } + if (aligned_next_memory + size > memory_end_) { // We don't have enough memory available to make this allocation. return NULL;
diff --git a/src/net/net.gyp b/src/net/net.gyp index d6dab37..3d7b9d4 100644 --- a/src/net/net.gyp +++ b/src/net/net.gyp
@@ -129,8 +129,6 @@ 'base/data_url.h', 'base/default_server_bound_cert_store.cc', 'base/default_server_bound_cert_store.h', - 'base/directory_lister.cc', - 'base/directory_lister.h', 'base/dns_reloader.cc', 'base/dns_reloader.h', 'base/dns_util.cc', @@ -985,6 +983,9 @@ ['exclude', 'disk_cache/cache_util_posix.cc'], ['exclude', 'disk_cache/file_posix.cc'], ['exclude', 'disk_cache/mapped_file_posix.cc'], + # we don't use the directory lister + ['exclude', 'base/directory_lister.cc'], + ['exclude', 'base/directory_lister.h'], # or SDCH, Shared Dictionary Compression over HTTP ['exclude', 'sdch'], # exclude any v8-specific bindings @@ -1528,7 +1529,6 @@ 'base/crl_set_unittest.cc', 'base/data_url_unittest.cc', 'base/default_server_bound_cert_store_unittest.cc', - 'base/directory_lister_unittest.cc', 'base/dns_util_unittest.cc', 'base/dnsrr_resolver_unittest.cc', 'base/escape_unittest.cc', @@ -2076,6 +2076,7 @@ ['exclude', 'python_utils_unittest'], ['exclude', 'proxy_script_fetcher_impl_unittest'], ['exclude', 'x509_cert_types_unittest'], # ParseDistinguishedName() only exists for mac/win + ['exclude', 'directory_lister_unittest'], # Not used. # FTP is not supported ['exclude', 'ftp_auth_cache_unittest'], ['exclude', 'ftp_ctrl_response_buffer_unittest'], @@ -2389,7 +2390,7 @@ 'variables': { 'executable_name': 'net_unittests', }, - 'includes': [ '../cobalt/build/deploy.gypi' ], + 'includes': [ '../starboard/build/deploy.gypi' ], }, ], }],
diff --git a/src/net/socket/transport_client_socket_unittest.cc b/src/net/socket/transport_client_socket_unittest.cc index a7a6edf..317b713 100644 --- a/src/net/socket/transport_client_socket_unittest.cc +++ b/src/net/socket/transport_client_socket_unittest.cc
@@ -105,6 +105,14 @@ // Find a free port to listen on scoped_refptr<TCPListenSocket> sock; int port; +#if defined(STARBOARD) + // Let the system choose a port for us. + sock = TCPListenSocket::CreateAndListen("127.0.0.1", 0, this); + ASSERT_TRUE(sock != NULL); + IPEndPoint address; + ASSERT_TRUE(sock->GetLocalAddress(&address) == 0); + port = address.port(); +#else // Range of ports to listen on. Shouldn't need to try many. const int kMinPort = 10100; const int kMaxPort = 10200; @@ -116,6 +124,7 @@ if (sock.get()) break; } +#endif ASSERT_TRUE(sock != NULL); listen_sock_ = sock; listen_port_ = port;
diff --git a/src/sql/sql.gyp b/src/sql/sql.gyp index 23fd2eb..8d354f9 100644 --- a/src/sql/sql.gyp +++ b/src/sql/sql.gyp
@@ -110,7 +110,7 @@ 'variables': { 'executable_name': 'sql_unittests', }, - 'includes': [ '../cobalt/build/deploy.gypi' ], + 'includes': [ '../starboard/build/deploy.gypi' ], }, ], }],
diff --git a/src/starboard/README.md b/src/starboard/README.md index f5cf36f..3d35ee3 100644 --- a/src/starboard/README.md +++ b/src/starboard/README.md
@@ -7,14 +7,8 @@ ## Current State -Starboard is still in development, and now runs Cobalt. The biggest things that -are missing, but coming soon, are: - - * Media support. Some APIs have been defined, but they are not complete, they - are not wired into Cobalt, they aren't yet implemented, and they are subject - to change. - * Blitter support. This is support for a hardware accelerated 2D blitter, - which some older platforms will have instead of OpenGL. +Desktop Linux Cobalt is fully implemented on top of Starboard, and version 1 of +the Starboard API is mostly locked down. ## Interesting Source Locations @@ -141,9 +135,19 @@ valid if you copy it to a new directory. You can then incrementally replace files with new implementations as necessary. -For example, if your device runs Linux, you should start from linux. +The cleanest, simplest starting point is from the Stub reference +implementation. Nothing will work, but you should be able to compile and link it +with your toolchain. You can then replace stub implementations with +implementations from `src/starboard/shared` or your own custom implementations +module-by-module, until you have gone through all modules. -Rename the `x64x11/` directory to `<binary-variant>` (e.g. `mipseb`). +You may also choose to copy either the Desktop Linux or Raspberry Pi ports and +work backwards fixing things that don't compile or work on your platform. + +For example, for `bobbox-mipsel`, you might do: + + mkdir -p src/third_party/starboard/bobbox + cp -R src/starboard/stub src/third_party/starboard/bobbox/mipsel Modify the files in `<binary-variant>/` as appropriate (you will probably be coming back to these files a lot). @@ -154,9 +158,6 @@ `src/` directory of your source tree. Otherwise, files are assumed to be relative to the directory the `.gyp` or `.gypi` file is in. - -### IV. Add Your Platform Configurations to cobalt_gyp - In order to use a new platform configuration in a build, you need to ensure that you have a `gyp_configuration.py`, `gyp_configuration.gypi`, and `starboard_platform.gypi` in their own directory for each binary variant, plus @@ -165,28 +166,30 @@ files, and then calculate a port name based on the directories between `src/third_party/starboard` and your `gyp_configuration.*` files. (e.g. for `src/third_party/starboard/bobbox/mipseb/gyp_configuration.py`, it would choose -the port name `bobbox_mipseb`.) +the platform configuration name `bobbox-mipseb`.) - 1. Set up `gyp_configuration.py` - 1. Copy `src/starboard/linux/x64x11/gyp_configuration.py` to - `src/third_party/starboard/<family-name>/<binary-variant>/gyp_configuration.py`. - You may also consider copying from another reference platform, like `raspi-1`. - 1. In `gyp_configuration.py` - 1. In the `_PlatformConfig.__init__()` function, remove checks for Clang - or GOMA. - 1. In the `CreatePlatformConfig()` function, pass your - `<platform-configuration>` as the parameter to the _PlatformConfig - constructor, like `return _PlatformConfig('bobbox-mipseb')`. - 1. In `GetVariables` - 1. Set `'clang': 1` if your toolchain is clang. - 1. Delete other variables in that function that are not needed for - your platform. - 1. In `GetEnvironmentVariables`, set the dictionary values to point - to the toolchain analogs for the toolchain for your platform. - 1. Set up `gyp_configuration.gypi` - 1. Copy `src/starboard/linux/x64x11/gyp_configuration.gypi` to - `src/third_party/starboard/<family-name>/<binary-variant>/gyp_configuration.gypi`. - You may also consider copying from another reference platform, like `raspi-1`. + +### IV. A New Port, Step-by-Step + + 1. Recursively copy `src/starboard/stub` to + `src/third_party/starboard/<family-name>/<binary-variant>`. You may also + consider copying from another reference platform, like `raspi-1` or + `linux-x64x11`. + 1. In `gyp_configuration.py` + 1. In the `CreatePlatformConfig()` function, pass your + `<platform-configuration>` as the parameter to the PlatformConfig + constructor, like `return PlatformConfig('bobbox-mipseb')`. + 1. In `GetVariables` + 1. Set `'clang': 1` if your toolchain is clang. + 1. Delete other variables in that function that are not needed for + your platform. + 1. In `GetEnvironmentVariables`, set the dictionary values to point to the + toolchain analogs for the toolchain for your platform. + 1. In `gyp_configuration.gypi` + 1. Update the names of the configurations and the default_configuration to + be `<platform-configuation>_<build-type>` for your platform + configuration name, where `<build-type>` is one of `debug`, `devel`, + `qa`, `gold`. 1. Update your platform variables. 1. Set `'target_arch'` to your architecture: `'arm'`, `'ppc'`, `'x64'`, `'x86'`, `'mips'` @@ -202,6 +205,12 @@ different for someone else. 1. Update the global defines in `'target_defaults'.'defines'`, if necessary. + 1. Go through `configuration_public.h` and adjust all the configuration values + as appropriate for your platform. + 1. Update `starboard_platform.gyp` to point at all the source files you want + to build as part of your new Starboard implementation (as mentioned above). + 1. Update `atomic_public.h` and `thread_types_public.h` as necessary to point + at the appropriate shared or custom implementations. You should now be able to run gyp with your new port. From your `src/` directory:
diff --git a/src/starboard/__init__.py b/src/starboard/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/starboard/__init__.py
diff --git a/src/starboard/build/__init__.py b/src/starboard/build/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/starboard/build/__init__.py
diff --git a/src/starboard/build/convert_i18n_data.gypi b/src/starboard/build/convert_i18n_data.gypi new file mode 100644 index 0000000..461e046 --- /dev/null +++ b/src/starboard/build/convert_i18n_data.gypi
@@ -0,0 +1,57 @@ +# 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 file is meant to be included into an action to convert a set of XLB files +# into files of a simpler format (e.g. CSV) in the product directory, e.g. +# e.g. out/ps4_debug/content/data/i18n. +# +# To use this, create a gyp target with the following form: +# { +# 'target_name': 'convert_i18n_data', +# 'type': 'none', +# 'actions': [ +# { +# 'action_name': 'convert_i18n_data', +# 'variables': { +# 'input_files': +# '<!(find <(DEPTH)/cobalt/content/i18n/platform/linux/*.xlb)', +# }, +# 'includes': [ '../build/convert_i18n_data.gypi' ], +# }, +# ], +# }, +# +# Meaning of the variables: +# input_files: list of paths to XLB files; directories are not expanded. + +{ + 'variables': { + 'output_dir': '<(PRODUCT_DIR)/content/data/i18n' + }, + + 'inputs': [ + '<!@pymod_do_main(starboard.build.convert_i18n_data -o <@(output_dir) --inputs <@(input_files))', + ], + + 'outputs': [ + '<!@pymod_do_main(starboard.build.convert_i18n_data -o <@(output_dir) --outputs <@(input_files))', + ], + + 'action': [ + 'python', + '<(DEPTH)/starboard/build/convert_i18n_data.py', + '-o', '<@(output_dir)', + '<@(input_files)', + ], +}
diff --git a/src/starboard/build/convert_i18n_data.py b/src/starboard/build/convert_i18n_data.py new file mode 100644 index 0000000..a34916a --- /dev/null +++ b/src/starboard/build/convert_i18n_data.py
@@ -0,0 +1,135 @@ +#!/usr/bin/python +# 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. + +"""Converts XLB files into CSV files in a given output directory. + +Since the output of this script is intended to be use by GYP, all resulting +paths are using Unix-style forward slashes. +""" + +import argparse +import os +import posixpath +import sys +import xml.etree.ElementTree + + +class WrongNumberOfArgumentsException(Exception): + pass + + +def EscapePath(path): + """Returns a path with spaces escaped.""" + return path.replace(' ', '\\ ') + + +def ChangeSuffix(filename, new_suffix): + """Changes the suffix of |filename| to |new_suffix|. If no current suffix, + adds |new_suffix| to the end of |filename|.""" + (root, ext) = os.path.splitext(filename) + return root + '.' + new_suffix + + +def ConvertSingleFile(filename, output_filename): + """Converts a single input XLB file to a CSV file.""" + tree = xml.etree.ElementTree.parse(filename) + root = tree.getroot() + + # First child of the root is the list of messages. + messages = root[0] + + # Write each message to the output file on its own line. + with open(output_filename, 'w') 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']) + output_file.write(msg.attrib['name']) + output_file.write(';') + # Encode the text as UTF8 to accommodate special characters. + output_file.write(msg.text.encode('utf8')) + output_file.write('\n') + + +def GetOutputs(files_to_convert, output_basedir): + """Returns a list of filenames relative to the output directory, + based on a list of input files.""" + outputs = []; + for filename in files_to_convert: + dirname = posixpath.dirname(filename) + relative_filename = posixpath.relpath(filename, dirname) + relative_filename = ChangeSuffix(relative_filename, 'csv') + output_filename = posixpath.join(output_basedir, relative_filename) + outputs.append(output_filename) + + return outputs + + +def ConvertFiles(files_to_convert, output_basedir): + """Converts files and writes the result the given output directory.""" + for filename in files_to_convert: + dirname = posixpath.dirname(filename) + relative_filename = posixpath.relpath(filename, dirname) + output_filename = posixpath.join(output_basedir, relative_filename) + output_dir = posixpath.dirname(output_filename) + + if not os.path.exists(output_dir): + os.makedirs(output_dir) + + output_filename = ChangeSuffix(output_filename, 'csv') + print 'Converting ' + filename + ' to ' + output_filename + ConvertSingleFile(filename, output_filename) + + +def DoMain(argv): + """Called by GYP using pymod_do_main.""" + parser = argparse.ArgumentParser() + parser.add_argument('-o', dest='output_dir', help='output directory') + parser.add_argument('--inputs', action='store_true', dest='list_inputs', + help='prints a list of all input files') + parser.add_argument('--outputs', action='store_true', dest='list_outputs', + help='prints a list of all output files') + parser.add_argument('input_paths', metavar='path', nargs='+', + help='path to an input file or directory') + options = parser.parse_args(argv) + + files_to_convert = [EscapePath(x) for x in options.input_paths] + + if options.list_inputs: + return '\n'.join(files_to_convert) + + if not options.output_dir: + raise WrongNumberOfArgumentsException('-o required.') + + if options.list_outputs: + outputs = GetOutputs(files_to_convert, options.output_dir) + return '\n'.join(outputs) + + ConvertFiles(files_to_convert, options.output_dir) + return + + +def main(argv): + print 'Running... in main()' + try: + result = DoMain(argv[1:]) + except WrongNumberOfArgumentsException, e: + print >> sys.stderr, e + return 1 + if result: + print result + return 0 + +if __name__ == '__main__': + sys.exit(main(sys.argv))
diff --git a/src/starboard/build/copy_data.py b/src/starboard/build/copy_data.py index c426dc0..cd1d6a2 100644 --- a/src/starboard/build/copy_data.py +++ b/src/starboard/build/copy_data.py
@@ -14,6 +14,7 @@ # limitations under the License. # This file is based on build/copy_test_data_ios.py + """Copies data files or directories into a given output directory. Since the output of this script is intended to be use by GYP, all resulting @@ -98,17 +99,11 @@ """Called by GYP using pymod_do_main.""" parser = argparse.ArgumentParser() parser.add_argument('-o', dest='output_dir', help='output directory') - parser.add_argument('--inputs', - action='store_true', - dest='list_inputs', + parser.add_argument('--inputs', action='store_true', dest='list_inputs', help='prints a list of all input files') - parser.add_argument('--outputs', - action='store_true', - dest='list_outputs', + parser.add_argument('--outputs', action='store_true', dest='list_outputs', help='prints a list of all output files') - parser.add_argument('input_paths', - metavar='path', - nargs='+', + parser.add_argument('input_paths', metavar='path', nargs='+', help='path to an input file or directory') options = parser.parse_args(argv) @@ -138,6 +133,5 @@ print result return 0 - if __name__ == '__main__': sys.exit(main(sys.argv))
diff --git a/src/starboard/build/copy_test_data.gypi b/src/starboard/build/copy_test_data.gypi index e4e47ed..13ac050 100644 --- a/src/starboard/build/copy_test_data.gypi +++ b/src/starboard/build/copy_test_data.gypi
@@ -50,14 +50,14 @@ { 'inputs': [ - '<!@pymod_do_main(copy_data --inputs <(input_files))', + '<!@pymod_do_main(starboard.build.copy_data --inputs <(input_files))', ], 'outputs': [ - '<!@pymod_do_main(copy_data -o <(PRODUCT_DIR)/content/dir_source_root/<(output_dir) --outputs <(input_files))', + '<!@pymod_do_main(starboard.build.copy_data -o <(PRODUCT_DIR)/content/dir_source_root/<(output_dir) --outputs <(input_files))', ], 'action': [ 'python', - '<(DEPTH)/cobalt/build/copy_data.py', + '<(DEPTH)/starboard/build/copy_data.py', '-o', '<(PRODUCT_DIR)/content/dir_source_root/<(output_dir)', '<@(input_files)', ],
diff --git a/src/starboard/build/deploy.gypi b/src/starboard/build/deploy.gypi new file mode 100644 index 0000000..ce7c9ce --- /dev/null +++ b/src/starboard/build/deploy.gypi
@@ -0,0 +1,54 @@ +# 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 file is meant to be included into a target to provide a rule +# to deploy a target on a target platform. +# +# The platform_deploy target should be defined in +# starboard/<port_path>/platform_deploy.gyp. This target should perform +# any per-executable logic that is specific to the platform. For example, +# copying per-executable metadata files to the output directory. +# +# To use this, create a gyp target with the following form: +# 'targets': [ +# { +# 'target_name': 'target_deploy', +# 'type': 'none', +# 'dependencies': [ +# 'target', +# ], +# 'variables': { +# 'executable_name': 'target', +# }, +# 'includes': [ +# '../build/deploy.gypi', +# ], +# }, +# + +{ + # Flag that will instruct gyp to create a special target in IDEs such as + # Visual Studio that can be used for launching a target. + 'variables' : { + 'ide_deploy_target': 1, + }, + + 'conditions': [ + ['OS=="starboard" and sb_has_deploy_step==1', { + 'dependencies': [ + '<(DEPTH)/<(starboard_path)/platform_deploy.gyp:platform_deploy', + ], + }], + ], +}
diff --git a/src/starboard/configuration.h b/src/starboard/configuration.h index 8dbf722..a106891 100644 --- a/src/starboard/configuration.h +++ b/src/starboard/configuration.h
@@ -57,6 +57,9 @@ // Determines at compile-time an inherent aspect of this platform. #define SB_IS(SB_FEATURE) (defined(SB_IS_##SB_FEATURE) && SB_IS_##SB_FEATURE) +// Determines at compile-time whether this platform has a quirk. +#define SB_HAS_QUIRK(SB_FEATURE) (defined(SB_HAS_QUIRK_##SB_FEATURE) && SB_HAS_QUIRK_##SB_FEATURE) + // Determines at compile-time if this platform implements a given Starboard API // version number (or above). #define SB_VERSION(SB_API) (SB_API_VERSION >= SB_API) @@ -384,6 +387,10 @@ #error "Your platform must define SB_HAS_BILINEAR_FILTERING_SUPPORT." #endif +#if !defined(SB_HAS_NV12_TEXTURE_SUPPORT) +#error "Your platform must define SB_HAS_NV12_TEXTURE_SUPPORT." +#endif + // --- Derived Configuration ------------------------------------------------- // Whether the current platform is little endian.
diff --git a/src/starboard/file.h b/src/starboard/file.h index 4cbd3e1..d1ecc11 100644 --- a/src/starboard/file.h +++ b/src/starboard/file.h
@@ -18,6 +18,7 @@ #define STARBOARD_FILE_H_ #include "starboard/export.h" +#include "starboard/log.h" #include "starboard/time.h" #include "starboard/types.h" @@ -181,4 +182,60 @@ } // extern "C" #endif +#ifdef __cplusplus +namespace starboard { + +// A class that opens an SbFile in its constructor and closes it in its +// destructor, so the file is open for the lifetime of the object. Member +// functions call the corresponding SbFile function. +class ScopedFile { + public: + ScopedFile(const char* path, + int flags, + bool* out_created, + SbFileError* out_error) + : file_(kSbFileInvalid) { + file_ = SbFileOpen(path, flags, out_created, out_error); + } + + ScopedFile(const char* path, int flags, bool* out_created) + : file_(kSbFileInvalid) { + file_ = SbFileOpen(path, flags, out_created, NULL); + } + + ScopedFile(const char* path, int flags) : file_(kSbFileInvalid) { + file_ = SbFileOpen(path, flags, NULL, NULL); + } + + ~ScopedFile() { SbFileClose(file_); } + + SbFile file() const { return file_; } + + bool IsValid() const { return SbFileIsValid(file_); } + + int64_t Seek(SbFileWhence whence, int64_t offset) const { + return SbFileSeek(file_, whence, offset); + } + + int Read(char* data, int size) const { return SbFileRead(file_, data, size); } + + int Write(const char* data, int size) const { + return SbFileWrite(file_, data, size); + } + + bool Truncate(int64_t length) const { return SbFileTruncate(file_, length); } + + bool Flush() const { return SbFileFlush(file_); } + + bool GetInfo(SbFileInfo* out_info) const { + return SbFileGetInfo(file_, out_info); + } + + private: + SbFile file_; +}; + +} // namespace starboard +#endif // ifdef __cplusplus + #endif // STARBOARD_FILE_H_
diff --git a/src/starboard/linux/shared/gyp_configuration.py b/src/starboard/linux/shared/gyp_configuration.py index a674378..cb6edb4 100644 --- a/src/starboard/linux/shared/gyp_configuration.py +++ b/src/starboard/linux/shared/gyp_configuration.py
@@ -15,6 +15,7 @@ import os +from config.base import Configs import config.starboard import gyp_utils @@ -22,7 +23,7 @@ class PlatformConfig(config.starboard.PlatformConfigStarboard): """Starboard Linux platform configuration.""" - def __init__(self, platform): + def __init__(self, platform, asan_enabled_by_default=True): super(PlatformConfig, self).__init__(platform) gyp_utils.CheckClangVersion() @@ -32,6 +33,8 @@ # correctly in the PATH. gyp_utils.FindAndInitGoma() + self.asan_default = 1 if asan_enabled_by_default else 0 + def GetBuildFormat(self): """Returns the desired build format.""" # The comma means that ninja and qtcreator_ninja will be chained and use the @@ -41,21 +44,17 @@ def GetVariables(self, configuration): variables = super(PlatformConfig, self).GetVariables(configuration) + use_tsan = int(os.environ.get('USE_TSAN', 0)) + # Enable ASAN by default for debug and devel builds only if USE_TSAN was not + # set to 1 in the environment. + use_asan_default = self.asan_default if not use_tsan and configuration in ( + Configs.DEBUG, Configs.DEVEL) else 0 variables.update({ 'clang': 1, - 'use_asan': int(os.environ.get('USE_ASAN', 0)), - 'use_tsan': int(os.environ.get('USE_TSAN', 0)), + 'use_asan': int(os.environ.get('USE_ASAN', use_asan_default)), + 'use_tsan': use_tsan, }) - if int(os.environ.get('USE_FUZZING', 0)): - # Build configuration for fuzz testing. - variables['use_asan'] = 1 - variables['use_tsan'] = 0 - # Disable code that tries to bind ports. The machines that run fuzz - # testing may not permit that, and we don't handle it gracefully. - variables['in_app_dial'] = 0 - variables['enable_remote_debugging'] = 0 - if variables.get('use_asan') == 1 and variables.get('use_tsan') == 1: raise RuntimeError('ASAN and TSAN are mutually exclusive') return variables
diff --git a/src/starboard/linux/x64directfb/configuration_public.h b/src/starboard/linux/x64directfb/configuration_public.h index 032fa17..c891232 100644 --- a/src/starboard/linux/x64directfb/configuration_public.h +++ b/src/starboard/linux/x64directfb/configuration_public.h
@@ -26,6 +26,11 @@ // API afterwards since we'll have DirectFB available. #include "starboard/linux/x64x11/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
diff --git a/src/starboard/linux/x64directfb/gyp_configuration.py b/src/starboard/linux/x64directfb/gyp_configuration.py index 34da360..0506121 100644 --- a/src/starboard/linux/x64directfb/gyp_configuration.py +++ b/src/starboard/linux/x64directfb/gyp_configuration.py
@@ -18,14 +18,15 @@ import sys # Import the shared Linux platform configuration. -sys.path.append(os.path.realpath(os.path.join(os.path.dirname(__file__), - os.pardir, 'shared'))) +sys.path.append(os.path.realpath(os.path.join( + os.path.dirname(__file__), os.pardir, 'shared'))) import gyp_configuration def CreatePlatformConfig(): try: - return gyp_configuration.PlatformConfig('linux-x64directfb') + return gyp_configuration.PlatformConfig('linux-x64directfb', + asan_enabled_by_default=False) except RuntimeError as e: logging.critical(e) return None
diff --git a/src/starboard/linux/x64directfb/starboard_platform.gyp b/src/starboard/linux/x64directfb/starboard_platform.gyp index e9ed5d5..279c8d9 100644 --- a/src/starboard/linux/x64directfb/starboard_platform.gyp +++ b/src/starboard/linux/x64directfb/starboard_platform.gyp
@@ -300,6 +300,8 @@ '<(DEPTH)/starboard/shared/stub/drm_system_internal.h', '<(DEPTH)/starboard/shared/stub/drm_update_session.cc', '<(DEPTH)/starboard/shared/stub/media_is_supported.cc', + '<(DEPTH)/starboard/shared/stub/system_clear_platform_error.cc', + '<(DEPTH)/starboard/shared/stub/system_raise_platform_error.cc', ], 'include_dirs': [ '/usr/include/directfb',
diff --git a/src/starboard/linux/x64x11/configuration_public.h b/src/starboard/linux/x64x11/configuration_public.h index 3bd1efb..f11107c 100644 --- a/src/starboard/linux/x64x11/configuration_public.h +++ b/src/starboard/linux/x64x11/configuration_public.h
@@ -97,6 +97,12 @@ // on the specifically pinned core. #define SB_HAS_CROSS_CORE_SCHEDULER 1 +// --- Graphics Configuration ------------------------------------------------ + +// Indicates whether or not the given platform supports rendering of NV12 +// textures. These textures typically originate from video decoders. +#define SB_HAS_NV12_TEXTURE_SUPPORT 1 + // Include the Linux configuration that's common between all Desktop Linuxes. #include "starboard/linux/shared/configuration_public.h"
diff --git a/src/starboard/linux/x64x11/starboard_platform.gyp b/src/starboard/linux/x64x11/starboard_platform.gyp index 867bc47..46ea9aa 100644 --- a/src/starboard/linux/x64x11/starboard_platform.gyp +++ b/src/starboard/linux/x64x11/starboard_platform.gyp
@@ -261,6 +261,8 @@ '<(DEPTH)/starboard/shared/stub/drm_system_internal.h', '<(DEPTH)/starboard/shared/stub/drm_update_session.cc', '<(DEPTH)/starboard/shared/stub/media_is_supported.cc', + '<(DEPTH)/starboard/shared/stub/system_clear_platform_error.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',
diff --git a/src/starboard/nplb/nplb.gyp b/src/starboard/nplb/nplb.gyp index da5bd7b..0835148 100644 --- a/src/starboard/nplb/nplb.gyp +++ b/src/starboard/nplb/nplb.gyp
@@ -234,6 +234,7 @@ 'variables': { 'executable_name': 'nplb', }, + 'includes': [ '../build/deploy.gypi' ], }, ], }
diff --git a/src/starboard/nplb/socket_accept_test.cc b/src/starboard/nplb/socket_accept_test.cc index b22a389..f9e9b9e 100644 --- a/src/starboard/nplb/socket_accept_test.cc +++ b/src/starboard/nplb/socket_accept_test.cc
@@ -24,11 +24,10 @@ namespace nplb { namespace { -const int kPort = 2048; - TEST(SbSocketAcceptTest, RainyDayNoConnection) { // Set up a socket to listen. - SbSocket server_socket = CreateListeningTcpIpv4Socket(kPort); + SbSocket server_socket = + CreateListeningTcpIpv4Socket(GetPortNumberForTests()); if (!SbSocketIsValid(server_socket)) { return; } @@ -60,7 +59,7 @@ TEST(SbSocketAcceptTest, RainyDayNotListening) { // Set up a socket, but don't Bind or Listen. - SbSocket server_socket = CreateBoundTcpIpv4Socket(kPort); + SbSocket server_socket = CreateBoundTcpIpv4Socket(GetPortNumberForTests()); if (!SbSocketIsValid(server_socket)) { return; }
diff --git a/src/starboard/nplb/socket_bind_test.cc b/src/starboard/nplb/socket_bind_test.cc index b74126d..81cb4e8 100644 --- a/src/starboard/nplb/socket_bind_test.cc +++ b/src/starboard/nplb/socket_bind_test.cc
@@ -28,7 +28,7 @@ const void* kNull = NULL; TEST(SbSocketBindTest, RainyDayNullSocket) { - SbSocketAddress address = GetIpv4Unspecified(2048); + SbSocketAddress address = GetIpv4Unspecified(GetPortNumberForTests()); EXPECT_EQ(kSbSocketErrorFailed, SbSocketBind(kSbSocketInvalid, &address)); } @@ -41,7 +41,7 @@ // Even though that failed, binding the same socket now with 0.0.0.0:2048 // should work. - SbSocketAddress address = GetIpv4Unspecified(2048); + SbSocketAddress address = GetIpv4Unspecified(GetPortNumberForTests()); EXPECT_EQ(kSbSocketOk, SbSocketBind(server_socket, &address)); EXPECT_TRUE(SbSocketDestroy(server_socket)); @@ -57,12 +57,12 @@ EXPECT_TRUE(SbSocketIsValid(server_socket)); // Binding with the wrong address type should fail. - SbSocketAddress address = GetIpv6Unspecified(2048); + SbSocketAddress address = GetIpv6Unspecified(GetPortNumberForTests()); EXPECT_EQ(kSbSocketErrorFailed, SbSocketBind(server_socket, &address)); // Even though that failed, binding the same socket now with 0.0.0.0:2048 // should work. - address = GetIpv4Unspecified(2048); + address = GetIpv4Unspecified(GetPortNumberForTests()); EXPECT_EQ(kSbSocketOk, SbSocketBind(server_socket, &address)); EXPECT_TRUE(SbSocketDestroy(server_socket));
diff --git a/src/starboard/nplb/socket_get_local_address_test.cc b/src/starboard/nplb/socket_get_local_address_test.cc index 5f29747..112f9a4 100644 --- a/src/starboard/nplb/socket_get_local_address_test.cc +++ b/src/starboard/nplb/socket_get_local_address_test.cc
@@ -82,8 +82,7 @@ } TEST(SbSocketGetLocalAddressTest, SunnyDayConnected) { - const int kPort = 2048; - + const int kPort = GetPortNumberForTests(); ConnectedTrio trio = CreateAndConnect(kPort, kSocketTimeout); if (!SbSocketIsValid(trio.server_socket)) { return;
diff --git a/src/starboard/nplb/socket_helpers.cc b/src/starboard/nplb/socket_helpers.cc index 922195b..6f9b35a 100644 --- a/src/starboard/nplb/socket_helpers.cc +++ b/src/starboard/nplb/socket_helpers.cc
@@ -14,6 +14,7 @@ #include "starboard/nplb/socket_helpers.h" +#include "starboard/once.h" #include "starboard/socket.h" #include "starboard/socket_waiter.h" #include "starboard/thread.h" @@ -22,6 +23,36 @@ namespace starboard { namespace nplb { +namespace { + +int port_number_for_tests = 0; +SbOnceControl valid_port_once_control = SB_ONCE_INITIALIZER; + +void InitializePortNumberForTests() { + // Create a listening socket. Let the system choose a port for us. + SbSocket socket = CreateListeningTcpIpv4Socket(0); + SB_DCHECK(socket != kSbSocketInvalid); + + // Query which port this socket was bound to and save it to valid_port_number. + SbSocketAddress socket_address = {0}; + bool result = SbSocketGetLocalAddress(socket, &socket_address); + SB_DCHECK(result); + port_number_for_tests = socket_address.port; + + // Clean up the socket. + result = SbSocketDestroy(socket); + SB_DCHECK(result); +} +} // namespace + +int GetPortNumberForTests() { +#if defined(SB_SOCKET_OVERRIDE_PORT_FOR_TESTS) + return SB_SOCKET_OVERRIDE_PORT_FOR_TESTS; +#else + SbOnce(&valid_port_once_control, &InitializePortNumberForTests); + return port_number_for_tests; +#endif +} bool IsUnspecified(const SbSocketAddress* address) { // Look at each piece of memory and make sure too many of them aren't zero.
diff --git a/src/starboard/nplb/socket_helpers.h b/src/starboard/nplb/socket_helpers.h index 5a59489..5b4e5d7 100644 --- a/src/starboard/nplb/socket_helpers.h +++ b/src/starboard/nplb/socket_helpers.h
@@ -43,6 +43,10 @@ // address types. bool IsLocalhost(const SbSocketAddress* address); +// Returns a valid port number that can be bound to for use in nplb tests. +// This will always return the same port number. +int GetPortNumberForTests(); + // Returns an IPv4 localhost address with the given port. SbSocketAddress GetIpv4Localhost(int port);
diff --git a/src/starboard/nplb/socket_is_connected_and_idle_test.cc b/src/starboard/nplb/socket_is_connected_and_idle_test.cc index 020701a..ffe83f5 100644 --- a/src/starboard/nplb/socket_is_connected_and_idle_test.cc +++ b/src/starboard/nplb/socket_is_connected_and_idle_test.cc
@@ -22,14 +22,13 @@ namespace nplb { namespace { -const int kPort = 2048; - TEST(SbSocketIsConnectedAndIdleTest, RainyDayInvalidSocket) { EXPECT_FALSE(SbSocketIsConnectedAndIdle(kSbSocketInvalid)); } TEST(SbSocketIsConnectedAndIdleTest, SunnyDay) { - ConnectedTrio trio = CreateAndConnect(kPort, kSocketTimeout); + ConnectedTrio trio = + CreateAndConnect(GetPortNumberForTests(), kSocketTimeout); if (!SbSocketIsValid(trio.server_socket)) { return; } @@ -68,7 +67,8 @@ } TEST(SbSocketIsConnectedAndIdleTest, SunnyDayListeningNotConnected) { - SbSocket server_socket = CreateListeningTcpIpv4Socket(kPort); + SbSocket server_socket = + CreateListeningTcpIpv4Socket(GetPortNumberForTests()); if (!SbSocketIsValid(server_socket)) { return; }
diff --git a/src/starboard/nplb/socket_is_connected_test.cc b/src/starboard/nplb/socket_is_connected_test.cc index 2c65d0d..e69fc4d 100644 --- a/src/starboard/nplb/socket_is_connected_test.cc +++ b/src/starboard/nplb/socket_is_connected_test.cc
@@ -21,14 +21,13 @@ namespace nplb { namespace { -const int kPort = 2048; - TEST(SbSocketIsConnectedTest, RainyDayInvalidSocket) { EXPECT_FALSE(SbSocketIsConnected(kSbSocketInvalid)); } TEST(SbSocketIsConnectedTest, SunnyDay) { - ConnectedTrio trio = CreateAndConnect(kPort, kSocketTimeout); + ConnectedTrio trio = + CreateAndConnect(GetPortNumberForTests(), kSocketTimeout); if (!SbSocketIsValid(trio.server_socket)) { return; } @@ -61,7 +60,8 @@ } TEST(SbSocketIsConnectedTest, SunnyDayListeningNotConnected) { - SbSocket server_socket = CreateListeningTcpIpv4Socket(kPort); + SbSocket server_socket = + CreateListeningTcpIpv4Socket(GetPortNumberForTests()); if (!SbSocketIsValid(server_socket)) { return; }
diff --git a/src/starboard/nplb/socket_receive_from_test.cc b/src/starboard/nplb/socket_receive_from_test.cc index 34f9215..5cd8c43 100644 --- a/src/starboard/nplb/socket_receive_from_test.cc +++ b/src/starboard/nplb/socket_receive_from_test.cc
@@ -60,11 +60,11 @@ } TEST(SbSocketReceiveFromTest, SunnyDay) { - const int kPort = 2048; const int kBufSize = 256 * 1024; const int kSockBufSize = kBufSize / 8; - ConnectedTrio trio = CreateAndConnect(kPort, kSocketTimeout); + ConnectedTrio trio = + CreateAndConnect(GetPortNumberForTests(), kSocketTimeout); if (!SbSocketIsValid(trio.server_socket)) { return; }
diff --git a/src/starboard/nplb/socket_waiter_wait_test.cc b/src/starboard/nplb/socket_waiter_wait_test.cc index fd1962e..8b67583 100644 --- a/src/starboard/nplb/socket_waiter_wait_test.cc +++ b/src/starboard/nplb/socket_waiter_wait_test.cc
@@ -56,13 +56,13 @@ } TEST(SbSocketWaiterWaitTest, SunnyDay) { - const int kPort = 2048; const int kBufSize = 1024; SbSocketWaiter waiter = SbSocketWaiterCreate(); EXPECT_TRUE(SbSocketWaiterIsValid(waiter)); - ConnectedTrio trio = CreateAndConnect(kPort, kSocketTimeout); + ConnectedTrio trio = + CreateAndConnect(GetPortNumberForTests(), kSocketTimeout); if (!SbSocketIsValid(trio.server_socket)) { ADD_FAILURE(); return; @@ -148,7 +148,6 @@ const char kAData[] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; const char kBData[] = "bb"; -const int kPort = 2048; void* AlreadyReadyEntryPoint(void* param) { AlreadyReadyContext* context = reinterpret_cast<AlreadyReadyContext*>(param); @@ -204,7 +203,7 @@ context.waiter = SbSocketWaiterCreate(); ASSERT_TRUE(SbSocketWaiterIsValid(context.waiter)); - context.trio = CreateAndConnect(kPort, kSocketTimeout); + context.trio = CreateAndConnect(GetPortNumberForTests(), kSocketTimeout); ASSERT_TRUE(SbSocketIsValid(context.trio.server_socket)); EXPECT_TRUE(SbSocketWaiterAdd(context.waiter, context.trio.client_socket,
diff --git a/src/starboard/nplb/socket_waiter_wait_timed_test.cc b/src/starboard/nplb/socket_waiter_wait_timed_test.cc index 57946ad..0166743 100644 --- a/src/starboard/nplb/socket_waiter_wait_timed_test.cc +++ b/src/starboard/nplb/socket_waiter_wait_timed_test.cc
@@ -47,13 +47,13 @@ } TEST(SbSocketWaiterWaitTimedTest, SunnyDay) { - const int kPort = 2048; const int kBufSize = 1024; SbSocketWaiter waiter = SbSocketWaiterCreate(); EXPECT_TRUE(SbSocketWaiterIsValid(waiter)); - ConnectedTrio trio = CreateAndConnect(kPort, kSocketTimeout); + ConnectedTrio trio = + CreateAndConnect(GetPortNumberForTests(), kSocketTimeout); if (!SbSocketIsValid(trio.server_socket)) { ADD_FAILURE(); return;
diff --git a/src/starboard/nplb/system_get_property_test.cc b/src/starboard/nplb/system_get_property_test.cc index 4ad7b86..82f35d5 100644 --- a/src/starboard/nplb/system_get_property_test.cc +++ b/src/starboard/nplb/system_get_property_test.cc
@@ -51,8 +51,8 @@ BasicTest(kSbSystemPropertyChipsetModelNumber, false, true, __LINE__); BasicTest(kSbSystemPropertyFirmwareVersion, false, true, __LINE__); BasicTest(kSbSystemPropertyFriendlyName, true, true, __LINE__); - BasicTest(kSbSystemPropertyManufacturerName, true, true, __LINE__); - BasicTest(kSbSystemPropertyModelName, true, true, __LINE__); + BasicTest(kSbSystemPropertyManufacturerName, false, true, __LINE__); + BasicTest(kSbSystemPropertyModelName, false, true, __LINE__); BasicTest(kSbSystemPropertyNetworkOperatorName, false, true, __LINE__); BasicTest(kSbSystemPropertyPlatformName, true, true, __LINE__); BasicTest(kSbSystemPropertyPlatformUuid, true, true, __LINE__);
diff --git a/src/starboard/raspi/1/starboard_platform.gyp b/src/starboard/raspi/1/starboard_platform.gyp index e1d104b..1b80d83 100644 --- a/src/starboard/raspi/1/starboard_platform.gyp +++ b/src/starboard/raspi/1/starboard_platform.gyp
@@ -30,8 +30,8 @@ '<(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_get_property.cc', '<(DEPTH)/starboard/linux/shared/system_has_capability.cc', + '<(DEPTH)/starboard/raspi/1/system_get_property.cc', '<(DEPTH)/starboard/raspi/shared/application_dispmanx.cc', '<(DEPTH)/starboard/raspi/shared/main.cc', '<(DEPTH)/starboard/raspi/shared/window_create.cc', @@ -268,6 +268,8 @@ '<(DEPTH)/starboard/shared/stub/drm_system_internal.h', '<(DEPTH)/starboard/shared/stub/drm_update_session.cc', '<(DEPTH)/starboard/shared/stub/media_is_supported.cc', + '<(DEPTH)/starboard/shared/stub/system_clear_platform_error.cc', + '<(DEPTH)/starboard/shared/stub/system_raise_platform_error.cc', ], 'defines': [ # This must be defined when building Starboard, and must not when
diff --git a/src/starboard/raspi/1/system_get_property.cc b/src/starboard/raspi/1/system_get_property.cc new file mode 100644 index 0000000..9a849da --- /dev/null +++ b/src/starboard/raspi/1/system_get_property.cc
@@ -0,0 +1,68 @@ +// 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/system.h" + +#include "starboard/log.h" +#include "starboard/string.h" + +namespace { + +const char* kFriendlyName = "My Linux"; +const char* kPlatformName = "Linux armv7l"; + +bool CopyStringAndTestIfSuccess(char* out_value, + int value_length, + const char* from_value) { + if (SbStringGetLength(from_value) + 1 > value_length) + return false; + SbStringCopy(out_value, from_value, value_length); + return true; +} + +} // namespace + +bool SbSystemGetProperty(SbSystemPropertyId property_id, + char* out_value, + int value_length) { + if (!out_value || !value_length) { + return false; + } + + switch (property_id) { + case kSbSystemPropertyChipsetModelNumber: + case kSbSystemPropertyFirmwareVersion: + case kSbSystemPropertyManufacturerName: + case kSbSystemPropertyModelName: + case kSbSystemPropertyNetworkOperatorName: + return false; + + case kSbSystemPropertyFriendlyName: + return CopyStringAndTestIfSuccess(out_value, value_length, kFriendlyName); + + case kSbSystemPropertyPlatformName: + return CopyStringAndTestIfSuccess(out_value, value_length, kPlatformName); + + case kSbSystemPropertyPlatformUuid: + SB_NOTIMPLEMENTED(); + return CopyStringAndTestIfSuccess(out_value, value_length, "N/A"); + + default: + SB_DLOG(WARNING) << __FUNCTION__ + << ": Unrecognized property: " << property_id; + break; + } + + return false; +}
diff --git a/src/starboard/raspi/shared/configuration_public.h b/src/starboard/raspi/shared/configuration_public.h index b625805..de26224 100644 --- a/src/starboard/raspi/shared/configuration_public.h +++ b/src/starboard/raspi/shared/configuration_public.h
@@ -223,6 +223,10 @@ // working properly. #define SB_HAS_BILINEAR_FILTERING_SUPPORT 1 +// Indicates whether or not the given platform supports rendering of NV12 +// textures. These textures typically originate from video decoders. +#define SB_HAS_NV12_TEXTURE_SUPPORT 1 + // --- Media Configuration --------------------------------------------------- // Specifies whether this platform has support for direct access to a decoder
diff --git a/src/starboard/shared/starboard/localized_strings.cc b/src/starboard/shared/starboard/localized_strings.cc new file mode 100644 index 0000000..2639c53 --- /dev/null +++ b/src/starboard/shared/starboard/localized_strings.cc
@@ -0,0 +1,153 @@ +// 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/localized_strings.h" + +#include "starboard/file.h" +#include "starboard/log.h" +#include "starboard/system.h" + +namespace starboard { +namespace shared { +namespace starboard { + +namespace { + +std::string GetFilenameForLanguage(const std::string& language) { + const int kBufferSize = 256; + char buffer[kBufferSize]; + bool got_path = + SbSystemGetPath(kSbSystemPathContentDirectory, buffer, kBufferSize); + if (!got_path) { + SB_DLOG(ERROR) << "Cannot get content path for i18n files."; + return std::string(); + } + + return std::string(buffer).append("/i18n/").append(language).append(".csv"); +} + +bool ReadFile(const std::string& filename, std::string* out_result) { + SB_DCHECK(filename.length() > 0); + SB_DCHECK(out_result); + + ScopedFile file(filename.c_str(), kSbFileOpenOnly | kSbFileRead); + if (!file.IsValid()) { + SB_DLOG(WARNING) << "Cannot open i18n file: " << filename; + return false; + } + + SbFileInfo file_info = {0}; + bool got_info = file.GetInfo(&file_info); + if (!got_info) { + SB_DLOG(ERROR) << "Cannot get information for i18n file."; + return false; + } + SB_DCHECK(file_info.size > 0); + + const int kMaxBufferSize = 16 * 1024; + if (file_info.size > kMaxBufferSize) { + SB_DLOG(ERROR) << "i18n file exceeds maximum size: " << file_info.size + << " (" << kMaxBufferSize << ")"; + return false; + } + + char* buffer = new char[file_info.size]; + SB_DCHECK(buffer); + int bytes_to_read = file_info.size; + char* buffer_pos = buffer; + while (bytes_to_read > 0) { + int bytes_read = file.Read(buffer_pos, bytes_to_read); + if (bytes_read < 0) { + SB_DLOG(ERROR) << "Read from i18n file failed."; + delete[] buffer; + return false; + } + bytes_to_read -= bytes_read; + buffer_pos += bytes_read; + } + + *out_result = std::string(buffer, file_info.size); + delete[] buffer; + return true; +} + +} // namespace + +LocalizedStrings::LocalizedStrings(const std::string& language) { + bool did_load_strings = LoadStrings(language); + + if (!did_load_strings) { + // Failed to load strings - try generic version of the language. + size_t dash = language.find_first_of("-_"); + if (dash != std::string::npos) { + std::string generic_lang(language.c_str(), dash); + did_load_strings = LoadStrings(generic_lang); + } + } + + SB_DCHECK(did_load_strings); +} + +std::string LocalizedStrings::GetString(const std::string& id, + const std::string& fallback) const { + StringMap::const_iterator iter = strings_.find(id); + if (iter == strings_.end()) { + return fallback; + } + return iter->second; +} + +bool LocalizedStrings::LoadStrings(const std::string& language) { + const std::string filename = GetFilenameForLanguage(language); + std::string file_contents; + if (!ReadFile(filename, &file_contents)) { + SB_DLOG(ERROR) << "Error reading i18n file."; + return false; + } + SB_DCHECK(file_contents.length() > 0); + SB_DCHECK(file_contents.back() == '\n'); + + // Each line of the file corresponds to one message (key/value). + size_t pos = 0; + while (true) { + size_t next_pos = file_contents.find("\n", pos); + if (next_pos == std::string::npos) { + break; + } + bool got_string = + LoadSingleString(std::string(file_contents, pos, next_pos - pos)); + SB_DCHECK(got_string); + pos = next_pos + 1; + } + + return true; +} + +bool LocalizedStrings::LoadSingleString(const std::string& message) { + // A single message is a key/value pair with separator. + size_t separator_pos = message.find(';'); + if (separator_pos == std::string::npos) { + SB_DLOG(ERROR) << "No separator found in: " << message; + return false; + } + + const std::string key(message, 0, separator_pos); + const std::string value(message, separator_pos + 1); + strings_[key] = value; + return true; +} + +} // namespace starboard +} // namespace shared +} // namespace starboard
diff --git a/src/starboard/shared/starboard/localized_strings.h b/src/starboard/shared/starboard/localized_strings.h new file mode 100644 index 0000000..fee9487 --- /dev/null +++ b/src/starboard/shared/starboard/localized_strings.h
@@ -0,0 +1,61 @@ +// 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 simple localized string table implementation. + +#ifndef STARBOARD_SHARED_STARBOARD_LOCALIZED_STRINGS_H_ +#define STARBOARD_SHARED_STARBOARD_LOCALIZED_STRINGS_H_ + +#include <map> +#include <string> + +#include "starboard/file.h" + +namespace starboard { +namespace shared { +namespace starboard { + +// Stores a map of internationalized strings for a particular language. +// Initialized from a language-specific file in a simple, CSV-style format. +class LocalizedStrings { + public: + explicit LocalizedStrings(const std::string& language); + + // Gets a localized string. + std::string GetString(const std::string& id, + const std::string& fallback) const; + + private: + typedef std::map<std::string, std::string> StringMap; + + // Loads the strings for a particular language. + // Returns true if successful, false otherwise. + bool LoadStrings(const std::string& language); + + // Loads the strings from a specified file. + // Returns true if successful, false otherwise. + bool LoadStrings(SbFile file); + + // Loads a single string. + // Returns true if successful, false otherwise. + bool LoadSingleString(const std::string& message); + + StringMap strings_; +}; + +} // namespace starboard +} // namespace shared +} // namespace starboard + +#endif // STARBOARD_SHARED_STARBOARD_LOCALIZED_STRINGS_H_
diff --git a/src/starboard/shared/starboard/player/audio_renderer_internal.h b/src/starboard/shared/starboard/player/audio_renderer_internal.h index d820049..cbc68c8 100644 --- a/src/starboard/shared/starboard/player/audio_renderer_internal.h +++ b/src/starboard/shared/starboard/player/audio_renderer_internal.h
@@ -21,7 +21,6 @@ #include "starboard/log.h" #include "starboard/media.h" #include "starboard/mutex.h" -#include "starboard/shared/ffmpeg/ffmpeg_audio_decoder.h" #include "starboard/shared/internal_only.h" #include "starboard/shared/starboard/player/audio_decoder_internal.h" #include "starboard/shared/starboard/player/input_buffer_internal.h"
diff --git a/src/starboard/shared/stub/system_clear_platform_error.cc b/src/starboard/shared/stub/system_clear_platform_error.cc new file mode 100644 index 0000000..2f13287 --- /dev/null +++ b/src/starboard/shared/stub/system_clear_platform_error.cc
@@ -0,0 +1,19 @@ +// 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/system.h" + +void SbSystemClearPlatformError(SbSystemPlatformError handle) { + SB_UNREFERENCED_PARAMETER(handle); +}
diff --git a/src/starboard/shared/stub/system_raise_platform_error.cc b/src/starboard/shared/stub/system_raise_platform_error.cc new file mode 100644 index 0000000..4a80cb1 --- /dev/null +++ b/src/starboard/shared/stub/system_raise_platform_error.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. + +#include "starboard/system.h" + +#include "starboard/log.h" + +SbSystemPlatformError SbSystemRaisePlatformError( + SbSystemPlatformErrorType type, + SbSystemPlatformErrorCallback callback, + void* user_data) { + SB_UNREFERENCED_PARAMETER(callback); + SB_UNREFERENCED_PARAMETER(user_data); + std::string message; + switch (type) { + case kSbSystemPlatformErrorTypeConnectionError: + message = "Connection error."; + break; + case kSbSystemPlatformErrorTypeUserSignedOut: + message = "User is not signed in."; + break; + case kSbSystemPlatformErrorTypeUserAgeRestricted: + message = "User is age restricted."; + break; + default: + message = "<unknown>"; + break; + } + SB_DLOG(INFO) << "SbSystemRaisePlatformError: " << message; + return false; +}
diff --git a/src/starboard/stub/configuration_public.h b/src/starboard/stub/configuration_public.h index 4726791..744c7d5 100644 --- a/src/starboard/stub/configuration_public.h +++ b/src/starboard/stub/configuration_public.h
@@ -293,6 +293,10 @@ // working properly. #define SB_HAS_BILINEAR_FILTERING_SUPPORT 1 +// Indicates whether or not the given platform supports rendering of NV12 +// textures. These textures typically originate from video decoders. +#define SB_HAS_NV12_TEXTURE_SUPPORT 0 + // --- Media Configuration --------------------------------------------------- // Specifies whether this platform has support for direct access to a decoder
diff --git a/src/starboard/stub/gyp_configuration.gypi b/src/starboard/stub/gyp_configuration.gypi index c314126..24cabf4 100644 --- a/src/starboard/stub/gyp_configuration.gypi +++ b/src/starboard/stub/gyp_configuration.gypi
@@ -13,16 +13,16 @@ # limitations under the License. { 'variables': { - 'target_arch%': 'x64', + 'target_arch': 'x64', 'target_os': 'linux', 'enable_webdriver': '1', # Use a stub rasterizer and graphical setup. - 'rasterizer_type%': 'stub', + 'rasterizer_type': 'stub', # No GL drivers available. - 'gl_type%': 'none', + 'gl_type': 'none', # This should have a default value in cobalt/base.gypi. See the comment # there for acceptable values for this variable.
diff --git a/src/starboard/stub/starboard_platform.gyp b/src/starboard/stub/starboard_platform.gyp index 59fb9e4..1279317 100644 --- a/src/starboard/stub/starboard_platform.gyp +++ b/src/starboard/stub/starboard_platform.gyp
@@ -170,6 +170,7 @@ '<(DEPTH)/starboard/shared/stub/system_binary_search.cc', '<(DEPTH)/starboard/shared/stub/system_break_into_debugger.cc', '<(DEPTH)/starboard/shared/stub/system_clear_last_error.cc', + '<(DEPTH)/starboard/shared/stub/system_clear_platform_error.cc', '<(DEPTH)/starboard/shared/stub/system_get_connection_type.cc', '<(DEPTH)/starboard/shared/stub/system_get_device_type.cc', '<(DEPTH)/starboard/shared/stub/system_get_error_string.cc', @@ -184,6 +185,7 @@ '<(DEPTH)/starboard/shared/stub/system_get_total_memory.cc', '<(DEPTH)/starboard/shared/stub/system_has_capability.cc', '<(DEPTH)/starboard/shared/stub/system_is_debugger_attached.cc', + '<(DEPTH)/starboard/shared/stub/system_raise_platform_error.cc', '<(DEPTH)/starboard/shared/stub/system_request_stop.cc', '<(DEPTH)/starboard/shared/stub/system_sort.cc', '<(DEPTH)/starboard/shared/stub/system_symbolize.cc',
diff --git a/src/starboard/system.h b/src/starboard/system.h index c1037c7..616d421 100644 --- a/src/starboard/system.h +++ b/src/starboard/system.h
@@ -135,6 +135,85 @@ kSbSystemCapabilityReversedEnterAndBack, } SbSystemCapabilityId; +// Enumeration of possible values for the |type| parameter passed to the +// |SbSystemRaisePlatformError| function. +typedef enum SbSystemPlatformErrorType { + // Cobalt received a network connection error, or a network disconnection + // event. + kSbSystemPlatformErrorTypeConnectionError, + + // The current user is not signed in (e.g. to PSN network). + kSbSystemPlatformErrorTypeUserSignedOut, + + // The current user does not meet the age requirements to use the app. + kSbSystemPlatformErrorTypeUserAgeRestricted +} SbSystemPlatformErrorType; + +// Possible responses for |SbSystemPlatformErrorCallback|. +typedef enum SbSystemPlatformErrorResponse { + kSbSystemPlatformErrorResponsePositive, + kSbSystemPlatformErrorResponseNegative, + kSbSystemPlatformErrorResponseCancel +} SbSystemPlatformErrorResponse; + +// Type of callback function that may be called in response to an error +// notification from |SbSystemRaisePlatformError|. |response| is a code to +// indicate the user's response, e.g. if the platform raised a dialog to notify +// the user of the error. |user_data| is the opaque pointer that was passed to +// the call to |SbSystemRaisePlatformError|. +typedef void (*SbSystemPlatformErrorCallback)( + SbSystemPlatformErrorResponse response, + void* user_data); + +// Private structure used to represent a raised platform error. +typedef struct SbSystemPlatformErrorPrivate SbSystemPlatformErrorPrivate; + +// Opaque handle returned by |SbSystemRaisePlatformError| that can be passed +// to |SbSystemClearPlatformError|. +typedef SbSystemPlatformErrorPrivate* SbSystemPlatformError; + +// Well-defined value for an invalid |SbSystemPlatformError|. +#define kSbSystemPlatformErrorInvalid (SbSystemPlatformError) NULL + +// Checks whether a |SbSystemPlatformError| is valid. +static SB_C_INLINE bool SbSystemPlatformErrorIsValid( + SbSystemPlatformError handle) { + return handle != kSbSystemPlatformErrorInvalid; +} + +// Called by Cobalt to notify the platform that an error has occurred in the +// application that may have to be handled by the platform. It is expected the +// platform will notify the user of the error, and provide interaction if +// required, for example by showing a dialog. +// +// |type| is one of the enumerated types above to define the error; |callback| +// is a function that may be called by the platform to let the caller know the +// user has reacted to the error; |user_data| is an opaque pointer that the +// platform should pass as an argument to the callback, if called. +// Returns a handle that may be used in a subsequent call to +// |SbClearPlatformError|, for example to programatically dismiss a dialog that +// may have been raised in response to the error. The lifetime of +// the object referenced by the handle is until the user reacts to the error +// or the error is dismissed by a call to |SbSystemClearPlatformError|, +// whichever happens first. If the platform cannot respond to the error, then +// this function should return |kSbSystemPlatformErrorInvalid|. +// +// This function may be called from any thread; it is the responsibility of the +// platform to decide how to handle an error received while a previous error is +// still pending - if only one error can be handled at a time, then the +// platform may queue the second error or ignore it by returning +// |kSbSystemPlatformErrorInvalid|. +SB_EXPORT SbSystemPlatformError +SbSystemRaisePlatformError(SbSystemPlatformErrorType type, + SbSystemPlatformErrorCallback callback, + void* user_data); + +// Clears a platform error that was previously raised by a call to +// |SbSystemRaisePlatformError|, specified by the handle that was returned by +// that function. The platform may use this, for example, to close a dialog +// that was opened in response to the error. +SB_EXPORT void SbSystemClearPlatformError(SbSystemPlatformError handle); + // Pointer to a function to compare two items, returning less than zero, zero, // or greater than zero depending on whether |a| is less than |b|, equal to |b|, // or greater than |b|, respectively (standard *cmp semantics).
diff --git a/src/starboard/user.h b/src/starboard/user.h index aa7afc0..9dd1e1a 100644 --- a/src/starboard/user.h +++ b/src/starboard/user.h
@@ -22,6 +22,7 @@ #define STARBOARD_USER_H_ #include "starboard/export.h" +#include "starboard/time.h" #include "starboard/types.h" #ifdef __cplusplus @@ -51,6 +52,27 @@ kSbUserPropertyUserId, } SbUserPropertyId; +#if SB_HAS(USER_APPLICATION_LINKING_SUPPORT) +// Information about an application-specific authorization token. +typedef struct SbUserApplicationTokenResults { + // The size of the buffer pointed to by |token_buffer|. Call + // SbUserMaxAuthenticationTokenSizeInBytes() to get an appropriate size. + // |token_buffer_size| must be set to a value greater than zero. + size_t token_buffer_size; + + // Pointer to a buffer into which the token will be copied. + // |token_buffer| must not be NULL. + char* token_buffer; + + // If true, |expiry| will be set. If false, the token never expires. + bool has_expiry; + + // The absolute time that this token expires. It is valid to use the value of + // |expiry| only if |has_expiry| is true. + SbTime expiry; +} SbUserApplicationTokenResults; +#endif + // Well-defined value for an invalid user. #define kSbUserInvalid (SbUser) NULL @@ -95,6 +117,54 @@ // user changed event being dispatched. SB_EXPORT void SbUserStartSignIn(); +#if SB_HAS(USER_APPLICATION_LINKING_SUPPORT) +// Initiates a process to link |user| with a per-application authentication +// token. On success, |out_token| is populated with the authentication token +// and |out_expiry| is set to the number of seconds until the token expires. An +// expiration of 0 indicates that the token never expires. +// This call will block until the linking process is complete, which may involve +// user input. +// After this call completes successfully, subsequent calls to +// SbUserRequestAuthenticationToken will return valid tokens. +// Returns false if |user| is invalid, |token_results| is NULL, +// |token_results.token_buffer| is NULL or if the token is larger than +// |token_results.token_buffer_size|. +// Returns true if process to link the token succeeded, and false if the process +// failed for any reason including user cancellation. +SB_EXPORT bool SbUserRequestApplicationLinking( + SbUser user, + SbUserApplicationTokenResults* token_results); + +// Remove the link between |user| and the per-application authentication token. +// This call will block until the linking process is complete, which may involve +// user input. +// After this call completes successfully, subsequent calls to +// SbUserRequestAuthenticationToken will fail. +// Returns false if |user| is invalid. +// Returns true if the process to unlink the token succeeded. Returns false if +// the process failed for any reason including user cancellation. +SB_EXPORT bool SbUserRequestApplicationUnlinking(SbUser user); + +// Requests a new per-application authentication token. On success, |out_token| +// is populated with the authentication token and |out_expiry| is set to the +// number of seconds until the token expires. An expiration of 0 indicates that +// the token never expires. +// This call will block until the token has been received. +// Returns false if |user| is invalid, |out_token| or |out_expiration| are NULL, +// or if the token is larger than |out_token_size|. +// Returns false if the user account is not linked with an application. In this +// case, SbUserRequestApplicationLinking should be called. +// Returns true if process to link the token succeeded, and false if the process +// failed for any reason including user cancellation. +SB_EXPORT bool SbUserRequestAuthenticationToken( + SbUser user, + SbUserApplicationTokenResults* token_results); + +// Gets the maximum size of an authentication token as returned by +// SbUserRequestApplicationLinking and SbUserRequestAuthenticationToken. +SB_EXPORT size_t SbUserMaxAuthenticationTokenSizeInBytes(); +#endif // SB_HAS(USER_APPLICATION_LINKING_SUPPORT) + #ifdef __cplusplus } // extern "C" #endif
diff --git a/src/third_party/libvpx/.mailmap b/src/third_party/libvpx/.mailmap new file mode 100644 index 0000000..4672e5c --- /dev/null +++ b/src/third_party/libvpx/.mailmap
@@ -0,0 +1,32 @@ +Adrian Grange <agrange@google.com> +Aâ„“ex Converse <aconverse@google.com> +Aâ„“ex Converse <aconverse@google.com> <alex.converse@gmail.com> +Alexis Ballier <aballier@gentoo.org> <alexis.ballier@gmail.com> +Alpha Lam <hclam@google.com> <hclam@chromium.org> +Deb Mukherjee <debargha@google.com> +Erik Niemeyer <erik.a.niemeyer@intel.com> <erik.a.niemeyer@gmail.com> +Guillaume Martres <gmartres@google.com> <smarter3@gmail.com> +Hangyu Kuang <hkuang@google.com> +Hui Su <huisu@google.com> +Jacky Chen <jackychen@google.com> +Jim Bankoski <jimbankoski@google.com> +Johann Koenig <johannkoenig@google.com> +Johann Koenig <johannkoenig@google.com> <johann.koenig@duck.com> +Johann Koenig <johannkoenig@google.com> <johann.koenig@gmail.com> +John Koleszar <jkoleszar@google.com> +Joshua Litt <joshualitt@google.com> <joshualitt@chromium.org> +Marco Paniconi <marpan@google.com> +Marco Paniconi <marpan@google.com> <marpan@chromium.org> +Pascal Massimino <pascal.massimino@gmail.com> +Paul Wilkins <paulwilkins@google.com> +Ralph Giles <giles@xiph.org> <giles@entropywave.com> +Ralph Giles <giles@xiph.org> <giles@mozilla.com> +Ronald S. Bultje <rsbultje@gmail.com> <rbultje@google.com> +Sami Pietilä <samipietila@google.com> +Tamar Levy <tamar.levy@intel.com> +Tamar Levy <tamar.levy@intel.com> <levytamar82@gmail.com> +Tero Rintaluoma <teror@google.com> <tero.rintaluoma@on2.com> +Timothy B. Terriberry <tterribe@xiph.org> Tim Terriberry <tterriberry@mozilla.com> +Tom Finegan <tomfinegan@google.com> +Tom Finegan <tomfinegan@google.com> <tomfinegan@chromium.org> +Yaowu Xu <yaowu@google.com> <yaowu@xuyaowu.com>
diff --git a/src/third_party/libvpx/AUTHORS b/src/third_party/libvpx/AUTHORS new file mode 100644 index 0000000..f89b677 --- /dev/null +++ b/src/third_party/libvpx/AUTHORS
@@ -0,0 +1,134 @@ +# This file is automatically generated from the git commit history +# by tools/gen_authors.sh. + +Aaron Watry <awatry@gmail.com> +Abo Talib Mahfoodh <ab.mahfoodh@gmail.com> +Adam Xu <adam@xuyaowu.com> +Adrian Grange <agrange@google.com> +Aâ„“ex Converse <aconverse@google.com> +Ahmad Sharif <asharif@google.com> +Alexander Voronov <avoronov@graphics.cs.msu.ru> +Alexis Ballier <aballier@gentoo.org> +Alok Ahuja <waveletcoeff@gmail.com> +Alpha Lam <hclam@google.com> +A.Mahfoodh <ab.mahfoodh@gmail.com> +Ami Fischman <fischman@chromium.org> +Andoni Morales Alastruey <ylatuya@gmail.com> +Andres Mejia <mcitadel@gmail.com> +Andrew Russell <anrussell@google.com> +Angie Chiang <angiebird@google.com> +Aron Rosenberg <arosenberg@logitech.com> +Attila Nagy <attilanagy@google.com> +Brion Vibber <bvibber@wikimedia.org> +changjun.yang <changjun.yang@intel.com> +Charles 'Buck' Krasic <ckrasic@google.com> +chm <chm@rock-chips.com> +Christian Duvivier <cduvivier@google.com> +Daniel Kang <ddkang@google.com> +Deb Mukherjee <debargha@google.com> +Dim Temp <dimtemp0@gmail.com> +Dmitry Kovalev <dkovalev@google.com> +Dragan Mrdjan <dmrdjan@mips.com> +Ed Baker <edward.baker@intel.com> +Ehsan Akhgari <ehsan.akhgari@gmail.com> +Erik Niemeyer <erik.a.niemeyer@intel.com> +Fabio Pedretti <fabio.ped@libero.it> +Frank Galligan <fgalligan@google.com> +Fredrik Söderquist <fs@opera.com> +Fritz Koenig <frkoenig@google.com> +Gaute Strokkenes <gaute.strokkenes@broadcom.com> +Geza Lore <gezalore@gmail.com> +Ghislain MARY <ghislainmary2@gmail.com> +Giuseppe Scrivano <gscrivano@gnu.org> +Gordana Cmiljanovic <gordana.cmiljanovic@imgtec.com> +Guillaume Martres <gmartres@google.com> +Guillermo Ballester Valor <gbvalor@gmail.com> +Hangyu Kuang <hkuang@google.com> +Hanno Böck <hanno@hboeck.de> +Henrik Lundin <hlundin@google.com> +Hui Su <huisu@google.com> +Ivan Maltz <ivanmaltz@google.com> +Jacek Caban <cjacek@gmail.com> +Jacky Chen <jackychen@google.com> +James Berry <jamesberry@google.com> +James Yu <james.yu@linaro.org> +James Zern <jzern@google.com> +Jan Gerber <j@mailb.org> +Jan Kratochvil <jan.kratochvil@redhat.com> +Janne Salonen <jsalonen@google.com> +Jeff Faust <jfaust@google.com> +Jeff Muizelaar <jmuizelaar@mozilla.com> +Jeff Petkau <jpet@chromium.org> +Jia Jia <jia.jia@linaro.org> +Jim Bankoski <jimbankoski@google.com> +Jingning Han <jingning@google.com> +Joey Parrish <joeyparrish@google.com> +Johann Koenig <johannkoenig@google.com> +John Koleszar <jkoleszar@google.com> +Johnny Klonaris <google@jawknee.com> +John Stark <jhnstrk@gmail.com> +Joshua Bleecher Snyder <josh@treelinelabs.com> +Joshua Litt <joshualitt@google.com> +Julia Robson <juliamrobson@gmail.com> +Justin Clift <justin@salasaga.org> +Justin Lebar <justin.lebar@gmail.com> +KO Myung-Hun <komh@chollian.net> +Lawrence Velázquez <larryv@macports.org> +Lou Quillio <louquillio@google.com> +Luca Barbato <lu_zero@gentoo.org> +Makoto Kato <makoto.kt@gmail.com> +Mans Rullgard <mans@mansr.com> +Marco Paniconi <marpan@google.com> +Mark Mentovai <mark@chromium.org> +Martin Ettl <ettl.martin78@googlemail.com> +Martin Storsjo <martin@martin.st> +Matthew Heaney <matthewjheaney@chromium.org> +Michael Kohler <michaelkohler@live.com> +Mike Frysinger <vapier@chromium.org> +Mike Hommey <mhommey@mozilla.com> +Mikhal Shemer <mikhal@google.com> +Minghai Shang <minghai@google.com> +Morton Jonuschat <yabawock@gmail.com> +Nico Weber <thakis@chromium.org> +Parag Salasakar <img.mips1@gmail.com> +Pascal Massimino <pascal.massimino@gmail.com> +Patrik Westin <patrik.westin@gmail.com> +Paul Wilkins <paulwilkins@google.com> +Pavol Rusnak <stick@gk2.sk> +PaweÅ‚ Hajdan <phajdan@google.com> +Pengchong Jin <pengchong@google.com> +Peter de Rivaz <peter.derivaz@gmail.com> +Philip Jägenstedt <philipj@opera.com> +Priit Laes <plaes@plaes.org> +Rafael Ávila de Espíndola <rafael.espindola@gmail.com> +Rafaël Carré <funman@videolan.org> +Ralph Giles <giles@xiph.org> +Rob Bradford <rob@linux.intel.com> +Ronald S. Bultje <rsbultje@gmail.com> +Rui Ueyama <ruiu@google.com> +Sami Pietilä <samipietila@google.com> +Scott Graham <scottmg@chromium.org> +Scott LaVarnway <slavarnway@google.com> +Sean McGovern <gseanmcg@gmail.com> +Sergey Ulanov <sergeyu@chromium.org> +Shimon Doodkin <helpmepro1@gmail.com> +Shunyao Li <shunyaoli@google.com> +Stefan Holmer <holmer@google.com> +Suman Sunkara <sunkaras@google.com> +Taekhyun Kim <takim@nvidia.com> +Takanori MATSUURA <t.matsuu@gmail.com> +Tamar Levy <tamar.levy@intel.com> +Tao Bai <michaelbai@chromium.org> +Tero Rintaluoma <teror@google.com> +Thijs Vermeir <thijsvermeir@gmail.com> +Tim Kopp <tkopp@google.com> +Timothy B. Terriberry <tterribe@xiph.org> +Tom Finegan <tomfinegan@google.com> +Vignesh Venkatasubramanian <vigneshv@google.com> +Yaowu Xu <yaowu@google.com> +Yongzhe Wang <yongzhe@google.com> +Yunqing Wang <yunqingwang@google.com> +Zoe Liu <zoeliu@google.com> +Google Inc. +The Mozilla Foundation +The Xiph.Org Foundation
diff --git a/src/third_party/libvpx/CHANGELOG b/src/third_party/libvpx/CHANGELOG new file mode 100644 index 0000000..7db420e --- /dev/null +++ b/src/third_party/libvpx/CHANGELOG
@@ -0,0 +1,628 @@ +Next Release + - Incompatible changes: + The VP9 encoder's default keyframe interval changed to 128 from 9999. + +2015-11-09 v1.5.0 "Javan Whistling Duck" + This release improves upon the VP9 encoder and speeds up the encoding and + decoding processes. + + - Upgrading: + This release is ABI incompatible with 1.4.0. It drops deprecated VP8 + controls and adds a variety of VP9 controls for testing. + + The vpxenc utility now prefers VP9 by default. + + - Enhancements: + Faster VP9 encoding and decoding + Smaller library size by combining functions used by VP8 and VP9 + + - Bug Fixes: + A variety of fuzzing issues + +2015-04-03 v1.4.0 "Indian Runner Duck" + This release includes significant improvements to the VP9 codec. + + - Upgrading: + This release is ABI incompatible with 1.3.0. It drops the compatibility + layer, requiring VPX_IMG_FMT_* instead of IMG_FMT_*, and adds several codec + controls for VP9. + + - Enhancements: + Faster VP9 encoding and decoding + Multithreaded VP9 decoding (tile and frame-based) + Multithreaded VP9 encoding - on by default + YUV 4:2:2 and 4:4:4 support in VP9 + 10 and 12bit support in VP9 + 64bit ARM support by replacing ARM assembly with intrinsics + + - Bug Fixes: + Fixes a VP9 bitstream issue in Profile 1. This only affected non-YUV 4:2:0 + files. + + - Known Issues: + Frame Parallel decoding fails for segmented and non-420 files. + +2013-11-15 v1.3.0 "Forest" + This release introduces the VP9 codec in a backward-compatible way. + All existing users of VP8 can continue to use the library without + modification. However, some VP8 options do not map to VP9 in the same manner. + + The VP9 encoder in this release is not feature complete. Users interested in + the encoder are advised to use the git master branch and discuss issues on + libvpx mailing lists. + + - Upgrading: + This release is ABI and API compatible with Duclair (v1.0.0). Users + of older releases should refer to the Upgrading notes in this document + for that release. + + - Enhancements: + Get rid of bashisms in the main build scripts + Added usage info on command line options + Add lossless compression mode + Dll build of libvpx + Add additional Mac OS X targets: 10.7, 10.8 and 10.9 (darwin11-13) + Add option to disable documentation + configure: add --enable-external-build support + make: support V=1 as short form of verbose=yes + configure: support mingw-w64 + configure: support hardfloat armv7 CHOSTS + configure: add support for android x86 + Add estimated completion time to vpxenc + Don't exit on decode errors in vpxenc + vpxenc: support scaling prior to encoding + vpxdec: support scaling output + vpxenc: improve progress indicators with --skip + msvs: Don't link to winmm.lib + Add a new script for producing vcxproj files + Produce Visual Studio 10 and 11 project files + Produce Windows Phone project files + msvs-build: use msbuild for vs >= 2005 + configure: default configure log to config.log + Add encoding option --static-thresh + + - Speed: + Miscellaneous speed optimizations for VP8 and VP9. + + - Quality: + In general, quality is consistent with the Eider release. + + - Bug Fixes: + This release represents approximately a year of engineering effort, + and contains multiple bug fixes. Please refer to git history for details. + + +2012-12-21 v1.2.0 + This release acts as a checkpoint for a large amount of internal refactoring + and testing. It also contains a number of small bugfixes, so all users are + encouraged to upgrade. + + - Upgrading: + This release is ABI and API compatible with Duclair (v1.0.0). Users + of older releases should refer to the Upgrading notes in this + document for that release. + + - Enhancements: + VP8 optimizations for MIPS dspr2 + vpxenc: add -quiet option + + - Speed: + Encoder and decoder speed is consistent with the Eider release. + + - Quality: + In general, quality is consistent with the Eider release. + + Minor tweaks to ARNR filtering + Minor improvements to real time encoding with multiple temporal layers + + - Bug Fixes: + Fixes multithreaded encoder race condition in loopfilter + Fixes multi-resolution threaded encoding + Fix potential encoder dead-lock after picture resize + + +2012-05-09 v1.1.0 "Eider" + This introduces a number of enhancements, mostly focused on real-time + encoding. In addition, it fixes a decoder bug (first introduced in + Duclair) so all users of that release are encouraged to upgrade. + + - Upgrading: + This release is ABI and API compatible with Duclair (v1.0.0). Users + of older releases should refer to the Upgrading notes in this + document for that release. + + This release introduces a new temporal denoiser, controlled by the + VP8E_SET_NOISE_SENSITIVITY control. The temporal denoiser does not + currently take a strength parameter, so the control is effectively + a boolean - zero (off) or non-zero (on). For compatibility with + existing applications, the values accepted are the same as those + for the spatial denoiser (0-6). The temporal denoiser is enabled + by default, and the older spatial denoiser may be restored by + configuring with --disable-temporal-denoising. The temporal denoiser + is more computationally intensive than the spatial one. + + This release removes support for a legacy, decode only API that was + supported, but deprecated, at the initial release of libvpx + (v0.9.0). This is not expected to have any impact. If you are + impacted, you can apply a reversion to commit 2bf8fb58 locally. + Please update to the latest libvpx API if you are affected. + + - Enhancements: + Adds a motion compensated temporal denoiser to the encoder, which + gives higher quality than the older spatial denoiser. (See above + for notes on upgrading). + + In addition, support for new compilers and platforms were added, + including: + improved support for XCode + Android x86 NDK build + OS/2 support + SunCC support + + Changing resolution with vpx_codec_enc_config_set() is now + supported. Previously, reinitializing the codec was required to + change the input resolution. + + The vpxenc application has initial support for producing multiple + encodes from the same input in one call. Resizing is not yet + supported, but varying other codec parameters is. Use -- to + delineate output streams. Options persist from one stream to the + next. + + Also, the vpxenc application will now use a keyframe interval of + 5 seconds by default. Use the --kf-max-dist option to override. + + - Speed: + Decoder performance improved 2.5% versus Duclair. Encoder speed is + consistent with Duclair for most material. Two pass encoding of + slideshow-like material will see significant improvements. + + Large realtime encoding speed gains at a small quality expense are + possible by configuring the on-the-fly bitpacking experiment with + --enable-onthefly-bitpacking. Realtime encoder can be up to 13% + faster (ARM) depending on the number of threads and bitrate + settings. This technique sees constant gain over the 5-16 speed + range. For VC style input the loss seen is up to 0.2dB. See commit + 52cf4dca for further details. + + - Quality: + On the whole, quality is consistent with the Duclair release. Some + tweaks: + + Reduced blockiness in easy sections by applying a penalty to + intra modes. + + Improved quality of static sections (like slideshows) with + two pass encoding. + + Improved keyframe sizing with multiple temporal layers + + - Bug Fixes: + Corrected alt-ref contribution to frame rate for visible updates + to the alt-ref buffer. This affected applications making manual + usage of the frame reference flags, or temporal layers. + + Additional constraints were added to disable multi-frame quality + enhancement (MFQE) in sections of the frame where there is motion. + (#392) + + Fixed corruption issues when vpx_codec_enc_config_set() was called + with spatial resampling enabled. + + Fixed a decoder error introduced in Duclair where the segmentation + map was not being reinitialized on keyframes (#378) + + +2012-01-27 v1.0.0 "Duclair" + Our fourth named release, focused on performance and features related to + real-time encoding. It also fixes a decoder crash bug introduced in + v0.9.7, so all users of that release are encouraged to upgrade. + + - Upgrading: + This release is ABI incompatible with prior releases of libvpx, so the + "major" version number has been bumped to 1. You must recompile your + applications against the latest version of the libvpx headers. The + API remains compatible, and this should not require code changes in most + applications. + + - Enhancements: + This release introduces several substantial new features to the encoder, + of particular interest to real time streaming applications. + + Temporal scalability allows the encoder to produce a stream that can + be decimated to different frame rates, with independent rate targetting + for each substream. + + Multiframe quality enhancement postprocessing can make visual quality + more consistent in the presence of frames that are substantially + different quality than the surrounding frames, as in the temporal + scalability case and in some forced keyframe scenarios. + + Multiple-resolution encoding support allows the encoding of the + same content at different resolutions faster than encoding them + separately. + + - Speed: + Optimization targets for this release included the decoder and the real- + time modes of the encoder. Decoder speed on x86 has improved 10.5% with + this release. Encoder improvements followed a curve where speeds 1-3 + improved 4.0%-1.5%, speeds 4-8 improved <1%, and speeds 9-16 improved + 1.5% to 10.5%, respectively. "Best" mode speed is consistent with the + Cayuga release. + + - Quality: + Encoder quality in the single stream case is consistent with the Cayuga + release. + + - Bug Fixes: + This release fixes an OOB read decoder crash bug present in v0.9.7 + related to the clamping of motion vectors in SPLITMV blocks. This + behavior could be triggered by corrupt input or by starting + decoding from a P-frame. + + +2011-08-15 v0.9.7-p1 "Cayuga" patch 1 + This is an incremental bugfix release against Cayuga. All users of that + release are strongly encouraged to upgrade. + + - Fix potential OOB reads (cdae03a) + + An unbounded out of bounds read was discovered when the + decoder was requested to perform error concealment (new in + Cayuga) given a frame with corrupt partition sizes. + + A bounded out of bounds read was discovered affecting all + versions of libvpx. Given an multipartition input frame that + is truncated between the mode/mv partition and the first + residiual paritition (in the block of partition offsets), up + to 3 extra bytes could have been read from the source buffer. + The code will not take any action regardless of the contents + of these undefined bytes, as the truncated buffer is detected + immediately following the read based on the calculated + starting position of the coefficient partition. + + - Fix potential error concealment crash when the very first frame + is missing or corrupt (a609be5) + + - Fix significant artifacts in error concealment (a4c2211, 99d870a) + + - Revert 1-pass CBR rate control changes (e961317) + Further testing showed this change produced undesirable visual + artifacts, rolling back for now. + + +2011-08-02 v0.9.7 "Cayuga" + Our third named release, focused on a faster, higher quality, encoder. + + - Upgrading: + This release is backwards compatible with Aylesbury (v0.9.5) and + Bali (v0.9.6). Users of older releases should refer to the Upgrading + notes in this document for that release. + + - Enhancements: + Stereo 3D format support for vpxenc + Runtime detection of available processor cores. + Allow specifying --end-usage by enum name + vpxdec: test for frame corruption + vpxenc: add quantizer histogram display + vpxenc: add rate histogram display + Set VPX_FRAME_IS_DROPPABLE + update configure for ios sdk 4.3 + Avoid text relocations in ARM vp8 decoder + Generate a vpx.pc file for pkg-config. + New ways of passing encoded data between encoder and decoder. + + - Speed: + This release includes across-the-board speed improvements to the + encoder. On x86, these measure at approximately 11.5% in Best mode, + 21.5% in Good mode (speed 0), and 22.5% in Realtime mode (speed 6). + On ARM Cortex A9 with Neon extensions, real-time encoding of video + telephony content is 35% faster than Bali on single core and 48% + faster on multi-core. On the NVidia Tegra2 platform, real time + encoding is 40% faster than Bali. + + Decoder speed was not a priority for this release, but improved + approximately 8.4% on x86. + + Reduce motion vector search on alt-ref frame. + Encoder loopfilter running in its own thread + Reworked loopfilter to precalculate more parameters + SSE2/SSSE3 optimizations for build_predictors_mbuv{,_s}(). + Make hor UV predict ~2x faster (73 vs 132 cycles) using SSSE3. + Removed redundant checks + Reduced structure sizes + utilize preload in ARMv6 MC/LPF/Copy routines + ARM optimized quantization, dfct, variance, subtract + Increase chrow row alignment to 16 bytes. + disable trellis optimization for first pass + Write SSSE3 sub-pixel filter function + Improve SSE2 half-pixel filter funtions + Add vp8_sub_pixel_variance16x8_ssse3 function + Reduce unnecessary distortion computation + Use diamond search to replace full search + Preload reference area in sub-pixel motion search (real-time mode) + + - Quality: + This release focused primarily on one-pass use cases, including + video conferencing. Low latency data rate control was significantly + improved, improving streamability over bandwidth constrained links. + Added support for error concealment, allowing frames to maintain + visual quality in the presence of substantial packet loss. + + Add rc_max_intra_bitrate_pct control + Limit size of initial keyframe in one-pass. + Improve framerate adaptation + Improved 1-pass CBR rate control + Improved KF insertion after fades to still. + Improved key frame detection. + Improved activity masking (lower PSNR impact for same SSIM boost) + Improved interaction between GF and ARFs + Adding error-concealment to the decoder. + Adding support for independent partitions + Adjusted rate-distortion constants + + + - Bug Fixes: + Removed firstpass motion map + Fix parallel make install + Fix multithreaded encoding for 1 MB wide frame + Fixed iwalsh_neon build problems with RVDS4.1 + Fix semaphore emulation, spin-wait intrinsics on Windows + Fix build with xcode4 and simplify GLOBAL. + Mark ARM asm objects as allowing a non-executable stack. + Fix vpxenc encoding incorrect webm file header on big endian + + +2011-03-07 v0.9.6 "Bali" + Our second named release, focused on a faster, higher quality, encoder. + + - Upgrading: + This release is backwards compatible with Aylesbury (v0.9.5). Users + of older releases should refer to the Upgrading notes in this + document for that release. + + - Enhancements: + vpxenc --psnr shows a summary when encode completes + --tune=ssim option to enable activity masking + improved postproc visualizations for development + updated support for Apple iOS to SDK 4.2 + query decoder to determine which reference frames were updated + implemented error tracking in the decoder + fix pipe support on windows + + - Speed: + Primary focus was on good quality mode, speed 0. Average improvement + on x86 about 40%, up to 100% on user-generated content at that speed. + Best quality mode speed improved 35%, and realtime speed 10-20%. This + release also saw significant improvement in realtime encoding speed + on ARM platforms. + + Improved encoder threading + Dont pick encoder filter level when loopfilter is disabled. + Avoid double copying of key frames into alt and golden buffer + FDCT optimizations. + x86 sse2 temporal filter + SSSE3 version of fast quantizer + vp8_rd_pick_best_mbsegmentation code restructure + Adjusted breakout RD for SPLITMV + Changed segmentation check order + Improved rd_pick_intra4x4block + Adds armv6 optimized variance calculation + ARMv6 optimized sad16x16 + ARMv6 optimized half pixel variance calculations + Full search SAD function optimization in SSE4.1 + Improve MV prediction accuracy to achieve performance gain + Improve MV prediction in vp8_pick_inter_mode() for speed>3 + + - Quality: + Best quality mode improved PSNR 6.3%, and SSIM 6.1%. This release + also includes support for "activity masking," which greatly improves + SSIM at the expense of PSNR. For now, this feature is available with + the --tune=ssim option. Further experimentation in this area + is ongoing. This release also introduces a new rate control mode + called "CQ," which changes the allocation of bits within a clip to + the sections where they will have the most visual impact. + + Tuning for the more exact quantizer. + Relax rate control for last few frames + CQ Mode + Limit key frame quantizer for forced key frames. + KF/GF Pulsing + Add simple version of activity masking. + make rdmult adaptive for intra in quantizer RDO + cap the best quantizer for 2nd order DC + change the threshold of DC check for encode breakout + + - Bug Fixes: + Fix crash on Sparc Solaris. + Fix counter of fixed keyframe distance + ARNR filter pointer update bug fix + Fixed use of motion percentage in KF/GF group calc + Changed condition for using RD in Intra Mode + Fix encoder real-time only configuration. + Fix ARM encoder crash with multiple token partitions + Fixed bug first cluster timecode of webm file is wrong. + Fixed various encoder bugs with odd-sized images + vp8e_get_preview fixed when spatial resampling enabled + quantizer: fix assertion in fast quantizer path + Allocate source buffers to be multiples of 16 + Fix for manual Golden frame frequency + Fix drastic undershoot in long form content + + +2010-10-28 v0.9.5 "Aylesbury" + Our first named release, focused on a faster decoder, and a better encoder. + + - Upgrading: + This release incorporates backwards-incompatible changes to the + ivfenc and ivfdec tools. These tools are now called vpxenc and vpxdec. + + vpxdec + * the -q (quiet) option has been removed, and replaced with + -v (verbose). the output is quiet by default. Use -v to see + the version number of the binary. + + * The default behavior is now to write output to a single file + instead of individual frames. The -y option has been removed. + Y4M output is the default. + + * For raw I420/YV12 output instead of Y4M, the --i420 or --yv12 + options must be specified. + + $ ivfdec -o OUTPUT INPUT + $ vpxdec --i420 -o OUTPUT INPUT + + * If an output file is not specified, the default is to write + Y4M to stdout. This makes piping more natural. + + $ ivfdec -y -o - INPUT | ... + $ vpxdec INPUT | ... + + * The output file has additional flexibility for formatting the + filename. It supports escape characters for constructing a + filename from the width, height, and sequence number. This + replaces the -p option. To get the equivalent: + + $ ivfdec -p frame INPUT + $ vpxdec --i420 -o frame-%wx%h-%4.i420 INPUT + + vpxenc + * The output file must be specified with -o, rather than as the + last argument. + + $ ivfenc <options> INPUT OUTPUT + $ vpxenc <options> -o OUTPUT INPUT + + * The output defaults to webm. To get IVF output, use the --ivf + option. + + $ ivfenc <options> INPUT OUTPUT.ivf + $ vpxenc <options> -o OUTPUT.ivf --ivf INPUT + + + - Enhancements: + ivfenc and ivfdec have been renamed to vpxenc, vpxdec. + vpxdec supports .webm input + vpxdec writes .y4m by default + vpxenc writes .webm output by default + vpxenc --psnr now shows the average/overall PSNR at the end + ARM platforms now support runtime cpu detection + vpxdec visualizations added for motion vectors, block modes, references + vpxdec now silent by default + vpxdec --progress shows frame-by-frame timing information + vpxenc supports the distinction between --fps and --timebase + NASM is now a supported assembler + configure: enable PIC for shared libs by default + configure: add --enable-small + configure: support for ppc32-linux-gcc + configure: support for sparc-solaris-gcc + + - Bugs: + Improve handling of invalid frames + Fix valgrind errors in the NEON loop filters. + Fix loopfilter delta zero transitions + Fix valgrind errors in vp8_sixtap_predict8x4_armv6(). + Build fixes for darwin-icc + + - Speed: + 20-40% (average 28%) improvement in libvpx decoder speed, + including: + Rewrite vp8_short_walsh4x4_sse2() + Optimizations on the loopfilters. + Miscellaneous improvements for Atom + Add 4-tap version of 2nd-pass ARMv6 MC filter. + Improved multithread utilization + Better instruction choices on x86 + reorder data to use wider instructions + Update NEON wide idcts + Make block access to frame buffer sequential + Improved subset block search + Bilinear subpixel optimizations for ssse3. + Decrease memory footprint + + Encoder speed improvements (percentage gain not measured): + Skip unnecessary search of identical frames + Add SSE2 subtract functions + Improve bounds checking in vp8_diamond_search_sadx4() + Added vp8_fast_quantize_b_sse2 + + - Quality: + Over 7% overall PSNR improvement (6.3% SSIM) in "best" quality + encoding mode, and up to 60% improvement on very noisy, still + or slow moving source video + + Motion compensated temporal filter for Alt-Ref Noise Reduction + Improved use of trellis quantization on 2nd order Y blocks + Tune effect of motion on KF/GF boost in two pass + Allow coefficient optimization for good quality speed 0. + Improved control of active min quantizer for two pass. + Enable ARFs for non-lagged compress + +2010-09-02 v0.9.2 + - Enhancements: + Disable frame dropping by default + Improved multithreaded performance + Improved Force Key Frame Behaviour + Increased rate control buffer level precision + Fix bug in 1st pass motion compensation + ivfenc: correct fixed kf interval, --disable-kf + - Speed: + Changed above and left context data layout + Rework idct calling structure. + Removed unnecessary MB_MODE_INFO copies + x86: SSSE3 sixtap prediction + Reworked IDCT to include reconstruction (add) step + Swap alt/gold/new/last frame buffer ptrs instead of copying. + Improve SSE2 loopfilter functions + Change bitreader to use a larger window. + Avoid loopfilter reinitialization when possible + - Quality: + Normalize quantizer's zero bin and rounding factors + Add trellis quantization. + Make the quantizer exact. + Updates to ARNR filtering algorithm + Fix breakout thresh computation for golden & AltRef frames + Redo the forward 4x4 dct + Improve the accuracy of forward walsh-hadamard transform + Further adjustment of RD behaviour with Q and Zbin. + - Build System: + Allow linking of libs built with MinGW to MSVC + Fix target auto-detection on mingw32 + Allow --cpu= to work for x86. + configure: pass original arguments through to make dist + Fix builds without runtime CPU detection + msvs: fix install of codec sources + msvs: Change devenv.com command line for better msys support + msvs: Add vs9 targets. + Add x86_64-linux-icc target + - Bugs: + Potential crashes on older MinGW builds + Fix two-pass framrate for Y4M input. + Fixed simple loop filter, other crashes on ARM v6 + arm: fix missing dependency with --enable-shared + configure: support directories containing .o + Replace pinsrw (SSE) with MMX instructions + apple: include proper mach primatives + Fixed rate control bug with long key frame interval. + Fix DSO link errors on x86-64 when not using a version script + Fixed buffer selection for UV in AltRef filtering + + +2010-06-17 v0.9.1 + - Enhancements: + * ivfenc/ivfdec now support YUV4MPEG2 input and pipe I/O + * Speed optimizations + - Bugfixes: + * Rate control + * Prevent out-of-bounds accesses on invalid data + - Build system updates: + * Detect toolchain to be used automatically for native builds + * Support building shared libraries + * Better autotools emulation (--prefix, --libdir, DESTDIR) + - Updated LICENSE + * http://webmproject.blogspot.com/2010/06/changes-to-webm-open-source-license.html + + +2010-05-18 v0.9.0 + - Initial open source release. Welcome to WebM and VP8! +
diff --git a/src/third_party/libvpx/LICENSE b/src/third_party/libvpx/LICENSE new file mode 100644 index 0000000..1ce4434 --- /dev/null +++ b/src/third_party/libvpx/LICENSE
@@ -0,0 +1,31 @@ +Copyright (c) 2010, The WebM Project authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Google, nor the WebM Project, nor the names + of its contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +
diff --git a/src/third_party/libvpx/PATENTS b/src/third_party/libvpx/PATENTS new file mode 100644 index 0000000..caedf60 --- /dev/null +++ b/src/third_party/libvpx/PATENTS
@@ -0,0 +1,23 @@ +Additional IP Rights Grant (Patents) +------------------------------------ + +"These implementations" means the copyrightable works that implement the WebM +codecs distributed by Google as part of the WebM Project. + +Google hereby grants to you a perpetual, worldwide, non-exclusive, no-charge, +royalty-free, irrevocable (except as stated in this section) patent license to +make, have made, use, offer to sell, sell, import, transfer, and otherwise +run, modify and propagate the contents of these implementations of WebM, where +such license applies only to those patent claims, both currently owned by +Google and acquired in the future, licensable by Google that are necessarily +infringed by these implementations of WebM. This grant does not include claims +that would be infringed only as a consequence of further modification of these +implementations. If you or your agent or exclusive licensee institute or order +or agree to the institution of patent litigation or any other patent +enforcement activity against any entity (including a cross-claim or +counterclaim in a lawsuit) alleging that any of these implementations of WebM +or any code incorporated within any of these implementations of WebM +constitute direct or contributory patent infringement, or inducement of +patent infringement, then any patent rights granted to you under this License +for these implementations of WebM shall terminate as of the date such +litigation is filed.
diff --git a/src/third_party/libvpx/README b/src/third_party/libvpx/README new file mode 100644 index 0000000..29072b9 --- /dev/null +++ b/src/third_party/libvpx/README
@@ -0,0 +1,138 @@ +README - 23 March 2015 + +Welcome to the WebM VP8/VP9 Codec SDK! + +COMPILING THE APPLICATIONS/LIBRARIES: + The build system used is similar to autotools. Building generally consists of + "configuring" with your desired build options, then using GNU make to build + the application. + + 1. Prerequisites + + * All x86 targets require the Yasm[1] assembler be installed. + * All Windows builds require that Cygwin[2] be installed. + * Building the documentation requires Doxygen[3]. If you do not + have this package, the install-docs option will be disabled. + * Downloading the data for the unit tests requires curl[4] and sha1sum. + sha1sum is provided via the GNU coreutils, installed by default on + many *nix platforms, as well as MinGW and Cygwin. If coreutils is not + available, a compatible version of sha1sum can be built from + source[5]. These requirements are optional if not running the unit + tests. + + [1]: http://www.tortall.net/projects/yasm + [2]: http://www.cygwin.com + [3]: http://www.doxygen.org + [4]: http://curl.haxx.se + [5]: http://www.microbrew.org/tools/md5sha1sum/ + + 2. Out-of-tree builds + Out of tree builds are a supported method of building the application. For + an out of tree build, the source tree is kept separate from the object + files produced during compilation. For instance: + + $ mkdir build + $ cd build + $ ../libvpx/configure <options> + $ make + + 3. Configuration options + The 'configure' script supports a number of options. The --help option can be + used to get a list of supported options: + $ ../libvpx/configure --help + + 4. Cross development + For cross development, the most notable option is the --target option. The + most up-to-date list of supported targets can be found at the bottom of the + --help output of the configure script. As of this writing, the list of + available targets is: + + armv6-linux-rvct + armv6-linux-gcc + armv6-none-rvct + arm64-darwin-gcc + armv7-android-gcc + armv7-darwin-gcc + armv7-linux-rvct + armv7-linux-gcc + armv7-none-rvct + armv7-win32-vs11 + armv7-win32-vs12 + armv7-win32-vs14 + armv7s-darwin-gcc + mips32-linux-gcc + mips64-linux-gcc + sparc-solaris-gcc + x86-android-gcc + x86-darwin8-gcc + x86-darwin8-icc + x86-darwin9-gcc + x86-darwin9-icc + x86-darwin10-gcc + x86-darwin11-gcc + x86-darwin12-gcc + x86-darwin13-gcc + x86-darwin14-gcc + x86-iphonesimulator-gcc + x86-linux-gcc + x86-linux-icc + x86-os2-gcc + x86-solaris-gcc + x86-win32-gcc + x86-win32-vs7 + x86-win32-vs8 + x86-win32-vs9 + x86-win32-vs10 + x86-win32-vs11 + x86-win32-vs12 + x86-win32-vs14 + x86_64-android-gcc + x86_64-darwin9-gcc + x86_64-darwin10-gcc + x86_64-darwin11-gcc + x86_64-darwin12-gcc + x86_64-darwin13-gcc + x86_64-darwin14-gcc + x86_64-iphonesimulator-gcc + x86_64-linux-gcc + x86_64-linux-icc + x86_64-solaris-gcc + x86_64-win64-gcc + x86_64-win64-vs8 + x86_64-win64-vs9 + x86_64-win64-vs10 + x86_64-win64-vs11 + x86_64-win64-vs12 + x86_64-win64-vs14 + generic-gnu + + The generic-gnu target, in conjunction with the CROSS environment variable, + can be used to cross compile architectures that aren't explicitly listed, if + the toolchain is a cross GNU (gcc/binutils) toolchain. Other POSIX toolchains + will likely work as well. For instance, to build using the mipsel-linux-uclibc + toolchain, the following command could be used (note, POSIX SH syntax, adapt + to your shell as necessary): + + $ CROSS=mipsel-linux-uclibc- ../libvpx/configure + + In addition, the executables to be invoked can be overridden by specifying the + environment variables: CC, AR, LD, AS, STRIP, NM. Additional flags can be + passed to these executables with CFLAGS, LDFLAGS, and ASFLAGS. + + 5. Configuration errors + If the configuration step fails, the first step is to look in the error log. + This defaults to config.log. This should give a good indication of what went + wrong. If not, contact us for support. + +VP8/VP9 TEST VECTORS: + The test vectors can be downloaded and verified using the build system after + running configure. To specify an alternate directory the + LIBVPX_TEST_DATA_PATH environment variable can be used. + + $ ./configure --enable-unit-tests + $ LIBVPX_TEST_DATA_PATH=../libvpx-test-data make testdata + +SUPPORT + This library is an open source project supported by its community. Please + please email webm-discuss@webmproject.org for help. +
diff --git a/src/third_party/libvpx/README.lbshell b/src/third_party/libvpx/README.lbshell new file mode 100644 index 0000000..9e83ef4 --- /dev/null +++ b/src/third_party/libvpx/README.lbshell
@@ -0,0 +1,15 @@ +Name: libvpx +URL: http://www.webmproject.org +Version: v1.3.0 +License: BSD +License File: source/libvpx/LICENSE +Security Critical: yes + +Date: Fri Jan 9 2015 +Branch: master +Commit: ccffe318ffc90ae584c33e254b3a35e9142ecc20 + +This is the version used in the public Chrome release. +See: [chromium] //src/third_party/libvpx/README.chromium + +See platforms/ps4 for Steel-specific details.
diff --git a/src/third_party/libvpx/args.c b/src/third_party/libvpx/args.c new file mode 100644 index 0000000..14b0310 --- /dev/null +++ b/src/third_party/libvpx/args.c
@@ -0,0 +1,236 @@ +/* + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + + +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include "args.h" + +#include "vpx_ports/msvc.h" + +#if defined(__GNUC__) && __GNUC__ +extern void die(const char *fmt, ...) __attribute__((noreturn)); +#else +extern void die(const char *fmt, ...); +#endif + + +struct arg arg_init(char **argv) { + struct arg a; + + a.argv = argv; + a.argv_step = 1; + a.name = NULL; + a.val = NULL; + a.def = NULL; + return a; +} + +int arg_match(struct arg *arg_, const struct arg_def *def, char **argv) { + struct arg arg; + + if (!argv[0] || argv[0][0] != '-') + return 0; + + arg = arg_init(argv); + + if (def->short_name + && strlen(arg.argv[0]) == strlen(def->short_name) + 1 + && !strcmp(arg.argv[0] + 1, def->short_name)) { + + arg.name = arg.argv[0] + 1; + arg.val = def->has_val ? arg.argv[1] : NULL; + arg.argv_step = def->has_val ? 2 : 1; + } else if (def->long_name) { + const size_t name_len = strlen(def->long_name); + + if (strlen(arg.argv[0]) >= name_len + 2 + && arg.argv[0][1] == '-' + && !strncmp(arg.argv[0] + 2, def->long_name, name_len) + && (arg.argv[0][name_len + 2] == '=' + || arg.argv[0][name_len + 2] == '\0')) { + + arg.name = arg.argv[0] + 2; + arg.val = arg.name[name_len] == '=' ? arg.name + name_len + 1 : NULL; + arg.argv_step = 1; + } + } + + if (arg.name && !arg.val && def->has_val) + die("Error: option %s requires argument.\n", arg.name); + + if (arg.name && arg.val && !def->has_val) + die("Error: option %s requires no argument.\n", arg.name); + + if (arg.name + && (arg.val || !def->has_val)) { + arg.def = def; + *arg_ = arg; + return 1; + } + + return 0; +} + + +const char *arg_next(struct arg *arg) { + if (arg->argv[0]) + arg->argv += arg->argv_step; + + return *arg->argv; +} + + +char **argv_dup(int argc, const char **argv) { + char **new_argv = malloc((argc + 1) * sizeof(*argv)); + + memcpy(new_argv, argv, argc * sizeof(*argv)); + new_argv[argc] = NULL; + return new_argv; +} + + +void arg_show_usage(FILE *fp, const struct arg_def *const *defs) { + char option_text[40] = {0}; + + for (; *defs; defs++) { + const struct arg_def *def = *defs; + char *short_val = def->has_val ? " <arg>" : ""; + char *long_val = def->has_val ? "=<arg>" : ""; + + if (def->short_name && def->long_name) { + char *comma = def->has_val ? "," : ", "; + + snprintf(option_text, 37, "-%s%s%s --%s%6s", + def->short_name, short_val, comma, + def->long_name, long_val); + } else if (def->short_name) + snprintf(option_text, 37, "-%s%s", + def->short_name, short_val); + else if (def->long_name) + snprintf(option_text, 37, " --%s%s", + def->long_name, long_val); + + fprintf(fp, " %-37s\t%s\n", option_text, def->desc); + + if (def->enums) { + const struct arg_enum_list *listptr; + + fprintf(fp, " %-37s\t ", ""); + + for (listptr = def->enums; listptr->name; listptr++) + fprintf(fp, "%s%s", listptr->name, + listptr[1].name ? ", " : "\n"); + } + } +} + + +unsigned int arg_parse_uint(const struct arg *arg) { + long int rawval; + char *endptr; + + rawval = strtol(arg->val, &endptr, 10); + + if (arg->val[0] != '\0' && endptr[0] == '\0') { + if (rawval >= 0 && rawval <= UINT_MAX) + return rawval; + + die("Option %s: Value %ld out of range for unsigned int\n", + arg->name, rawval); + } + + die("Option %s: Invalid character '%c'\n", arg->name, *endptr); + return 0; +} + + +int arg_parse_int(const struct arg *arg) { + long int rawval; + char *endptr; + + rawval = strtol(arg->val, &endptr, 10); + + if (arg->val[0] != '\0' && endptr[0] == '\0') { + if (rawval >= INT_MIN && rawval <= INT_MAX) + return rawval; + + die("Option %s: Value %ld out of range for signed int\n", + arg->name, rawval); + } + + die("Option %s: Invalid character '%c'\n", arg->name, *endptr); + return 0; +} + + +struct vpx_rational { + int num; /**< fraction numerator */ + int den; /**< fraction denominator */ +}; +struct vpx_rational arg_parse_rational(const struct arg *arg) { + long int rawval; + char *endptr; + struct vpx_rational rat; + + /* parse numerator */ + rawval = strtol(arg->val, &endptr, 10); + + if (arg->val[0] != '\0' && endptr[0] == '/') { + if (rawval >= INT_MIN && rawval <= INT_MAX) + rat.num = rawval; + else die("Option %s: Value %ld out of range for signed int\n", + arg->name, rawval); + } else die("Option %s: Expected / at '%c'\n", arg->name, *endptr); + + /* parse denominator */ + rawval = strtol(endptr + 1, &endptr, 10); + + if (arg->val[0] != '\0' && endptr[0] == '\0') { + if (rawval >= INT_MIN && rawval <= INT_MAX) + rat.den = rawval; + else die("Option %s: Value %ld out of range for signed int\n", + arg->name, rawval); + } else die("Option %s: Invalid character '%c'\n", arg->name, *endptr); + + return rat; +} + + +int arg_parse_enum(const struct arg *arg) { + const struct arg_enum_list *listptr; + long int rawval; + char *endptr; + + /* First see if the value can be parsed as a raw value */ + rawval = strtol(arg->val, &endptr, 10); + if (arg->val[0] != '\0' && endptr[0] == '\0') { + /* Got a raw value, make sure it's valid */ + for (listptr = arg->def->enums; listptr->name; listptr++) + if (listptr->val == rawval) + return rawval; + } + + /* Next see if it can be parsed as a string */ + for (listptr = arg->def->enums; listptr->name; listptr++) + if (!strcmp(arg->val, listptr->name)) + return listptr->val; + + die("Option %s: Invalid value '%s'\n", arg->name, arg->val); + return 0; +} + + +int arg_parse_enum_or_int(const struct arg *arg) { + if (arg->def->enums) + return arg_parse_enum(arg); + return arg_parse_int(arg); +}
diff --git a/src/third_party/libvpx/args.h b/src/third_party/libvpx/args.h new file mode 100644 index 0000000..1f37151 --- /dev/null +++ b/src/third_party/libvpx/args.h
@@ -0,0 +1,60 @@ +/* + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + + +#ifndef ARGS_H_ +#define ARGS_H_ +#include <stdio.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct arg { + char **argv; + const char *name; + const char *val; + unsigned int argv_step; + const struct arg_def *def; +}; + +struct arg_enum_list { + const char *name; + int val; +}; +#define ARG_ENUM_LIST_END {0} + +typedef struct arg_def { + const char *short_name; + const char *long_name; + int has_val; + const char *desc; + const struct arg_enum_list *enums; +} arg_def_t; +#define ARG_DEF(s,l,v,d) {s,l,v,d, NULL} +#define ARG_DEF_ENUM(s,l,v,d,e) {s,l,v,d,e} +#define ARG_DEF_LIST_END {0} + +struct arg arg_init(char **argv); +int arg_match(struct arg *arg_, const struct arg_def *def, char **argv); +const char *arg_next(struct arg *arg); +void arg_show_usage(FILE *fp, const struct arg_def *const *defs); +char **argv_dup(int argc, const char **argv); + +unsigned int arg_parse_uint(const struct arg *arg); +int arg_parse_int(const struct arg *arg); +struct vpx_rational arg_parse_rational(const struct arg *arg); +int arg_parse_enum(const struct arg *arg); +int arg_parse_enum_or_int(const struct arg *arg); +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // ARGS_H_
diff --git a/src/third_party/libvpx/build/make/Android.mk b/src/third_party/libvpx/build/make/Android.mk new file mode 100644 index 0000000..df01dec --- /dev/null +++ b/src/third_party/libvpx/build/make/Android.mk
@@ -0,0 +1,205 @@ +## +## Copyright (c) 2012 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## + +# +# This file is to be used for compiling libvpx for Android using the NDK. +# In an Android project place a libvpx checkout in the jni directory. +# Run the configure script from the jni directory. Base libvpx +# encoder/decoder configuration will look similar to: +# ./libvpx/configure --target=armv7-android-gcc --disable-examples \ +# --sdk-path=/opt/android-ndk-r6b/ +# +# When targeting Android, realtime-only is enabled by default. This can +# be overridden by adding the command line flag: +# --disable-realtime-only +# +# This will create .mk files that contain variables that contain the +# source files to compile. +# +# Place an Android.mk file in the jni directory that references the +# Android.mk file in the libvpx directory: +# LOCAL_PATH := $(call my-dir) +# include $(CLEAR_VARS) +# include jni/libvpx/build/make/Android.mk +# +# There are currently two TARGET_ARCH_ABI targets for ARM. +# armeabi and armeabi-v7a. armeabi-v7a is selected by creating an +# Application.mk in the jni directory that contains: +# APP_ABI := armeabi-v7a +# +# By default libvpx will detect at runtime the existance of NEON extension. +# For this we import the 'cpufeatures' module from the NDK sources. +# libvpx can also be configured without this runtime detection method. +# Configuring with --disable-runtime-cpu-detect will assume presence of NEON. +# Configuring with --disable-runtime-cpu-detect --disable-neon \ +# --disable-neon-asm +# will remove any NEON dependency. + +# To change to building armeabi, run ./libvpx/configure again, but with +# --target=armv6-android-gcc and modify the Application.mk file to +# set APP_ABI := armeabi +# +# Running ndk-build will build libvpx and include it in your project. +# + +CONFIG_DIR := $(LOCAL_PATH)/ +LIBVPX_PATH := $(LOCAL_PATH)/libvpx +ASM_CNV_PATH_LOCAL := $(TARGET_ARCH_ABI)/ads2gas +ASM_CNV_PATH := $(LOCAL_PATH)/$(ASM_CNV_PATH_LOCAL) + +# Use the makefiles generated by upstream configure to determine which files to +# build. Also set any architecture-specific flags. +ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) + include $(CONFIG_DIR)libs-armv7-android-gcc.mk + LOCAL_ARM_MODE := arm +else ifeq ($(TARGET_ARCH_ABI),armeabi) + include $(CONFIG_DIR)libs-armv6-android-gcc.mk + LOCAL_ARM_MODE := arm +else ifeq ($(TARGET_ARCH_ABI),arm64-v8a) + include $(CONFIG_DIR)libs-armv8-android-gcc.mk + LOCAL_ARM_MODE := arm +else ifeq ($(TARGET_ARCH_ABI),x86) + include $(CONFIG_DIR)libs-x86-android-gcc.mk +else ifeq ($(TARGET_ARCH_ABI),x86_64) + include $(CONFIG_DIR)libs-x86_64-android-gcc.mk +else ifeq ($(TARGET_ARCH_ABI),mips) + include $(CONFIG_DIR)libs-mips-android-gcc.mk +else + $(error Not a supported TARGET_ARCH_ABI: $(TARGET_ARCH_ABI)) +endif + +# Rule that is normally in Makefile created by libvpx +# configure. Used to filter out source files based on configuration. +enabled=$(filter-out $($(1)-no),$($(1)-yes)) + +# Override the relative path that is defined by the libvpx +# configure process +SRC_PATH_BARE := $(LIBVPX_PATH) + +# Include the list of files to be built +include $(LIBVPX_PATH)/libs.mk + +# Optimise the code. May want to revisit this setting in the future. +LOCAL_CFLAGS := -O3 + +# For x86, include the source code in the search path so it will find files +# like x86inc.asm and x86_abi_support.asm +LOCAL_ASMFLAGS := -I$(LIBVPX_PATH) + +.PRECIOUS: %.asm.s +$(ASM_CNV_PATH)/libvpx/%.asm.s: $(LIBVPX_PATH)/%.asm + @mkdir -p $(dir $@) + @$(CONFIG_DIR)$(ASM_CONVERSION) <$< > $@ + +# For building *_rtcd.h, which have rules in libs.mk +TGT_ISA:=$(word 1, $(subst -, ,$(TOOLCHAIN))) +target := libs + +LOCAL_SRC_FILES += vpx_config.c + +# Remove duplicate entries +CODEC_SRCS_UNIQUE = $(sort $(CODEC_SRCS)) + +# Pull out C files. vpx_config.c is in the immediate directory and +# so it does not need libvpx/ prefixed like the rest of the source files. +# The neon files with intrinsics need to have .neon appended so the proper +# flags are applied. +CODEC_SRCS_C = $(filter %.c, $(CODEC_SRCS_UNIQUE)) +LOCAL_NEON_SRCS_C = $(filter %_neon.c, $(CODEC_SRCS_C)) +LOCAL_CODEC_SRCS_C = $(filter-out vpx_config.c %_neon.c, $(CODEC_SRCS_C)) + +LOCAL_SRC_FILES += $(foreach file, $(LOCAL_CODEC_SRCS_C), libvpx/$(file)) +ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) + LOCAL_SRC_FILES += $(foreach file, $(LOCAL_NEON_SRCS_C), libvpx/$(file).neon) +else # If there are neon sources then we are building for arm64 and do not need to specify .neon + LOCAL_SRC_FILES += $(foreach file, $(LOCAL_NEON_SRCS_C), libvpx/$(file)) +endif + +# Pull out assembly files, splitting NEON from the rest. This is +# done to specify that the NEON assembly files use NEON assembler flags. +# x86 assembly matches %.asm, arm matches %.asm.s + +# x86: + +CODEC_SRCS_ASM_X86 = $(filter %.asm, $(CODEC_SRCS_UNIQUE)) +LOCAL_SRC_FILES += $(foreach file, $(CODEC_SRCS_ASM_X86), libvpx/$(file)) + +# arm: +CODEC_SRCS_ASM_ARM_ALL = $(filter %.asm.s, $(CODEC_SRCS_UNIQUE)) +CODEC_SRCS_ASM_ARM = $(foreach v, \ + $(CODEC_SRCS_ASM_ARM_ALL), \ + $(if $(findstring neon,$(v)),,$(v))) +CODEC_SRCS_ASM_ADS2GAS = $(patsubst %.s, \ + $(ASM_CNV_PATH_LOCAL)/libvpx/%.s, \ + $(CODEC_SRCS_ASM_ARM)) +LOCAL_SRC_FILES += $(CODEC_SRCS_ASM_ADS2GAS) + +ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) + CODEC_SRCS_ASM_NEON = $(foreach v, \ + $(CODEC_SRCS_ASM_ARM_ALL),\ + $(if $(findstring neon,$(v)),$(v),)) + CODEC_SRCS_ASM_NEON_ADS2GAS = $(patsubst %.s, \ + $(ASM_CNV_PATH_LOCAL)/libvpx/%.s, \ + $(CODEC_SRCS_ASM_NEON)) + LOCAL_SRC_FILES += $(patsubst %.s, \ + %.s.neon, \ + $(CODEC_SRCS_ASM_NEON_ADS2GAS)) +endif + +LOCAL_CFLAGS += \ + -DHAVE_CONFIG_H=vpx_config.h \ + -I$(LIBVPX_PATH) \ + -I$(ASM_CNV_PATH) + +LOCAL_MODULE := libvpx + +ifeq ($(CONFIG_RUNTIME_CPU_DETECT),yes) + LOCAL_STATIC_LIBRARIES := cpufeatures +endif + +# Add a dependency to force generation of the RTCD files. +define rtcd_dep_template +rtcd_dep_template_SRCS := $(addprefix $(LOCAL_PATH)/, $(LOCAL_SRC_FILES)) +rtcd_dep_template_SRCS := $$(rtcd_dep_template_SRCS:.neon=) +ifeq ($(CONFIG_VP8), yes) +$$(rtcd_dep_template_SRCS): vp8_rtcd.h +endif +ifeq ($(CONFIG_VP9), yes) +$$(rtcd_dep_template_SRCS): vp9_rtcd.h +endif +ifeq ($(CONFIG_VP10), yes) +$$(rtcd_dep_template_SRCS): vp10_rtcd.h +endif +$$(rtcd_dep_template_SRCS): vpx_scale_rtcd.h +$$(rtcd_dep_template_SRCS): vpx_dsp_rtcd.h + +ifneq ($(findstring $(TARGET_ARCH_ABI),x86 x86_64),) +$$(rtcd_dep_template_SRCS): vpx_config.asm +endif +endef + +$(eval $(call rtcd_dep_template)) + +.PHONY: clean +clean: + @echo "Clean: ads2gas files [$(TARGET_ARCH_ABI)]" + @$(RM) $(CODEC_SRCS_ASM_ADS2GAS) $(CODEC_SRCS_ASM_NEON_ADS2GAS) + @$(RM) -r $(ASM_CNV_PATH) + @$(RM) $(CLEAN-OBJS) + +ifeq ($(ENABLE_SHARED),1) + include $(BUILD_SHARED_LIBRARY) +else + include $(BUILD_STATIC_LIBRARY) +endif + +ifeq ($(CONFIG_RUNTIME_CPU_DETECT),yes) +$(call import-module,cpufeatures) +endif
diff --git a/src/third_party/libvpx/build/make/Makefile b/src/third_party/libvpx/build/make/Makefile new file mode 100644 index 0000000..3e8c0249 --- /dev/null +++ b/src/third_party/libvpx/build/make/Makefile
@@ -0,0 +1,451 @@ +## +## Copyright (c) 2010 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## + + +include config.mk +quiet?=true +ifeq ($(target),) +# If a target wasn't specified, invoke for all enabled targets. +.DEFAULT: + @for t in $(ALL_TARGETS); do \ + $(MAKE) --no-print-directory target=$$t $(MAKECMDGOALS) || exit $$?;\ + done +all: .DEFAULT +clean:: .DEFAULT +exampletest: .DEFAULT +install:: .DEFAULT +test:: .DEFAULT +test-no-data-check:: .DEFAULT +testdata:: .DEFAULT +utiltest: .DEFAULT +exampletest-no-data-check utiltest-no-data-check: .DEFAULT + + +# Note: md5sum is not installed on OS X, but openssl is. Openssl may not be +# installed on cygwin, so we need to autodetect here. +md5sum := $(firstword $(wildcard \ + $(foreach e,md5sum openssl,\ + $(foreach p,$(subst :, ,$(PATH)),$(p)/$(e)*))\ + )) +md5sum := $(if $(filter %openssl,$(md5sum)),$(md5sum) dgst -md5,$(md5sum)) + +TGT_CC:=$(word 3, $(subst -, ,$(TOOLCHAIN))) +dist: + @for t in $(ALL_TARGETS); do \ + $(MAKE) --no-print-directory target=$$t $(MAKECMDGOALS) || exit $$?;\ + done + # Run configure for the user with the current toolchain. + @if [ -d "$(DIST_DIR)/src" ]; then \ + mkdir -p "$(DIST_DIR)/build"; \ + cd "$(DIST_DIR)/build"; \ + echo "Rerunning configure $(CONFIGURE_ARGS)"; \ + ../src/configure $(CONFIGURE_ARGS); \ + $(if $(filter vs%,$(TGT_CC)),make NO_LAUNCH_DEVENV=1;) \ + fi + @if [ -d "$(DIST_DIR)" ]; then \ + echo " [MD5SUM] $(DIST_DIR)"; \ + cd $(DIST_DIR) && \ + $(md5sum) `find . -name md5sums.txt -prune -o -type f -print` \ + | sed -e 's/MD5(\(.*\))= \([0-9a-f]\{32\}\)/\2 \1/' \ + > md5sums.txt;\ + fi +endif + +# Since we invoke make recursively for multiple targets we need to include the +# .mk file for the correct target, but only when $(target) is non-empty. +ifneq ($(target),) +include $(target)-$(TOOLCHAIN).mk +endif +BUILD_ROOT?=. +VPATH=$(SRC_PATH_BARE) +CFLAGS+=-I$(BUILD_PFX)$(BUILD_ROOT) -I$(SRC_PATH) +CXXFLAGS+=-I$(BUILD_PFX)$(BUILD_ROOT) -I$(SRC_PATH) +ASFLAGS+=-I$(BUILD_PFX)$(BUILD_ROOT)/ -I$(SRC_PATH)/ +DIST_DIR?=dist +HOSTCC?=gcc +TGT_ISA:=$(word 1, $(subst -, ,$(TOOLCHAIN))) +TGT_OS:=$(word 2, $(subst -, ,$(TOOLCHAIN))) +TGT_CC:=$(word 3, $(subst -, ,$(TOOLCHAIN))) +quiet:=$(if $(or $(verbose), $(V)),, yes) +qexec=$(if $(quiet),@) + +# Cancel built-in implicit rules +%: %.o +%.asm: +%.a: +%: %.cc + +# +# Common rules" +# +.PHONY: all +all: + +.PHONY: clean +clean:: + rm -f $(OBJS-yes) $(OBJS-yes:.o=.d) $(OBJS-yes:.asm.s.o=.asm.s) + rm -f $(CLEAN-OBJS) + +.PHONY: clean +distclean: clean + if [ -z "$(target)" ]; then \ + rm -f Makefile; \ + rm -f config.log config.mk; \ + rm -f vpx_config.[hc] vpx_config.asm; \ + else \ + rm -f $(target)-$(TOOLCHAIN).mk; \ + fi + +.PHONY: dist +dist: +.PHONY: exampletest +exampletest: +.PHONY: install +install:: +.PHONY: test +test:: +.PHONY: testdata +testdata:: +.PHONY: utiltest +utiltest: +.PHONY: test-no-data-check exampletest-no-data-check utiltest-no-data-check +test-no-data-check:: +exampletest-no-data-check utiltest-no-data-check: + +# Force to realign stack always on OS/2 +ifeq ($(TOOLCHAIN), x86-os2-gcc) +CFLAGS += -mstackrealign +endif + +$(BUILD_PFX)%_mmx.c.d: CFLAGS += -mmmx +$(BUILD_PFX)%_mmx.c.o: CFLAGS += -mmmx +$(BUILD_PFX)%_sse2.c.d: CFLAGS += -msse2 +$(BUILD_PFX)%_sse2.c.o: CFLAGS += -msse2 +$(BUILD_PFX)%_sse3.c.d: CFLAGS += -msse3 +$(BUILD_PFX)%_sse3.c.o: CFLAGS += -msse3 +$(BUILD_PFX)%_ssse3.c.d: CFLAGS += -mssse3 +$(BUILD_PFX)%_ssse3.c.o: CFLAGS += -mssse3 +$(BUILD_PFX)%_sse4.c.d: CFLAGS += -msse4.1 +$(BUILD_PFX)%_sse4.c.o: CFLAGS += -msse4.1 +$(BUILD_PFX)%_avx.c.d: CFLAGS += -mavx +$(BUILD_PFX)%_avx.c.o: CFLAGS += -mavx +$(BUILD_PFX)%_avx2.c.d: CFLAGS += -mavx2 +$(BUILD_PFX)%_avx2.c.o: CFLAGS += -mavx2 + +$(BUILD_PFX)%.c.d: %.c + $(if $(quiet),@echo " [DEP] $@") + $(qexec)mkdir -p $(dir $@) + $(qexec)$(CC) $(INTERNAL_CFLAGS) $(CFLAGS) -M $< | $(fmt_deps) > $@ + +$(BUILD_PFX)%.c.o: %.c + $(if $(quiet),@echo " [CC] $@") + $(qexec)$(if $(CONFIG_DEPENDENCY_TRACKING),,mkdir -p $(dir $@)) + $(qexec)$(CC) $(INTERNAL_CFLAGS) $(CFLAGS) -c -o $@ $< + +$(BUILD_PFX)%.cc.d: %.cc + $(if $(quiet),@echo " [DEP] $@") + $(qexec)mkdir -p $(dir $@) + $(qexec)$(CXX) $(INTERNAL_CFLAGS) $(CXXFLAGS) -M $< | $(fmt_deps) > $@ + +$(BUILD_PFX)%.cc.o: %.cc + $(if $(quiet),@echo " [CXX] $@") + $(qexec)$(if $(CONFIG_DEPENDENCY_TRACKING),,mkdir -p $(dir $@)) + $(qexec)$(CXX) $(INTERNAL_CFLAGS) $(CXXFLAGS) -c -o $@ $< + +$(BUILD_PFX)%.cpp.d: %.cpp + $(if $(quiet),@echo " [DEP] $@") + $(qexec)mkdir -p $(dir $@) + $(qexec)$(CXX) $(INTERNAL_CFLAGS) $(CXXFLAGS) -M $< | $(fmt_deps) > $@ + +$(BUILD_PFX)%.cpp.o: %.cpp + $(if $(quiet),@echo " [CXX] $@") + $(qexec)$(if $(CONFIG_DEPENDENCY_TRACKING),,mkdir -p $(dir $@)) + $(qexec)$(CXX) $(INTERNAL_CFLAGS) $(CXXFLAGS) -c -o $@ $< + +$(BUILD_PFX)%.asm.d: %.asm + $(if $(quiet),@echo " [DEP] $@") + $(qexec)mkdir -p $(dir $@) + $(qexec)$(SRC_PATH_BARE)/build/make/gen_asm_deps.sh \ + --build-pfx=$(BUILD_PFX) --depfile=$@ $(ASFLAGS) $< > $@ + +$(BUILD_PFX)%.asm.o: %.asm + $(if $(quiet),@echo " [AS] $@") + $(qexec)$(if $(CONFIG_DEPENDENCY_TRACKING),,mkdir -p $(dir $@)) + $(qexec)$(AS) $(ASFLAGS) -o $@ $< + +$(BUILD_PFX)%.s.d: %.s + $(if $(quiet),@echo " [DEP] $@") + $(qexec)mkdir -p $(dir $@) + $(qexec)$(SRC_PATH_BARE)/build/make/gen_asm_deps.sh \ + --build-pfx=$(BUILD_PFX) --depfile=$@ $(ASFLAGS) $< > $@ + +$(BUILD_PFX)%.s.o: %.s + $(if $(quiet),@echo " [AS] $@") + $(qexec)$(if $(CONFIG_DEPENDENCY_TRACKING),,mkdir -p $(dir $@)) + $(qexec)$(AS) $(ASFLAGS) -o $@ $< + +.PRECIOUS: %.c.S +%.c.S: CFLAGS += -DINLINE_ASM +$(BUILD_PFX)%.c.S: %.c + $(if $(quiet),@echo " [GEN] $@") + $(qexec)$(if $(CONFIG_DEPENDENCY_TRACKING),,mkdir -p $(dir $@)) + $(qexec)$(CC) -S $(CFLAGS) -o $@ $< + +.PRECIOUS: %.asm.s +$(BUILD_PFX)%.asm.s: %.asm + $(if $(quiet),@echo " [ASM CONVERSION] $@") + $(qexec)mkdir -p $(dir $@) + $(qexec)$(ASM_CONVERSION) <$< >$@ + +# If we're in debug mode, pretend we don't have GNU strip, to fall back to +# the copy implementation +HAVE_GNU_STRIP := $(if $(CONFIG_DEBUG),,$(HAVE_GNU_STRIP)) +ifeq ($(HAVE_GNU_STRIP),yes) +# Older binutils strip global symbols not needed for relocation processing +# when given --strip-unneeded. Using nm and awk to identify globals and +# keep them caused command line length issues under mingw and segfaults in +# test_libvpx were observed under OS/2: simply use --strip-debug. +%.a: %_g.a + $(if $(quiet),@echo " [STRIP] $@ < $<") + $(qexec)$(STRIP) --strip-debug \ + -o $@ $< +else +%.a: %_g.a + $(if $(quiet),@echo " [CP] $@ < $<") + $(qexec)cp $< $@ +endif + +# +# Utility functions +# +pairmap=$(if $(strip $(2)),\ + $(call $(1),$(word 1,$(2)),$(word 2,$(2)))\ + $(call pairmap,$(1),$(wordlist 3,$(words $(2)),$(2)))\ +) + +enabled=$(filter-out $($(1)-no),$($(1)-yes)) +cond_enabled=$(if $(filter yes,$($(1))), $(call enabled,$(2))) + +find_file1=$(word 1,$(wildcard $(subst //,/,$(addsuffix /$(1),$(2))))) +find_file=$(foreach f,$(1),$(call find_file1,$(strip $(f)),$(strip $(2))) ) +obj_pats=.c=.c.o $(AS_SFX)=$(AS_SFX).o .cc=.cc.o .cpp=.cpp.o +objs=$(addprefix $(BUILD_PFX),$(foreach p,$(obj_pats),$(filter %.o,$(1:$(p))) )) + +install_map_templates=$(eval $(call install_map_template,$(1),$(2))) + +not=$(subst yes,no,$(1)) + +ifeq ($(CONFIG_MSVS),yes) +lib_file_name=$(1).lib +else +lib_file_name=lib$(1).a +endif +# +# Rule Templates +# +define linker_template +$(1): $(filter-out -%,$(2)) +$(1): + $(if $(quiet),@echo " [LD] $$@") + $(qexec)$$(LD) $$(strip $$(INTERNAL_LDFLAGS) $$(LDFLAGS) -o $$@ $(2) $(3) $$(extralibs)) +endef +define linkerxx_template +$(1): $(filter-out -%,$(2)) +$(1): + $(if $(quiet),@echo " [LD] $$@") + $(qexec)$$(CXX) $$(strip $$(INTERNAL_LDFLAGS) $$(LDFLAGS) -o $$@ $(2) $(3) $$(extralibs)) +endef +# make-3.80 has a bug with expanding large input strings to the eval function, +# which was triggered in some cases by the following component of +# linker_template: +# $(1): $$(call find_file, $(patsubst -l%,lib%.a,$(filter -l%,$(2))),\ +# $$(patsubst -L%,%,$$(filter -L%,$$(LDFLAGS) $(2)))) +# This may be useful to revisit in the future (it tries to locate libraries +# in a search path and add them as prerequisites + +define install_map_template +$(DIST_DIR)/$(1): $(2) + $(if $(quiet),@echo " [INSTALL] $$@") + $(qexec)mkdir -p $$(dir $$@) + $(qexec)cp -p $$< $$@ +endef + +define archive_template +# Not using a pattern rule here because we don't want to generate empty +# archives when they are listed as a dependency in files not responsible +# for creating them. +$(1): + $(if $(quiet),@echo " [AR] $$@") + $(qexec)$$(AR) $$(ARFLAGS) $$@ $$^ +endef + +define so_template +# Not using a pattern rule here because we don't want to generate empty +# archives when they are listed as a dependency in files not responsible +# for creating them. +# +# This needs further abstraction for dealing with non-GNU linkers. +$(1): + $(if $(quiet),@echo " [LD] $$@") + $(qexec)$$(LD) -shared $$(LDFLAGS) \ + -Wl,--no-undefined -Wl,-soname,$$(SONAME) \ + -Wl,--version-script,$$(EXPORTS_FILE) -o $$@ \ + $$(filter %.o,$$^) $$(extralibs) +endef + +define dl_template +# Not using a pattern rule here because we don't want to generate empty +# archives when they are listed as a dependency in files not responsible +# for creating them. +$(1): + $(if $(quiet),@echo " [LD] $$@") + $(qexec)$$(LD) -dynamiclib $$(LDFLAGS) \ + -exported_symbols_list $$(EXPORTS_FILE) \ + -Wl,-headerpad_max_install_names,-compatibility_version,1.0,-current_version,$$(VERSION_MAJOR) \ + -o $$@ \ + $$(filter %.o,$$^) $$(extralibs) +endef + +define dll_template +# Not using a pattern rule here because we don't want to generate empty +# archives when they are listed as a dependency in files not responsible +# for creating them. +$(1): + $(if $(quiet),@echo " [LD] $$@") + $(qexec)$$(LD) -Zdll $$(LDFLAGS) \ + -o $$@ \ + $$(filter %.o,$$^) $$(extralibs) $$(EXPORTS_FILE) +endef + + +# +# Get current configuration +# +ifneq ($(target),) +include $(SRC_PATH_BARE)/$(target:-$(TOOLCHAIN)=).mk +endif + +skip_deps := $(filter %clean,$(MAKECMDGOALS)) +skip_deps += $(findstring testdata,$(MAKECMDGOALS)) +ifeq ($(strip $(skip_deps)),) + ifeq ($(CONFIG_DEPENDENCY_TRACKING),yes) + # Older versions of make don't like -include directives with no arguments + ifneq ($(filter %.d,$(OBJS-yes:.o=.d)),) + -include $(filter %.d,$(OBJS-yes:.o=.d)) + endif + endif +endif + +# +# Configuration dependent rules +# +$(call pairmap,install_map_templates,$(INSTALL_MAPS)) + +DOCS=$(call cond_enabled,CONFIG_INSTALL_DOCS,DOCS) +.docs: $(DOCS) + @touch $@ + +INSTALL-DOCS=$(call cond_enabled,CONFIG_INSTALL_DOCS,INSTALL-DOCS) +ifeq ($(MAKECMDGOALS),dist) +INSTALL-DOCS+=$(call cond_enabled,CONFIG_INSTALL_DOCS,DIST-DOCS) +endif +.install-docs: .docs $(addprefix $(DIST_DIR)/,$(INSTALL-DOCS)) + @touch $@ + +clean:: + rm -f .docs .install-docs $(DOCS) + +BINS=$(call enabled,BINS) +.bins: $(BINS) + @touch $@ + +INSTALL-BINS=$(call cond_enabled,CONFIG_INSTALL_BINS,INSTALL-BINS) +ifeq ($(MAKECMDGOALS),dist) +INSTALL-BINS+=$(call cond_enabled,CONFIG_INSTALL_BINS,DIST-BINS) +endif +.install-bins: .bins $(addprefix $(DIST_DIR)/,$(INSTALL-BINS)) + @touch $@ + +clean:: + rm -f .bins .install-bins $(BINS) + +LIBS=$(call enabled,LIBS) +.libs: $(LIBS) + @touch $@ +$(foreach lib,$(filter %_g.a,$(LIBS)),$(eval $(call archive_template,$(lib)))) +$(foreach lib,$(filter %so.$(SO_VERSION_MAJOR).$(SO_VERSION_MINOR).$(SO_VERSION_PATCH),$(LIBS)),$(eval $(call so_template,$(lib)))) +$(foreach lib,$(filter %$(SO_VERSION_MAJOR).dylib,$(LIBS)),$(eval $(call dl_template,$(lib)))) +$(foreach lib,$(filter %$(SO_VERSION_MAJOR).dll,$(LIBS)),$(eval $(call dll_template,$(lib)))) + +INSTALL-LIBS=$(call cond_enabled,CONFIG_INSTALL_LIBS,INSTALL-LIBS) +ifeq ($(MAKECMDGOALS),dist) +INSTALL-LIBS+=$(call cond_enabled,CONFIG_INSTALL_LIBS,DIST-LIBS) +endif +.install-libs: .libs $(addprefix $(DIST_DIR)/,$(INSTALL-LIBS)) + @touch $@ + +clean:: + rm -f .libs .install-libs $(LIBS) + +ifeq ($(CONFIG_EXTERNAL_BUILD),yes) +PROJECTS=$(call enabled,PROJECTS) +.projects: $(PROJECTS) + @touch $@ + +INSTALL-PROJECTS=$(call cond_enabled,CONFIG_INSTALL_PROJECTS,INSTALL-PROJECTS) +ifeq ($(MAKECMDGOALS),dist) +INSTALL-PROJECTS+=$(call cond_enabled,CONFIG_INSTALL_PROJECTS,DIST-PROJECTS) +endif +.install-projects: .projects $(addprefix $(DIST_DIR)/,$(INSTALL-PROJECTS)) + @touch $@ + +clean:: + rm -f .projects .install-projects $(PROJECTS) +endif + +# If there are any source files to be distributed, then include the build +# system too. +ifneq ($(call enabled,DIST-SRCS),) + DIST-SRCS-yes += configure + DIST-SRCS-yes += build/make/configure.sh + DIST-SRCS-yes += build/make/gen_asm_deps.sh + DIST-SRCS-yes += build/make/Makefile + DIST-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_def.sh + DIST-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_proj.sh + DIST-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_sln.sh + DIST-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_vcxproj.sh + DIST-SRCS-$(CONFIG_MSVS) += build/make/msvs_common.sh + DIST-SRCS-$(CONFIG_RVCT) += build/make/armlink_adapter.sh + DIST-SRCS-$(ARCH_ARM) += build/make/ads2gas.pl + DIST-SRCS-$(ARCH_ARM) += build/make/ads2gas_apple.pl + DIST-SRCS-$(ARCH_ARM) += build/make/ads2armasm_ms.pl + DIST-SRCS-$(ARCH_ARM) += build/make/thumb.pm + DIST-SRCS-yes += $(target:-$(TOOLCHAIN)=).mk +endif +INSTALL-SRCS := $(call cond_enabled,CONFIG_INSTALL_SRCS,INSTALL-SRCS) +ifeq ($(MAKECMDGOALS),dist) +INSTALL-SRCS += $(call cond_enabled,CONFIG_INSTALL_SRCS,DIST-SRCS) +endif +.install-srcs: $(addprefix $(DIST_DIR)/src/,$(INSTALL-SRCS)) + @touch $@ + +clean:: + rm -f .install-srcs + +ifeq ($(CONFIG_EXTERNAL_BUILD),yes) + BUILD_TARGETS += .projects + INSTALL_TARGETS += .install-projects +endif +BUILD_TARGETS += .docs .libs .bins +INSTALL_TARGETS += .install-docs .install-srcs .install-libs .install-bins +all: $(BUILD_TARGETS) +install:: $(INSTALL_TARGETS) +dist: $(INSTALL_TARGETS) +test::
diff --git a/src/third_party/libvpx/build/make/ads2armasm_ms.pl b/src/third_party/libvpx/build/make/ads2armasm_ms.pl new file mode 100755 index 0000000..2a2c470 --- /dev/null +++ b/src/third_party/libvpx/build/make/ads2armasm_ms.pl
@@ -0,0 +1,39 @@ +#!/usr/bin/env perl +## +## Copyright (c) 2013 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## + +use FindBin; +use lib $FindBin::Bin; +use thumb; + +print "; This file was created from a .asm file\n"; +print "; using the ads2armasm_ms.pl script.\n"; + +while (<STDIN>) +{ + undef $comment; + undef $line; + + s/REQUIRE8//; + s/PRESERVE8//; + s/^\s*ARM\s*$//; + s/AREA\s+\|\|(.*)\|\|/AREA |$1|/; + s/qsubaddx/qsax/i; + s/qaddsubx/qasx/i; + + thumb::FixThumbInstructions($_, 1); + + s/ldrneb/ldrbne/i; + s/ldrneh/ldrhne/i; + s/^(\s*)ENDP.*/$&\n$1ALIGN 4/; + + print; +} +
diff --git a/src/third_party/libvpx/build/make/ads2gas.pl b/src/third_party/libvpx/build/make/ads2gas.pl new file mode 100755 index 0000000..7272424 --- /dev/null +++ b/src/third_party/libvpx/build/make/ads2gas.pl
@@ -0,0 +1,236 @@ +#!/usr/bin/env perl +## +## Copyright (c) 2010 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## + + +# ads2gas.pl +# Author: Eric Fung (efung (at) acm.org) +# +# Convert ARM Developer Suite 1.0.1 syntax assembly source to GNU as format +# +# Usage: cat inputfile | perl ads2gas.pl > outputfile +# + +use FindBin; +use lib $FindBin::Bin; +use thumb; + +my $thumb = 0; + +foreach my $arg (@ARGV) { + $thumb = 1 if ($arg eq "-thumb"); +} + +print "@ This file was created from a .asm file\n"; +print "@ using the ads2gas.pl script.\n"; +print "\t.equ DO1STROUNDING, 0\n"; +if ($thumb) { + print "\t.syntax unified\n"; + print "\t.thumb\n"; +} + +# Stack of procedure names. +@proc_stack = (); + +while (<STDIN>) +{ + undef $comment; + undef $line; + $comment_char = ";"; + $comment_sub = "@"; + + # Handle comments. + if (/$comment_char/) + { + $comment = ""; + ($line, $comment) = /(.*?)$comment_char(.*)/; + $_ = $line; + } + + # Load and store alignment + s/@/,:/g; + + # Hexadecimal constants prefaced by 0x + s/#&/#0x/g; + + # Convert :OR: to | + s/:OR:/ | /g; + + # Convert :AND: to & + s/:AND:/ & /g; + + # Convert :NOT: to ~ + s/:NOT:/ ~ /g; + + # Convert :SHL: to << + s/:SHL:/ << /g; + + # Convert :SHR: to >> + s/:SHR:/ >> /g; + + # Convert ELSE to .else + s/\bELSE\b/.else/g; + + # Convert ENDIF to .endif + s/\bENDIF\b/.endif/g; + + # Convert ELSEIF to .elseif + s/\bELSEIF\b/.elseif/g; + + # Convert LTORG to .ltorg + s/\bLTORG\b/.ltorg/g; + + # Convert endfunc to nothing. + s/\bendfunc\b//ig; + + # Convert FUNCTION to nothing. + s/\bFUNCTION\b//g; + s/\bfunction\b//g; + + s/\bENTRY\b//g; + s/\bMSARMASM\b/0/g; + s/^\s+end\s+$//g; + + # Convert IF :DEF:to .if + # gcc doesn't have the ability to do a conditional + # if defined variable that is set by IF :DEF: on + # armasm, so convert it to a normal .if and then + # make sure to define a value elesewhere + if (s/\bIF :DEF:\b/.if /g) + { + s/=/==/g; + } + + # Convert IF to .if + if (s/\bIF\b/.if/g) + { + s/=+/==/g; + } + + # Convert INCLUDE to .INCLUDE "file" + s/INCLUDE(\s*)(.*)$/.include $1\"$2\"/; + + # Code directive (ARM vs Thumb) + s/CODE([0-9][0-9])/.code $1/; + + # No AREA required + # But ALIGNs in AREA must be obeyed + s/^\s*AREA.*ALIGN=([0-9])$/.text\n.p2align $1/; + # If no ALIGN, strip the AREA and align to 4 bytes + s/^\s*AREA.*$/.text\n.p2align 2/; + + # DCD to .word + # This one is for incoming symbols + s/DCD\s+\|(\w*)\|/.long $1/; + + # DCW to .short + s/DCW\s+\|(\w*)\|/.short $1/; + s/DCW(.*)/.short $1/; + + # Constants defined in scope + s/DCD(.*)/.long $1/; + s/DCB(.*)/.byte $1/; + + # RN to .req + if (s/RN\s+([Rr]\d+|lr)/.req $1/) + { + print; + print "$comment_sub$comment\n" if defined $comment; + next; + } + + # Make function visible to linker, and make additional symbol with + # prepended underscore + s/EXPORT\s+\|([\$\w]*)\|/.global $1 \n\t.type $1, function/; + s/IMPORT\s+\|([\$\w]*)\|/.global $1/; + + s/EXPORT\s+([\$\w]*)/.global $1/; + s/export\s+([\$\w]*)/.global $1/; + + # No vertical bars required; make additional symbol with prepended + # underscore + s/^\|(\$?\w+)\|/_$1\n\t$1:/g; + + # Labels need trailing colon +# s/^(\w+)/$1:/ if !/EQU/; + # put the colon at the end of the line in the macro + s/^([a-zA-Z_0-9\$]+)/$1:/ if !/EQU/; + + # ALIGN directive + s/\bALIGN\b/.balign/g; + + if ($thumb) { + # ARM code - we force everything to thumb with the declaration in the header + s/\sARM//g; + } else { + # ARM code + s/\sARM/.arm/g; + } + + # push/pop + s/(push\s+)(r\d+)/stmdb sp\!, \{$2\}/g; + s/(pop\s+)(r\d+)/ldmia sp\!, \{$2\}/g; + + # NEON code + s/(vld1.\d+\s+)(q\d+)/$1\{$2\}/g; + s/(vtbl.\d+\s+[^,]+),([^,]+)/$1,\{$2\}/g; + + if ($thumb) { + thumb::FixThumbInstructions($_, 0); + } + + # eabi_attributes numerical equivalents can be found in the + # "ARM IHI 0045C" document. + + # REQUIRE8 Stack is required to be 8-byte aligned + s/\sREQUIRE8/.eabi_attribute 24, 1 \@Tag_ABI_align_needed/g; + + # PRESERVE8 Stack 8-byte align is preserved + s/\sPRESERVE8/.eabi_attribute 25, 1 \@Tag_ABI_align_preserved/g; + + # Use PROC and ENDP to give the symbols a .size directive. + # This makes them show up properly in debugging tools like gdb and valgrind. + if (/\bPROC\b/) + { + my $proc; + /^_([\.0-9A-Z_a-z]\w+)\b/; + $proc = $1; + push(@proc_stack, $proc) if ($proc); + s/\bPROC\b/@ $&/; + } + if (/\bENDP\b/) + { + my $proc; + s/\bENDP\b/@ $&/; + $proc = pop(@proc_stack); + $_ = "\t.size $proc, .-$proc".$_ if ($proc); + } + + # EQU directive + s/(\S+\s+)EQU(\s+\S+)/.equ $1, $2/; + + # Begin macro definition + if (/\bMACRO\b/) { + $_ = <STDIN>; + s/^/.macro/; + s/\$//g; # remove formal param reference + s/;/@/g; # change comment characters + } + + # For macros, use \ to reference formal params + s/\$/\\/g; # End macro definition + s/\bMEND\b/.endm/; # No need to tell it where to stop assembling + next if /^\s*END\s*$/; + print; + print "$comment_sub$comment\n" if defined $comment; +} + +# Mark that this object doesn't need an executable stack. +printf ("\t.section\t.note.GNU-stack,\"\",\%\%progbits\n");
diff --git a/src/third_party/libvpx/build/make/ads2gas_apple.pl b/src/third_party/libvpx/build/make/ads2gas_apple.pl new file mode 100755 index 0000000..a82f3eb --- /dev/null +++ b/src/third_party/libvpx/build/make/ads2gas_apple.pl
@@ -0,0 +1,235 @@ +#!/usr/bin/env perl +## +## Copyright (c) 2010 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## + + +# ads2gas_apple.pl +# Author: Eric Fung (efung (at) acm.org) +# +# Convert ARM Developer Suite 1.0.1 syntax assembly source to GNU as format +# +# Usage: cat inputfile | perl ads2gas_apple.pl > outputfile +# + +my $chromium = 0; + +foreach my $arg (@ARGV) { + $chromium = 1 if ($arg eq "-chromium"); +} + +print "@ This file was created from a .asm file\n"; +print "@ using the ads2gas_apple.pl script.\n\n"; +print "\t.set WIDE_REFERENCE, 0\n"; +print "\t.set ARCHITECTURE, 5\n"; +print "\t.set DO1STROUNDING, 0\n"; + +my %register_aliases; +my %macro_aliases; + +my @mapping_list = ("\$0", "\$1", "\$2", "\$3", "\$4", "\$5", "\$6", "\$7", "\$8", "\$9"); + +my @incoming_array; + +my @imported_functions; + +# Perl trim function to remove whitespace from the start and end of the string +sub trim($) +{ + my $string = shift; + $string =~ s/^\s+//; + $string =~ s/\s+$//; + return $string; +} + +while (<STDIN>) +{ + # Load and store alignment + s/@/,:/g; + + # Comment character + s/;/ @/g; + + # Hexadecimal constants prefaced by 0x + s/#&/#0x/g; + + # Convert :OR: to | + s/:OR:/ | /g; + + # Convert :AND: to & + s/:AND:/ & /g; + + # Convert :NOT: to ~ + s/:NOT:/ ~ /g; + + # Convert :SHL: to << + s/:SHL:/ << /g; + + # Convert :SHR: to >> + s/:SHR:/ >> /g; + + # Convert ELSE to .else + s/\bELSE\b/.else/g; + + # Convert ENDIF to .endif + s/\bENDIF\b/.endif/g; + + # Convert ELSEIF to .elseif + s/\bELSEIF\b/.elseif/g; + + # Convert LTORG to .ltorg + s/\bLTORG\b/.ltorg/g; + + # Convert IF :DEF:to .if + # gcc doesn't have the ability to do a conditional + # if defined variable that is set by IF :DEF: on + # armasm, so convert it to a normal .if and then + # make sure to define a value elesewhere + if (s/\bIF :DEF:\b/.if /g) + { + s/=/==/g; + } + + # Convert IF to .if + if (s/\bIF\b/.if/g) + { + s/=/==/g; + } + + # Convert INCLUDE to .INCLUDE "file" + s/INCLUDE(\s*)(.*)$/.include $1\"$2\"/; + + # Code directive (ARM vs Thumb) + s/CODE([0-9][0-9])/.code $1/; + + # No AREA required + # But ALIGNs in AREA must be obeyed + s/^\s*AREA.*ALIGN=([0-9])$/.text\n.p2align $1/; + # If no ALIGN, strip the AREA and align to 4 bytes + s/^\s*AREA.*$/.text\n.p2align 2/; + + # DCD to .word + # This one is for incoming symbols + s/DCD\s+\|(\w*)\|/.long $1/; + + # DCW to .short + s/DCW\s+\|(\w*)\|/.short $1/; + s/DCW(.*)/.short $1/; + + # Constants defined in scope + s/DCD(.*)/.long $1/; + s/DCB(.*)/.byte $1/; + + # Build a hash of all the register - alias pairs. + if (s/(.*)RN(.*)/$1 .req $2/g) + { + $register_aliases{trim($1)} = trim($2); + next; + } + + while (($key, $value) = each(%register_aliases)) + { + s/\b$key\b/$value/g; + } + + # Make function visible to linker, and make additional symbol with + # prepended underscore + s/EXPORT\s+\|([\$\w]*)\|/.globl _$1\n\t.globl $1/; + + # Prepend imported functions with _ + if (s/IMPORT\s+\|([\$\w]*)\|/.globl $1/) + { + $function = trim($1); + push(@imported_functions, $function); + } + + foreach $function (@imported_functions) + { + s/$function/_$function/; + } + + # No vertical bars required; make additional symbol with prepended + # underscore + s/^\|(\$?\w+)\|/_$1\n\t$1:/g; + + # Labels need trailing colon +# s/^(\w+)/$1:/ if !/EQU/; + # put the colon at the end of the line in the macro + s/^([a-zA-Z_0-9\$]+)/$1:/ if !/EQU/; + + # ALIGN directive + s/\bALIGN\b/.balign/g; + + # Strip ARM + s/\sARM/@ ARM/g; + + # Strip REQUIRE8 + #s/\sREQUIRE8/@ REQUIRE8/g; + s/\sREQUIRE8/@ /g; + + # Strip PRESERVE8 + s/\sPRESERVE8/@ PRESERVE8/g; + + # Strip PROC and ENDPROC + s/\bPROC\b/@/g; + s/\bENDP\b/@/g; + + # EQU directive + s/(.*)EQU(.*)/.set $1, $2/; + + # Begin macro definition + if (/\bMACRO\b/) + { + # Process next line down, which will be the macro definition + $_ = <STDIN>; + + $trimmed = trim($_); + + # remove commas that are separating list + $trimmed =~ s/,//g; + + # string to array + @incoming_array = split(/\s+/, $trimmed); + + print ".macro @incoming_array[0]\n"; + + # remove the first element, as that is the name of the macro + shift (@incoming_array); + + @macro_aliases{@incoming_array} = @mapping_list; + + next; + } + + while (($key, $value) = each(%macro_aliases)) + { + $key =~ s/\$/\\\$/; + s/$key\b/$value/g; + } + + # For macros, use \ to reference formal params +# s/\$/\\/g; # End macro definition + s/\bMEND\b/.endm/; # No need to tell it where to stop assembling + next if /^\s*END\s*$/; + + # Clang used by Chromium differs slightly from clang in XCode in what it + # will accept in the assembly. + if ($chromium) { + s/qsubaddx/qsax/i; + s/qaddsubx/qasx/i; + s/ldrneb/ldrbne/i; + s/ldrneh/ldrhne/i; + s/(vqshrun\.s16 .*, \#)0$/${1}8/i; + + # http://llvm.org/bugs/show_bug.cgi?id=16022 + s/\.include/#include/; + } + + print; +}
diff --git a/src/third_party/libvpx/build/make/armlink_adapter.sh b/src/third_party/libvpx/build/make/armlink_adapter.sh new file mode 100755 index 0000000..75c342e --- /dev/null +++ b/src/third_party/libvpx/build/make/armlink_adapter.sh
@@ -0,0 +1,54 @@ +#!/bin/sh +## +## Copyright (c) 2010 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## + + +verbose=0 +set -- $* +for i; do + if [ "$i" = "-o" ]; then + on_of=1 + elif [ "$i" = "-v" ]; then + verbose=1 + elif [ "$i" = "-g" ]; then + args="${args} --debug" + elif [ "$on_of" = "1" ]; then + outfile=$i + on_of=0 + elif [ -f "$i" ]; then + infiles="$infiles $i" + elif [ "${i#-l}" != "$i" ]; then + libs="$libs ${i#-l}" + elif [ "${i#-L}" != "$i" ]; then + libpaths="${libpaths} ${i#-L}" + else + args="${args} ${i}" + fi + shift +done + +# Absolutize library file names +for f in $libs; do + found=0 + for d in $libpaths; do + [ -f "$d/$f" ] && infiles="$infiles $d/$f" && found=1 && break + [ -f "$d/lib${f}.so" ] && infiles="$infiles $d/lib${f}.so" && found=1 && break + [ -f "$d/lib${f}.a" ] && infiles="$infiles $d/lib${f}.a" && found=1 && break + done + [ $found -eq 0 ] && infiles="$infiles $f" +done +for d in $libpaths; do + [ -n "$libsearchpath" ] && libsearchpath="${libsearchpath}," + libsearchpath="${libsearchpath}$d" +done + +cmd="armlink $args --userlibpath=$libsearchpath --output=$outfile $infiles" +[ $verbose -eq 1 ] && echo $cmd +$cmd
diff --git a/src/third_party/libvpx/build/make/configure.sh b/src/third_party/libvpx/build/make/configure.sh new file mode 100644 index 0000000..c738504 --- /dev/null +++ b/src/third_party/libvpx/build/make/configure.sh
@@ -0,0 +1,1605 @@ +#!/bin/sh +## +## configure.sh +## +## This script is sourced by the main configure script and contains +## utility functions and other common bits that aren't strictly libvpx +## related. +## +## This build system is based in part on the FFmpeg configure script. +## + + +# +# Logging / Output Functions +# +die_unknown(){ + echo "Unknown option \"$1\"." + echo "See $0 --help for available options." + clean_temp_files + exit 1 +} + +die() { + echo "$@" + echo + echo "Configuration failed. This could reflect a misconfiguration of your" + echo "toolchains, improper options selected, or another problem. If you" + echo "don't see any useful error messages above, the next step is to look" + echo "at the configure error log file ($logfile) to determine what" + echo "configure was trying to do when it died." + clean_temp_files + exit 1 +} + +log(){ + echo "$@" >>$logfile +} + +log_file(){ + log BEGIN $1 + cat -n $1 >>$logfile + log END $1 +} + +log_echo() { + echo "$@" + log "$@" +} + +fwrite () { + outfile=$1 + shift + echo "$@" >> ${outfile} +} + +show_help_pre(){ + for opt in ${CMDLINE_SELECT}; do + opt2=`echo $opt | sed -e 's;_;-;g'` + if enabled $opt; then + eval "toggle_${opt}=\"--disable-${opt2}\"" + else + eval "toggle_${opt}=\"--enable-${opt2} \"" + fi + done + + cat <<EOF +Usage: configure [options] +Options: + +Build options: + --help print this message + --log=yes|no|FILE file configure log is written to [config.log] + --target=TARGET target platform tuple [generic-gnu] + --cpu=CPU optimize for a specific cpu rather than a family + --extra-cflags=ECFLAGS add ECFLAGS to CFLAGS [$CFLAGS] + --extra-cxxflags=ECXXFLAGS add ECXXFLAGS to CXXFLAGS [$CXXFLAGS] + ${toggle_extra_warnings} emit harmless warnings (always non-fatal) + ${toggle_werror} treat warnings as errors, if possible + (not available with all compilers) + ${toggle_optimizations} turn on/off compiler optimization flags + ${toggle_pic} turn on/off Position Independent Code + ${toggle_ccache} turn on/off compiler cache + ${toggle_debug} enable/disable debug mode + ${toggle_gprof} enable/disable gprof profiling instrumentation + ${toggle_gcov} enable/disable gcov coverage instrumentation + ${toggle_thumb} enable/disable building arm assembly in thumb mode + ${toggle_dependency_tracking} + disable to speed up one-time build + +Install options: + ${toggle_install_docs} control whether docs are installed + ${toggle_install_bins} control whether binaries are installed + ${toggle_install_libs} control whether libraries are installed + ${toggle_install_srcs} control whether sources are installed + + +EOF +} + +show_help_post(){ + cat <<EOF + + +NOTES: + Object files are built at the place where configure is launched. + + All boolean options can be negated. The default value is the opposite + of that shown above. If the option --disable-foo is listed, then + the default value for foo is enabled. + +Supported targets: +EOF + show_targets ${all_platforms} + echo + exit 1 +} + +show_targets() { + while [ -n "$*" ]; do + if [ "${1%%-*}" = "${2%%-*}" ]; then + if [ "${2%%-*}" = "${3%%-*}" ]; then + printf " %-24s %-24s %-24s\n" "$1" "$2" "$3" + shift; shift; shift + else + printf " %-24s %-24s\n" "$1" "$2" + shift; shift + fi + else + printf " %-24s\n" "$1" + shift + fi + done +} + +show_help() { + show_help_pre + show_help_post +} + +# +# List Processing Functions +# +set_all(){ + value=$1 + shift + for var in $*; do + eval $var=$value + done +} + +is_in(){ + value=$1 + shift + for var in $*; do + [ $var = $value ] && return 0 + done + return 1 +} + +add_cflags() { + CFLAGS="${CFLAGS} $@" + CXXFLAGS="${CXXFLAGS} $@" +} + +add_cflags_only() { + CFLAGS="${CFLAGS} $@" +} + +add_cxxflags_only() { + CXXFLAGS="${CXXFLAGS} $@" +} + +add_ldflags() { + LDFLAGS="${LDFLAGS} $@" +} + +add_asflags() { + ASFLAGS="${ASFLAGS} $@" +} + +add_extralibs() { + extralibs="${extralibs} $@" +} + +# +# Boolean Manipulation Functions +# + +enable_codec(){ + enabled $1 || echo " enabling $1" + set_all yes $1 + + is_in $1 vp8 vp9 vp10 && \ + set_all yes $1_encoder && \ + set_all yes $1_decoder +} + +disable_codec(){ + disabled $1 || echo " disabling $1" + set_all no $1 + + is_in $1 vp8 vp9 vp10 && \ + set_all no $1_encoder && \ + set_all no $1_decoder +} + +enable_feature(){ + set_all yes $* +} + +disable_feature(){ + set_all no $* +} + +enabled(){ + eval test "x\$$1" = "xyes" +} + +disabled(){ + eval test "x\$$1" = "xno" +} + +# Iterates through positional parameters, checks to confirm the parameter has +# not been explicitly (force) disabled, and enables the setting controlled by +# the parameter when the setting is not disabled. +# Note: Does NOT alter RTCD generation options ($RTCD_OPTIONS). +soft_enable() { + for var in $*; do + if ! disabled $var; then + enabled $var || log_echo " enabling $var" + enable_feature $var + fi + done +} + +# Iterates through positional parameters, checks to confirm the parameter has +# not been explicitly (force) enabled, and disables the setting controlled by +# the parameter when the setting is not enabled. +# Note: Does NOT alter RTCD generation options ($RTCD_OPTIONS). +soft_disable() { + for var in $*; do + if ! enabled $var; then + disabled $var || log_echo " disabling $var" + disable_feature $var + fi + done +} + +# +# Text Processing Functions +# +toupper(){ + echo "$@" | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ +} + +tolower(){ + echo "$@" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz +} + +# +# Temporary File Functions +# +source_path=${0%/*} +enable_feature source_path_used +if [ -z "$source_path" ] || [ "$source_path" = "." ]; then + # rjogrady: Hack for Cygwin / PS4 interaction. + # PS4 compiler doesn't understand cygdrive. + #source_path="`pwd`" + source_path='.' + disable_feature source_path_used +fi + +if test ! -z "$TMPDIR" ; then + TMPDIRx="${TMPDIR}" +elif test ! -z "$TEMPDIR" ; then + TMPDIRx="${TEMPDIR}" +else + TMPDIRx="/tmp" +fi +RAND=$(awk 'BEGIN { srand(); printf "%d\n",(rand() * 32768)}') +TMP_H="${TMPDIRx}/vpx-conf-$$-${RAND}.h" +TMP_C="${TMPDIRx}/vpx-conf-$$-${RAND}.c" +TMP_CC="${TMPDIRx}/vpx-conf-$$-${RAND}.cc" +TMP_O="${TMPDIRx}/vpx-conf-$$-${RAND}.o" +TMP_X="${TMPDIRx}/vpx-conf-$$-${RAND}.x" +TMP_ASM="${TMPDIRx}/vpx-conf-$$-${RAND}.asm" + +clean_temp_files() { + rm -f ${TMP_C} ${TMP_CC} ${TMP_H} ${TMP_O} ${TMP_X} ${TMP_ASM} + enabled gcov && rm -f ${TMP_C%.c}.gcno ${TMP_CC%.cc}.gcno +} + +# +# Toolchain Check Functions +# +check_cmd() { + enabled external_build && return + log "$@" + "$@" >>${logfile} 2>&1 +} + +check_cc() { + log check_cc "$@" + cat >${TMP_C} + log_file ${TMP_C} + check_cmd ${CC} ${CFLAGS} "$@" -c -o ${TMP_O} ${TMP_C} +} + +check_cxx() { + log check_cxx "$@" + cat >${TMP_CC} + log_file ${TMP_CC} + check_cmd ${CXX} ${CXXFLAGS} "$@" -c -o ${TMP_O} ${TMP_CC} +} + +check_cpp() { + log check_cpp "$@" + cat > ${TMP_C} + log_file ${TMP_C} + check_cmd ${CC} ${CFLAGS} "$@" -E -o ${TMP_O} ${TMP_C} +} + +check_ld() { + log check_ld "$@" + check_cc $@ \ + && check_cmd ${LD} ${LDFLAGS} "$@" -o ${TMP_X} ${TMP_O} ${extralibs} +} + +check_header(){ + log check_header "$@" + header=$1 + shift + var=`echo $header | sed 's/[^A-Za-z0-9_]/_/g'` + disable_feature $var + check_cpp "$@" <<EOF && enable_feature $var +#include "$header" +int x; +EOF +} + +check_cflags() { + log check_cflags "$@" + check_cc -Werror "$@" <<EOF +int x; +EOF +} + +check_cxxflags() { + log check_cxxflags "$@" + + # Catch CFLAGS that trigger CXX warnings + case "$CXX" in + *c++-analyzer|*clang++|*g++*) + check_cxx -Werror "$@" <<EOF +int x; +EOF + ;; + *) + check_cxx -Werror "$@" <<EOF +int x; +EOF + ;; + esac +} + +check_add_cflags() { + check_cxxflags "$@" && add_cxxflags_only "$@" + check_cflags "$@" && add_cflags_only "$@" +} + +check_add_cxxflags() { + check_cxxflags "$@" && add_cxxflags_only "$@" +} + +check_add_asflags() { + log add_asflags "$@" + add_asflags "$@" +} + +check_add_ldflags() { + log add_ldflags "$@" + add_ldflags "$@" +} + +check_asm_align() { + log check_asm_align "$@" + cat >${TMP_ASM} <<EOF +section .rodata +align 16 +EOF + log_file ${TMP_ASM} + check_cmd ${AS} ${ASFLAGS} -o ${TMP_O} ${TMP_ASM} + readelf -WS ${TMP_O} >${TMP_X} + log_file ${TMP_X} + if ! grep -q '\.rodata .* 16$' ${TMP_X}; then + die "${AS} ${ASFLAGS} does not support section alignment (nasm <=2.08?)" + fi +} + +# tests for -m$1 toggling the feature given in $2. If $2 is empty $1 is used. +check_gcc_machine_option() { + opt="$1" + feature="$2" + [ -n "$feature" ] || feature="$opt" + + if enabled gcc && ! disabled "$feature" && ! check_cflags "-m$opt"; then + RTCD_OPTIONS="${RTCD_OPTIONS}--disable-$feature " + else + soft_enable "$feature" + fi +} + +write_common_config_banner() { + print_webm_license config.mk "##" "" + echo '# This file automatically generated by configure. Do not edit!' >> config.mk + echo "TOOLCHAIN := ${toolchain}" >> config.mk + + case ${toolchain} in + *-linux-rvct) + echo "ALT_LIBC := ${alt_libc}" >> config.mk + ;; + esac +} + +write_common_config_targets() { + for t in ${all_targets}; do + if enabled ${t}; then + if enabled child; then + fwrite config.mk "ALL_TARGETS += ${t}-${toolchain}" + else + fwrite config.mk "ALL_TARGETS += ${t}" + fi + fi + true; + done + true +} + +write_common_target_config_mk() { + saved_CC="${CC}" + saved_CXX="${CXX}" + enabled ccache && CC="ccache ${CC}" + enabled ccache && CXX="ccache ${CXX}" + print_webm_license $1 "##" "" + + cat >> $1 << EOF +# This file automatically generated by configure. Do not edit! +SRC_PATH="$source_path" +SRC_PATH_BARE=$source_path +BUILD_PFX=${BUILD_PFX} +TOOLCHAIN=${toolchain} +ASM_CONVERSION=${asm_conversion_cmd:-${source_path}/build/make/ads2gas.pl} +GEN_VCPROJ=${gen_vcproj_cmd} +MSVS_ARCH_DIR=${msvs_arch_dir} + +CC=${CC} +CXX=${CXX} +AR=${AR} +LD=${LD} +AS=${AS} +STRIP=${STRIP} +NM=${NM} + +CFLAGS = ${CFLAGS} +CXXFLAGS = ${CXXFLAGS} +ARFLAGS = -crs\$(if \$(quiet),,v) +LDFLAGS = ${LDFLAGS} +ASFLAGS = ${ASFLAGS} +extralibs = ${extralibs} +AS_SFX = ${AS_SFX:-.asm} +EXE_SFX = ${EXE_SFX} +VCPROJ_SFX = ${VCPROJ_SFX} +RTCD_OPTIONS = ${RTCD_OPTIONS} +EOF + + if enabled rvct; then cat >> $1 << EOF +fmt_deps = sed -e 's;^__image.axf;\${@:.d=.o} \$@;' #hide +EOF +elif enabled orbis; then cat >> $1 << EOF +fmt_deps = python fix_orbis_deps.py +EOF + else cat >> $1 << EOF +fmt_deps = sed -e 's;^\([a-zA-Z0-9_]*\)\.o;\${@:.d=.o} \$@;' +EOF + fi + + print_config_mk ARCH "${1}" ${ARCH_LIST} + print_config_mk HAVE "${1}" ${HAVE_LIST} + print_config_mk CONFIG "${1}" ${CONFIG_LIST} + print_config_mk HAVE "${1}" gnu_strip + + enabled msvs && echo "CONFIG_VS_VERSION=${vs_version}" >> "${1}" + + CC="${saved_CC}" + CXX="${saved_CXX}" +} + +write_common_target_config_h() { + print_webm_license ${TMP_H} "/*" " */" + cat >> ${TMP_H} << EOF +/* This file automatically generated by configure. Do not edit! */ +#ifndef VPX_CONFIG_H +#define VPX_CONFIG_H +#define RESTRICT ${RESTRICT} +#define INLINE ${INLINE} +EOF + print_config_h ARCH "${TMP_H}" ${ARCH_LIST} + print_config_h HAVE "${TMP_H}" ${HAVE_LIST} + print_config_h CONFIG "${TMP_H}" ${CONFIG_LIST} + print_config_vars_h "${TMP_H}" ${VAR_LIST} + echo "#endif /* VPX_CONFIG_H */" >> ${TMP_H} + mkdir -p `dirname "$1"` + cmp "$1" ${TMP_H} >/dev/null 2>&1 || mv ${TMP_H} "$1" +} + +process_common_cmdline() { + for opt in "$@"; do + optval="${opt#*=}" + case "$opt" in + --child) + enable_feature child + ;; + --log*) + logging="$optval" + if ! disabled logging ; then + enabled logging || logfile="$logging" + else + logfile=/dev/null + fi + ;; + --target=*) + toolchain="${toolchain:-${optval}}" + ;; + --force-target=*) + toolchain="${toolchain:-${optval}}" + enable_feature force_toolchain + ;; + --cpu=*) + tune_cpu="$optval" + ;; + --extra-cflags=*) + extra_cflags="${optval}" + ;; + --extra-cxxflags=*) + extra_cxxflags="${optval}" + ;; + --enable-?*|--disable-?*) + eval `echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g'` + if is_in ${option} ${ARCH_EXT_LIST}; then + [ $action = "disable" ] && RTCD_OPTIONS="${RTCD_OPTIONS}--disable-${option} " + elif [ $action = "disable" ] && ! disabled $option ; then + is_in ${option} ${CMDLINE_SELECT} || die_unknown $opt + log_echo " disabling $option" + elif [ $action = "enable" ] && ! enabled $option ; then + is_in ${option} ${CMDLINE_SELECT} || die_unknown $opt + log_echo " enabling $option" + fi + ${action}_feature $option + ;; + --require-?*) + eval `echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g'` + if is_in ${option} ${ARCH_EXT_LIST}; then + RTCD_OPTIONS="${RTCD_OPTIONS}${opt} " + else + die_unknown $opt + fi + ;; + --force-enable-?*|--force-disable-?*) + eval `echo "$opt" | sed 's/--force-/action=/;s/-/ option=/;s/-/_/g'` + ${action}_feature $option + ;; + --libc=*) + [ -d "${optval}" ] || die "Not a directory: ${optval}" + disable_feature builtin_libc + alt_libc="${optval}" + ;; + --as=*) + [ "${optval}" = yasm ] || [ "${optval}" = nasm ] \ + || [ "${optval}" = auto ] \ + || die "Must be yasm, nasm or auto: ${optval}" + alt_as="${optval}" + ;; + --size-limit=*) + w="${optval%%x*}" + h="${optval##*x}" + VAR_LIST="DECODE_WIDTH_LIMIT ${w} DECODE_HEIGHT_LIMIT ${h}" + [ ${w} -gt 0 ] && [ ${h} -gt 0 ] || die "Invalid size-limit: too small." + [ ${w} -lt 65536 ] && [ ${h} -lt 65536 ] \ + || die "Invalid size-limit: too big." + enable_feature size_limit + ;; + --prefix=*) + prefix="${optval}" + ;; + --libdir=*) + libdir="${optval}" + ;; + --sdk-path=*) + [ -d "${optval}" ] || die "Not a directory: ${optval}" + sdk_path="${optval}" + ;; + --libc|--as|--prefix|--libdir|--sdk-path) + die "Option ${opt} requires argument" + ;; + --help|-h) + show_help + ;; + *) + die_unknown $opt + ;; + esac + done +} + +process_cmdline() { + for opt do + optval="${opt#*=}" + case "$opt" in + *) + process_common_cmdline $opt + ;; + esac + done +} + +post_process_common_cmdline() { + prefix="${prefix:-/usr/local}" + prefix="${prefix%/}" + libdir="${libdir:-${prefix}/lib}" + libdir="${libdir%/}" + if [ "${libdir#${prefix}}" = "${libdir}" ]; then + die "Libdir ${libdir} must be a subdirectory of ${prefix}" + fi +} + +post_process_cmdline() { + true; +} + +setup_gnu_toolchain() { + CC=${CC:-${CROSS}gcc} + CXX=${CXX:-${CROSS}g++} + AR=${AR:-${CROSS}ar} + LD=${LD:-${CROSS}${link_with_cc:-ld}} + AS=${AS:-${CROSS}as} + STRIP=${STRIP:-${CROSS}strip} + NM=${NM:-${CROSS}nm} + AS_SFX=.s + EXE_SFX= +} + +setup_clang_toolchain() { + CC=${CC:-${CROSS}clang} + CXX=${CXX:-${CROSS}clang++} + AR=${AR:-${CROSS}ar} + LD=${LD:-${CROSS}ld} + AS=${AS:-${CROSS}as} + STRIP=${STRIP:-${CROSS}strip} + NM=${NM:-${CROSS}nm} + AS_SFX=.s + EXE_SFX= +} + +# Reliably find the newest available Darwin SDKs. (Older versions of +# xcrun don't support --show-sdk-path.) +show_darwin_sdk_path() { + xcrun --sdk $1 --show-sdk-path 2>/dev/null || + xcodebuild -sdk $1 -version Path 2>/dev/null +} + +# Print the major version number of the Darwin SDK specified by $1. +show_darwin_sdk_major_version() { + xcrun --sdk $1 --show-sdk-version 2>/dev/null | cut -d. -f1 +} + +# Print the Xcode version. +show_xcode_version() { + xcodebuild -version | head -n1 | cut -d' ' -f2 +} + +# Fails when Xcode version is less than 6.3. +check_xcode_minimum_version() { + xcode_major=$(show_xcode_version | cut -f1 -d.) + xcode_minor=$(show_xcode_version | cut -f2 -d.) + xcode_min_major=6 + xcode_min_minor=3 + if [ ${xcode_major} -lt ${xcode_min_major} ]; then + return 1 + fi + if [ ${xcode_major} -eq ${xcode_min_major} ] \ + && [ ${xcode_minor} -lt ${xcode_min_minor} ]; then + return 1 + fi +} + +process_common_toolchain() { + if [ -z "$toolchain" ]; then + gcctarget="${CHOST:-$(gcc -dumpmachine 2> /dev/null)}" + + # detect tgt_isa + case "$gcctarget" in + aarch64*) + tgt_isa=arm64 + ;; + armv6*) + tgt_isa=armv6 + ;; + armv7*-hardfloat* | armv7*-gnueabihf | arm-*-gnueabihf) + tgt_isa=armv7 + float_abi=hard + ;; + armv7*) + tgt_isa=armv7 + float_abi=softfp + ;; + *x86_64*|*amd64*) + tgt_isa=x86_64 + ;; + *i[3456]86*) + tgt_isa=x86 + ;; + *sparc*) + tgt_isa=sparc + ;; + esac + + # detect tgt_os + case "$gcctarget" in + *darwin10*) + tgt_isa=x86_64 + tgt_os=darwin10 + ;; + *darwin11*) + tgt_isa=x86_64 + tgt_os=darwin11 + ;; + *darwin12*) + tgt_isa=x86_64 + tgt_os=darwin12 + ;; + *darwin13*) + tgt_isa=x86_64 + tgt_os=darwin13 + ;; + *darwin14*) + tgt_isa=x86_64 + tgt_os=darwin14 + ;; + *darwin15*) + tgt_isa=x86_64 + tgt_os=darwin15 + ;; + x86_64*mingw32*) + tgt_os=win64 + ;; + *mingw32*|*cygwin*) + [ -z "$tgt_isa" ] && tgt_isa=x86 + tgt_os=win32 + ;; + *linux*|*bsd*) + tgt_os=linux + ;; + *solaris2.10) + tgt_os=solaris + ;; + *os2*) + tgt_os=os2 + ;; + esac + + if [ -n "$tgt_isa" ] && [ -n "$tgt_os" ]; then + toolchain=${tgt_isa}-${tgt_os}-gcc + fi + fi + + toolchain=${toolchain:-generic-gnu} + + is_in ${toolchain} ${all_platforms} || enabled force_toolchain \ + || die "Unrecognized toolchain '${toolchain}'" + + enabled child || log_echo "Configuring for target '${toolchain}'" + + # + # Set up toolchain variables + # + tgt_isa=$(echo ${toolchain} | awk 'BEGIN{FS="-"}{print $1}') + tgt_os=$(echo ${toolchain} | awk 'BEGIN{FS="-"}{print $2}') + tgt_cc=$(echo ${toolchain} | awk 'BEGIN{FS="-"}{print $3}') + + # Mark the specific ISA requested as enabled + soft_enable ${tgt_isa} + enable_feature ${tgt_os} + enable_feature ${tgt_cc} + + # Enable the architecture family + case ${tgt_isa} in + arm*) + enable_feature arm + ;; + mips*) + enable_feature mips + ;; + esac + + # PIC is probably what we want when building shared libs + enabled shared && soft_enable pic + enabled orbis && soft_enable pic + + # Minimum iOS version for all target platforms (darwin and iphonesimulator). + # Shared library framework builds are only possible on iOS 8 and later. + if enabled shared; then + IOS_VERSION_OPTIONS="--enable-shared" + IOS_VERSION_MIN="8.0" + else + IOS_VERSION_OPTIONS="" + IOS_VERSION_MIN="6.0" + fi + + # Handle darwin variants. Newer SDKs allow targeting older + # platforms, so use the newest one available. + case ${toolchain} in + arm*-darwin*) + add_cflags "-miphoneos-version-min=${IOS_VERSION_MIN}" + iphoneos_sdk_dir="$(show_darwin_sdk_path iphoneos)" + if [ -d "${iphoneos_sdk_dir}" ]; then + add_cflags "-isysroot ${iphoneos_sdk_dir}" + add_ldflags "-isysroot ${iphoneos_sdk_dir}" + fi + ;; + x86*-darwin*) + osx_sdk_dir="$(show_darwin_sdk_path macosx)" + if [ -d "${osx_sdk_dir}" ]; then + add_cflags "-isysroot ${osx_sdk_dir}" + add_ldflags "-isysroot ${osx_sdk_dir}" + fi + ;; + esac + + case ${toolchain} in + *-darwin8-*) + add_cflags "-mmacosx-version-min=10.4" + add_ldflags "-mmacosx-version-min=10.4" + ;; + *-darwin9-*) + add_cflags "-mmacosx-version-min=10.5" + add_ldflags "-mmacosx-version-min=10.5" + ;; + *-darwin10-*) + add_cflags "-mmacosx-version-min=10.6" + add_ldflags "-mmacosx-version-min=10.6" + ;; + *-darwin11-*) + add_cflags "-mmacosx-version-min=10.7" + add_ldflags "-mmacosx-version-min=10.7" + ;; + *-darwin12-*) + add_cflags "-mmacosx-version-min=10.8" + add_ldflags "-mmacosx-version-min=10.8" + ;; + *-darwin13-*) + add_cflags "-mmacosx-version-min=10.9" + add_ldflags "-mmacosx-version-min=10.9" + ;; + *-darwin14-*) + add_cflags "-mmacosx-version-min=10.10" + add_ldflags "-mmacosx-version-min=10.10" + ;; + *-darwin15-*) + add_cflags "-mmacosx-version-min=10.11" + add_ldflags "-mmacosx-version-min=10.11" + ;; + *-iphonesimulator-*) + add_cflags "-miphoneos-version-min=${IOS_VERSION_MIN}" + add_ldflags "-miphoneos-version-min=${IOS_VERSION_MIN}" + iossim_sdk_dir="$(show_darwin_sdk_path iphonesimulator)" + if [ -d "${iossim_sdk_dir}" ]; then + add_cflags "-isysroot ${iossim_sdk_dir}" + add_ldflags "-isysroot ${iossim_sdk_dir}" + fi + ;; + esac + + # Handle Solaris variants. Solaris 10 needs -lposix4 + case ${toolchain} in + sparc-solaris-*) + add_extralibs -lposix4 + ;; + *-solaris-*) + add_extralibs -lposix4 + ;; + esac + + # Process ARM architecture variants + case ${toolchain} in + arm*) + # on arm, isa versions are supersets + case ${tgt_isa} in + arm64|armv8) + soft_enable neon + ;; + armv7|armv7s) + soft_enable neon + # Only enable neon_asm when neon is also enabled. + enabled neon && soft_enable neon_asm + # If someone tries to force it through, die. + if disabled neon && enabled neon_asm; then + die "Disabling neon while keeping neon-asm is not supported" + fi + case ${toolchain} in + # Apple iOS SDKs no longer support armv6 as of the version 9 + # release (coincides with release of Xcode 7). Only enable media + # when using earlier SDK releases. + *-darwin*) + if [ "$(show_darwin_sdk_major_version iphoneos)" -lt 9 ]; then + soft_enable media + else + soft_disable media + RTCD_OPTIONS="${RTCD_OPTIONS}--disable-media " + fi + ;; + *) + soft_enable media + ;; + esac + ;; + armv6) + case ${toolchain} in + *-darwin*) + if [ "$(show_darwin_sdk_major_version iphoneos)" -lt 9 ]; then + soft_enable media + else + die "Your iOS SDK does not support armv6." + fi + ;; + *) + soft_enable media + ;; + esac + ;; + esac + + asm_conversion_cmd="cat" + + case ${tgt_cc} in + gcc) + link_with_cc=gcc + setup_gnu_toolchain + arch_int=${tgt_isa##armv} + arch_int=${arch_int%%te} + check_add_asflags --defsym ARCHITECTURE=${arch_int} + tune_cflags="-mtune=" + if [ ${tgt_isa} = "armv7" ] || [ ${tgt_isa} = "armv7s" ]; then + if [ -z "${float_abi}" ]; then + check_cpp <<EOF && float_abi=hard || float_abi=softfp +#ifndef __ARM_PCS_VFP +#error "not hardfp" +#endif +EOF + fi + check_add_cflags -march=armv7-a -mfloat-abi=${float_abi} + check_add_asflags -march=armv7-a -mfloat-abi=${float_abi} + + if enabled neon || enabled neon_asm; then + check_add_cflags -mfpu=neon #-ftree-vectorize + check_add_asflags -mfpu=neon + fi + else + check_add_cflags -march=${tgt_isa} + check_add_asflags -march=${tgt_isa} + fi + + enabled debug && add_asflags -g + asm_conversion_cmd="${source_path}/build/make/ads2gas.pl" + if enabled thumb; then + asm_conversion_cmd="$asm_conversion_cmd -thumb" + check_add_cflags -mthumb + check_add_asflags -mthumb -mimplicit-it=always + fi + ;; + vs*) + asm_conversion_cmd="${source_path}/build/make/ads2armasm_ms.pl" + AS_SFX=.s + msvs_arch_dir=arm-msvs + disable_feature multithread + disable_feature unit_tests + vs_version=${tgt_cc##vs} + if [ $vs_version -ge 12 ]; then + # MSVC 2013 doesn't allow doing plain .exe projects for ARM, + # only "AppContainerApplication" which requires an AppxManifest. + # Therefore disable the examples, just build the library. + disable_feature examples + fi + ;; + rvct) + CC=armcc + AR=armar + AS=armasm + LD="${source_path}/build/make/armlink_adapter.sh" + STRIP=arm-none-linux-gnueabi-strip + NM=arm-none-linux-gnueabi-nm + tune_cflags="--cpu=" + tune_asflags="--cpu=" + if [ -z "${tune_cpu}" ]; then + if [ ${tgt_isa} = "armv7" ]; then + if enabled neon || enabled neon_asm + then + check_add_cflags --fpu=softvfp+vfpv3 + check_add_asflags --fpu=softvfp+vfpv3 + fi + check_add_cflags --cpu=Cortex-A8 + check_add_asflags --cpu=Cortex-A8 + else + check_add_cflags --cpu=${tgt_isa##armv} + check_add_asflags --cpu=${tgt_isa##armv} + fi + fi + arch_int=${tgt_isa##armv} + arch_int=${arch_int%%te} + check_add_asflags --pd "\"ARCHITECTURE SETA ${arch_int}\"" + enabled debug && add_asflags -g + add_cflags --gnu + add_cflags --enum_is_int + add_cflags --wchar32 + ;; + esac + + case ${tgt_os} in + none*) + disable_feature multithread + disable_feature os_support + ;; + + android*) + SDK_PATH=${sdk_path} + COMPILER_LOCATION=`find "${SDK_PATH}" \ + -name "arm-linux-androideabi-gcc*" -print -quit` + TOOLCHAIN_PATH=${COMPILER_LOCATION%/*}/arm-linux-androideabi- + CC=${TOOLCHAIN_PATH}gcc + CXX=${TOOLCHAIN_PATH}g++ + AR=${TOOLCHAIN_PATH}ar + LD=${TOOLCHAIN_PATH}gcc + AS=${TOOLCHAIN_PATH}as + STRIP=${TOOLCHAIN_PATH}strip + NM=${TOOLCHAIN_PATH}nm + + if [ -z "${alt_libc}" ]; then + alt_libc=`find "${SDK_PATH}" -name arch-arm -print | \ + awk '{n = split($0,a,"/"); \ + split(a[n-1],b,"-"); \ + print $0 " " b[2]}' | \ + sort -g -k 2 | \ + awk '{ print $1 }' | tail -1` + fi + + if [ -d "${alt_libc}" ]; then + add_cflags "--sysroot=${alt_libc}" + add_ldflags "--sysroot=${alt_libc}" + fi + + # linker flag that routes around a CPU bug in some + # Cortex-A8 implementations (NDK Dev Guide) + add_ldflags "-Wl,--fix-cortex-a8" + + enable_feature pic + soft_enable realtime_only + if [ ${tgt_isa} = "armv7" ]; then + soft_enable runtime_cpu_detect + fi + if enabled runtime_cpu_detect; then + add_cflags "-I${SDK_PATH}/sources/android/cpufeatures" + fi + ;; + + darwin*) + XCRUN_FIND="xcrun --sdk iphoneos --find" + CXX="$(${XCRUN_FIND} clang++)" + CC="$(${XCRUN_FIND} clang)" + AR="$(${XCRUN_FIND} ar)" + AS="$(${XCRUN_FIND} as)" + STRIP="$(${XCRUN_FIND} strip)" + NM="$(${XCRUN_FIND} nm)" + RANLIB="$(${XCRUN_FIND} ranlib)" + AS_SFX=.s + LD="${CXX:-$(${XCRUN_FIND} ld)}" + + # ASFLAGS is written here instead of using check_add_asflags + # because we need to overwrite all of ASFLAGS and purge the + # options that were put in above + ASFLAGS="-arch ${tgt_isa} -g" + + add_cflags -arch ${tgt_isa} + add_ldflags -arch ${tgt_isa} + + alt_libc="$(show_darwin_sdk_path iphoneos)" + if [ -d "${alt_libc}" ]; then + add_cflags -isysroot ${alt_libc} + fi + + if [ "${LD}" = "${CXX}" ]; then + add_ldflags -miphoneos-version-min="${IOS_VERSION_MIN}" + else + add_ldflags -ios_version_min "${IOS_VERSION_MIN}" + fi + + for d in lib usr/lib usr/lib/system; do + try_dir="${alt_libc}/${d}" + [ -d "${try_dir}" ] && add_ldflags -L"${try_dir}" + done + + case ${tgt_isa} in + armv7|armv7s|armv8|arm64) + if enabled neon && ! check_xcode_minimum_version; then + soft_disable neon + log_echo " neon disabled: upgrade Xcode (need v6.3+)." + if enabled neon_asm; then + soft_disable neon_asm + log_echo " neon_asm disabled: upgrade Xcode (need v6.3+)." + fi + fi + ;; + esac + + asm_conversion_cmd="${source_path}/build/make/ads2gas_apple.pl" + + if [ "$(show_darwin_sdk_major_version iphoneos)" -gt 8 ]; then + check_add_cflags -fembed-bitcode + check_add_asflags -fembed-bitcode + check_add_ldflags -fembed-bitcode + fi + ;; + + linux*) + enable_feature linux + if enabled rvct; then + # Check if we have CodeSourcery GCC in PATH. Needed for + # libraries + which arm-none-linux-gnueabi-gcc 2>&- || \ + die "Couldn't find CodeSourcery GCC from PATH" + + # Use armcc as a linker to enable translation of + # some gcc specific options such as -lm and -lpthread. + LD="armcc --translate_gcc" + + # create configuration file (uses path to CodeSourcery GCC) + armcc --arm_linux_configure --arm_linux_config_file=arm_linux.cfg + + add_cflags --arm_linux_paths --arm_linux_config_file=arm_linux.cfg + add_asflags --no_hide_all --apcs=/interwork + add_ldflags --arm_linux_paths --arm_linux_config_file=arm_linux.cfg + enabled pic && add_cflags --apcs=/fpic + enabled pic && add_asflags --apcs=/fpic + enabled shared && add_cflags --shared + fi + ;; + esac + ;; + mips*) + link_with_cc=gcc + setup_gnu_toolchain + tune_cflags="-mtune=" + if enabled dspr2; then + check_add_cflags -mips32r2 -mdspr2 + fi + + if enabled runtime_cpu_detect; then + disable_feature runtime_cpu_detect + fi + + if [ -n "${tune_cpu}" ]; then + case ${tune_cpu} in + p5600) + check_add_cflags -mips32r5 -funroll-loops -mload-store-pairs + check_add_cflags -msched-weight -mhard-float -mfp64 + check_add_asflags -mips32r5 -mhard-float -mfp64 + check_add_ldflags -mfp64 + ;; + i6400) + check_add_cflags -mips64r6 -mabi=64 -funroll-loops -msched-weight + check_add_cflags -mload-store-pairs -mhard-float -mfp64 + check_add_asflags -mips64r6 -mabi=64 -mhard-float -mfp64 + check_add_ldflags -mips64r6 -mabi=64 -mfp64 + ;; + esac + + if enabled msa; then + add_cflags -mmsa + add_asflags -mmsa + add_ldflags -mmsa + fi + fi + + check_add_cflags -march=${tgt_isa} + check_add_asflags -march=${tgt_isa} + check_add_asflags -KPIC + ;; + x86*) + case ${tgt_os} in + win*) + enabled gcc && add_cflags -fno-common + ;; + solaris*) + CC=${CC:-${CROSS}gcc} + CXX=${CXX:-${CROSS}g++} + LD=${LD:-${CROSS}gcc} + CROSS=${CROSS-g} + ;; + os2) + disable_feature pic + AS=${AS:-nasm} + add_ldflags -Zhigh-mem + ;; + orbis) + CROSS=${CROSS:-orbis-} + ;; + esac + + AS="${alt_as:-${AS:-auto}}" + case ${tgt_cc} in + icc*) + CC=${CC:-icc} + LD=${LD:-icc} + setup_gnu_toolchain + add_cflags -use-msasm # remove -use-msasm too? + # add -no-intel-extensions to suppress warning #10237 + # refer to http://software.intel.com/en-us/forums/topic/280199 + add_ldflags -i-static -no-intel-extensions + enabled x86_64 && add_cflags -ipo -static -O3 -no-prec-div + enabled x86_64 && AR=xiar + case ${tune_cpu} in + atom*) + tune_cflags="-x" + tune_cpu="SSE3_ATOM" + ;; + *) + tune_cflags="-march=" + ;; + esac + ;; + gcc*) + link_with_cc=gcc + tune_cflags="-march=" + setup_gnu_toolchain + #for 32 bit x86 builds, -O3 did not turn on this flag + enabled optimizations && disabled gprof && check_add_cflags -fomit-frame-pointer + ;; + clang*) + link_with_cc=clang + tune_cflags="-march=" + setup_clang_toolchain + ;; + vs*) + # When building with Microsoft Visual Studio the assembler is + # invoked directly. Checking at configure time is unnecessary. + # Skip the check by setting AS arbitrarily + AS=msvs + msvs_arch_dir=x86-msvs + vc_version=${tgt_cc##vs} + case $vc_version in + 7|8|9|10) + echo "${tgt_cc} does not support avx/avx2, disabling....." + RTCD_OPTIONS="${RTCD_OPTIONS}--disable-avx --disable-avx2 " + soft_disable avx + soft_disable avx2 + ;; + esac + case $vc_version in + 7|8|9) + echo "${tgt_cc} omits stdint.h, disabling webm-io..." + soft_disable webm_io + ;; + esac + ;; + esac + + bits=32 + enabled x86_64 && bits=64 + check_cpp <<EOF && bits=x32 +#if !defined(__ILP32__) || !defined(__x86_64__) +#error "not x32" +#endif +EOF + case ${tgt_cc} in + gcc*) + add_cflags -m${bits} + add_ldflags -m${bits} + ;; + esac + + disabled orbis && soft_enable runtime_cpu_detect + # We can't use 'check_cflags' until the compiler is configured and CC is + # populated. + for ext in ${ARCH_EXT_LIST_X86}; do + # disable higher order extensions to simplify asm dependencies + if [ "$disable_exts" = "yes" ]; then + if ! disabled $ext; then + RTCD_OPTIONS="${RTCD_OPTIONS}--disable-${ext} " + disable_feature $ext + fi + elif disabled $ext; then + disable_exts="yes" + elif [ "$ext" = "avx2" ]; then + # on orbis never enable avx2. + disabled orbis && check_gcc_machine_option ${ext%_*} $ext + else + # use the shortened version for the flag: sse4_1 -> sse4 + check_gcc_machine_option ${ext%_*} $ext + fi + done + + if enabled external_build; then + log_echo " skipping assembler detection" + else + case "${AS}" in + auto|"") + which nasm >/dev/null 2>&1 && AS=nasm + which yasm >/dev/null 2>&1 && AS=yasm + if [ "${AS}" = nasm ] ; then + # Apple ships version 0.98 of nasm through at least Xcode 6. Revisit + # this check if they start shipping a compatible version. + apple=`nasm -v | grep "Apple"` + [ -n "${apple}" ] \ + && echo "Unsupported version of nasm: ${apple}" \ + && AS="" + fi + [ "${AS}" = auto ] || [ -z "${AS}" ] \ + && die "Neither yasm nor nasm have been found." \ + "See the prerequisites section in the README for more info." + ;; + esac + log_echo " using $AS" + fi + [ "${AS##*/}" = nasm ] && add_asflags -Ox + AS_SFX=.asm + case ${tgt_os} in + win32) + add_asflags -f win32 + enabled debug && add_asflags -g cv8 + EXE_SFX=.exe + ;; + win64) + add_asflags -f x64 + enabled debug && add_asflags -g cv8 + EXE_SFX=.exe + ;; + linux*|solaris*|android*) + add_asflags -f elf${bits} + enabled debug && [ "${AS}" = yasm ] && add_asflags -g dwarf2 + enabled debug && [ "${AS}" = nasm ] && add_asflags -g + [ "${AS##*/}" = nasm ] && check_asm_align + ;; + darwin*) + add_asflags -f macho${bits} + enabled x86 && darwin_arch="-arch i386" || darwin_arch="-arch x86_64" + add_cflags ${darwin_arch} + add_ldflags ${darwin_arch} + # -mdynamic-no-pic is still a bit of voodoo -- it was required at + # one time, but does not seem to be now, and it breaks some of the + # code that still relies on inline assembly. + # enabled icc && ! enabled pic && add_cflags -fno-pic -mdynamic-no-pic + enabled icc && ! enabled pic && add_cflags -fno-pic + ;; + iphonesimulator) + add_asflags -f macho${bits} + enabled x86 && sim_arch="-arch i386" || sim_arch="-arch x86_64" + add_cflags ${sim_arch} + add_ldflags ${sim_arch} + + if [ "$(show_darwin_sdk_major_version iphonesimulator)" -gt 8 ]; then + # yasm v1.3.0 doesn't know what -fembed-bitcode means, so turning it + # on is pointless (unless building a C-only lib). Warn the user, but + # do nothing here. + log "Warning: Bitcode embed disabled for simulator targets." + fi + ;; + os2) + add_asflags -f aout + enabled debug && add_asflags -g + EXE_SFX=.exe + ;; + orbis*) + add_asflags -f elf${bits} + enabled debug && [ "${AS}" = yasm ] && add_asflags -g dwarf2 + enabled debug && [ "${AS}" = nasm ] && add_asflags -g + [ "${AS##*/}" = nasm ] && check_asm_align + add_ldflags "-L\"${SCE_ORBIS_SDK_DIR}/target/lib/\"" + add_ldflags "-Wl,--fself-flags=videoservice" + add_ldflags "-Wl,--target=orbis" + add_ldflags "-Wl,-lc_stub_weak" + add_ldflags "-Wl,-lkernel_stub_weak" + add_ldflags "-Wl,-lScePosix_stub_weak" + EXE_SFX=.elf + disable_feature os_support + soft_disable avx2 + RTCD_OPTIONS="${RTCD_OPTIONS}--disable-avx2 " + ;; + *) + log "Warning: Unknown os $tgt_os while setting up $AS flags" + ;; + esac + ;; + *-gcc|generic-gnu) + link_with_cc=gcc + enable_feature gcc + setup_gnu_toolchain + ;; + esac + + # Try to enable CPU specific tuning + if [ -n "${tune_cpu}" ]; then + if [ -n "${tune_cflags}" ]; then + check_add_cflags ${tune_cflags}${tune_cpu} || \ + die "Requested CPU '${tune_cpu}' not supported by compiler" + fi + if [ -n "${tune_asflags}" ]; then + check_add_asflags ${tune_asflags}${tune_cpu} || \ + die "Requested CPU '${tune_cpu}' not supported by assembler" + fi + if [ -z "${tune_cflags}${tune_asflags}" ]; then + log_echo "Warning: CPU tuning not supported by this toolchain" + fi + fi + + if enabled debug; then + check_add_cflags -g && check_add_ldflags -g + else + check_add_cflags -DNDEBUG + fi + + enabled gprof && check_add_cflags -pg && check_add_ldflags -pg + enabled gcov && + check_add_cflags -fprofile-arcs -ftest-coverage && + check_add_ldflags -fprofile-arcs -ftest-coverage + + if enabled optimizations; then + if enabled rvct; then + enabled small && check_add_cflags -Ospace || check_add_cflags -Otime + else + enabled small && check_add_cflags -O2 || check_add_cflags -O3 + fi + fi + + if [ "${tgt_isa}" = "x86_64" ] || [ "${tgt_isa}" = "x86" ]; then + soft_enable use_x86inc + fi + + # Position Independent Code (PIC) support, for building relocatable + # shared objects + enabled gcc && enabled pic && check_add_cflags -fPIC + + # Work around longjmp interception on glibc >= 2.11, to improve binary + # compatibility. See http://code.google.com/p/webm/issues/detail?id=166 + enabled linux && check_add_cflags -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 + + # Check for strip utility variant + ${STRIP} -V 2>/dev/null | grep GNU >/dev/null && enable_feature gnu_strip + + # Try to determine target endianness + check_cc <<EOF +unsigned int e = 'O'<<24 | '2'<<16 | 'B'<<8 | 'E'; +EOF + [ -f "${TMP_O}" ] && od -A n -t x1 "${TMP_O}" | tr -d '\n' | + grep '4f *32 *42 *45' >/dev/null 2>&1 && enable_feature big_endian + + # Try to find which inline keywords are supported + check_cc <<EOF && INLINE="inline" +static inline function() {} +EOF + + # Almost every platform uses pthreads. + if enabled multithread; then + case ${toolchain} in + *-win*-vs*) + ;; + *-android-gcc) + ;; + *orbis*) + ;; + *) + check_header pthread.h && add_extralibs -lpthread + ;; + esac + fi + + # only for MIPS platforms + case ${toolchain} in + mips*) + if enabled big_endian; then + if enabled dspr2; then + echo "dspr2 optimizations are available only for little endian platforms" + disable_feature dspr2 + fi + if enabled msa; then + echo "msa optimizations are available only for little endian platforms" + disable_feature msa + fi + fi + ;; + esac + + # glibc needs these + if enabled linux; then + add_cflags -D_LARGEFILE_SOURCE + add_cflags -D_FILE_OFFSET_BITS=64 + fi +} + +process_toolchain() { + process_common_toolchain +} + +print_config_mk() { + saved_prefix="${prefix}" + prefix=$1 + makefile=$2 + shift 2 + for cfg; do + if enabled $cfg; then + upname="`toupper $cfg`" + echo "${prefix}_${upname}=yes" >> $makefile + fi + done + prefix="${saved_prefix}" +} + +print_config_h() { + saved_prefix="${prefix}" + prefix=$1 + header=$2 + shift 2 + for cfg; do + upname="`toupper $cfg`" + if enabled $cfg; then + echo "#define ${prefix}_${upname} 1" >> $header + else + echo "#define ${prefix}_${upname} 0" >> $header + fi + done + prefix="${saved_prefix}" +} + +print_config_vars_h() { + header=$1 + shift + while [ $# -gt 0 ]; do + upname="`toupper $1`" + echo "#define ${upname} $2" >> $header + shift 2 + done +} + +print_webm_license() { + saved_prefix="${prefix}" + destination=$1 + prefix="$2" + suffix="$3" + shift 3 + cat <<EOF > ${destination} +${prefix} Copyright (c) 2011 The WebM project authors. All Rights Reserved.${suffix} +${prefix} ${suffix} +${prefix} Use of this source code is governed by a BSD-style license${suffix} +${prefix} that can be found in the LICENSE file in the root of the source${suffix} +${prefix} tree. An additional intellectual property rights grant can be found${suffix} +${prefix} in the file PATENTS. All contributing project authors may${suffix} +${prefix} be found in the AUTHORS file in the root of the source tree.${suffix} +EOF + prefix="${saved_prefix}" +} + +process_targets() { + true; +} + +process_detect() { + true; +} + +enable_feature logging +logfile="config.log" +self=$0 +process() { + cmdline_args="$@" + process_cmdline "$@" + if enabled child; then + echo "# ${self} $@" >> ${logfile} + else + echo "# ${self} $@" > ${logfile} + fi + post_process_common_cmdline + post_process_cmdline + process_toolchain + process_detect + process_targets + + OOT_INSTALLS="${OOT_INSTALLS}" + if enabled source_path_used; then + # Prepare the PWD for building. + for f in ${OOT_INSTALLS}; do + install -D "${source_path}/$f" "$f" + done + fi + cp "${source_path}/build/make/Makefile" . + + clean_temp_files + true +}
diff --git a/src/third_party/libvpx/build/make/gen_asm_deps.sh b/src/third_party/libvpx/build/make/gen_asm_deps.sh new file mode 100755 index 0000000..6a7bff9 --- /dev/null +++ b/src/third_party/libvpx/build/make/gen_asm_deps.sh
@@ -0,0 +1,64 @@ +#!/bin/sh +## +## Copyright (c) 2010 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## + + +self=$0 +show_help() { + echo "usage: $self [options] <srcfile>" + echo + echo "Generate Makefile dependency information from assembly code source" + echo + exit 1 +} +die_unknown(){ + echo "Unknown option \"$1\"." + echo "See $0 --help for available options." + exit 1 +} +for opt do + optval="${opt#*=}" + case "$opt" in + --build-pfx=*) pfx="${optval}" + ;; + --depfile=*) out="${optval}" + ;; + -I*) raw_inc_paths="${raw_inc_paths} ${opt}" + inc_path="${inc_path} ${opt#-I}" + ;; + -h|--help) show_help + ;; + *) [ -f "$opt" ] && srcfile="$opt" + ;; + esac +done + +[ -n "$srcfile" ] || show_help +sfx=${sfx:-asm} +includes=$(LC_ALL=C egrep -i "include +\"?[a-z0-9_/]+\.${sfx}" $srcfile | + perl -p -e "s;.*?([a-z0-9_/]+.${sfx}).*;\1;") +#" restore editor state +for inc in ${includes}; do + found_inc_path= + for idir in ${inc_path}; do + [ -f "${idir}/${inc}" ] && found_inc_path="${idir}" && break + done + if [ -f `dirname $srcfile`/$inc ]; then + # Handle include files in the same directory as the source + $self --build-pfx=$pfx --depfile=$out ${raw_inc_paths} `dirname $srcfile`/$inc + elif [ -n "${found_inc_path}" ]; then + # Handle include files on the include path + $self --build-pfx=$pfx --depfile=$out ${raw_inc_paths} "${found_inc_path}/$inc" + else + # Handle generated includes in the build root (which may not exist yet) + echo ${out} ${out%d}o: "${pfx}${inc}" + fi +done +echo ${out} ${out%d}o: $srcfile
diff --git a/src/third_party/libvpx/build/make/gen_msvs_def.sh b/src/third_party/libvpx/build/make/gen_msvs_def.sh new file mode 100755 index 0000000..4defcc2 --- /dev/null +++ b/src/third_party/libvpx/build/make/gen_msvs_def.sh
@@ -0,0 +1,83 @@ +#!/bin/bash +## +## Copyright (c) 2010 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## + + +self=$0 +self_basename=${self##*/} +EOL=$'\n' + +show_help() { + cat <<EOF +Usage: ${self_basename} [options] file1 [file2 ...] + +This script generates a MSVC module definition file containing a list of symbols +to export from a DLL. Source files are technically bash scripts (and thus may +use #comment syntax) but in general, take the form of a list of symbols: + + <kind> symbol1 [symbol2, symbol3, ...] + +where <kind> is either 'text' or 'data' + + +Options: + --help Print this message + --out=filename Write output to a file [stdout] + --name=project_name Name of the library (required) +EOF + exit 1 +} + +die() { + echo "${self_basename}: $@" + exit 1 +} + +die_unknown(){ + echo "Unknown option \"$1\"." + echo "See ${self_basename} --help for available options." + exit 1 +} + +text() { + for sym in "$@"; do + echo " $sym" >> ${outfile} + done +} + +data() { + for sym in "$@"; do + printf " %-40s DATA\n" "$sym" >> ${outfile} + done +} + +# Process command line +for opt in "$@"; do + optval="${opt#*=}" + case "$opt" in + --help|-h) show_help + ;; + --out=*) outfile="$optval" + ;; + --name=*) name="${optval}" + ;; + -*) die_unknown $opt + ;; + *) file_list[${#file_list[@]}]="$opt" + esac +done +outfile=${outfile:-/dev/stdout} +[ -n "$name" ] || die "Library name (--name) must be specified!" + +echo "LIBRARY ${name}" > ${outfile} +echo "EXPORTS" >> ${outfile} +for f in "${file_list[@]}"; do + . $f +done
diff --git a/src/third_party/libvpx/build/make/gen_msvs_proj.sh b/src/third_party/libvpx/build/make/gen_msvs_proj.sh new file mode 100755 index 0000000..2b91fbf --- /dev/null +++ b/src/third_party/libvpx/build/make/gen_msvs_proj.sh
@@ -0,0 +1,490 @@ +#!/bin/bash +## +## Copyright (c) 2010 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## + +self=$0 +self_basename=${self##*/} +self_dirname=$(dirname "$0") + +. "$self_dirname/msvs_common.sh"|| exit 127 + +show_help() { + cat <<EOF +Usage: ${self_basename} --name=projname [options] file1 [file2 ...] + +This script generates a Visual Studio project file from a list of source +code files. + +Options: + --help Print this message + --exe Generate a project for building an Application + --lib Generate a project for creating a static library + --dll Generate a project for creating a dll + --static-crt Use the static C runtime (/MT) + --target=isa-os-cc Target specifier (required) + --out=filename Write output to a file [stdout] + --name=project_name Name of the project (required) + --proj-guid=GUID GUID to use for the project + --module-def=filename File containing export definitions (for DLLs) + --ver=version Version (7,8,9) of visual studio to generate for + --src-path-bare=dir Path to root of source tree + -Ipath/to/include Additional include directories + -DFLAG[=value] Preprocessor macros to define + -Lpath/to/lib Additional library search paths + -llibname Library to link against +EOF + exit 1 +} + +generate_filter() { + local var=$1 + local name=$2 + local pats=$3 + local file_list_sz + local i + local f + local saveIFS="$IFS" + local pack + echo "generating filter '$name' from ${#file_list[@]} files" >&2 + IFS=* + + open_tag Filter \ + Name=$name \ + Filter=$pats \ + UniqueIdentifier=`generate_uuid` \ + + file_list_sz=${#file_list[@]} + for i in ${!file_list[@]}; do + f=${file_list[i]} + for pat in ${pats//;/$IFS}; do + if [ "${f##*.}" == "$pat" ]; then + unset file_list[i] + + objf=$(echo ${f%.*}.obj \ + | sed -e "s,$src_path_bare,," \ + -e 's/^[\./]\+//g' -e 's,[:/ ],_,g') + open_tag File RelativePath="$f" + + if [ "$pat" == "asm" ] && $asm_use_custom_step; then + # Avoid object file name collisions, i.e. vpx_config.c and + # vpx_config.asm produce the same object file without + # this additional suffix. + objf=${objf%.obj}_asm.obj + for plat in "${platforms[@]}"; do + for cfg in Debug Release; do + open_tag FileConfiguration \ + Name="${cfg}|${plat}" \ + + tag Tool \ + Name="VCCustomBuildTool" \ + Description="Assembling \$(InputFileName)" \ + CommandLine="$(eval echo \$asm_${cfg}_cmdline) -o \$(IntDir)\\$objf" \ + Outputs="\$(IntDir)\\$objf" \ + + close_tag FileConfiguration + done + done + fi + if [ "$pat" == "c" ] || \ + [ "$pat" == "cc" ] || [ "$pat" == "cpp" ]; then + for plat in "${platforms[@]}"; do + for cfg in Debug Release; do + open_tag FileConfiguration \ + Name="${cfg}|${plat}" \ + + tag Tool \ + Name="VCCLCompilerTool" \ + ObjectFile="\$(IntDir)\\$objf" \ + + close_tag FileConfiguration + done + done + fi + close_tag File + + break + fi + done + done + + close_tag Filter + IFS="$saveIFS" +} + +# Process command line +unset target +for opt in "$@"; do + optval="${opt#*=}" + case "$opt" in + --help|-h) show_help + ;; + --target=*) target="${optval}" + ;; + --out=*) outfile="$optval" + ;; + --name=*) name="${optval}" + ;; + --proj-guid=*) guid="${optval}" + ;; + --module-def=*) link_opts="${link_opts} ModuleDefinitionFile=${optval}" + ;; + --exe) proj_kind="exe" + ;; + --dll) proj_kind="dll" + ;; + --lib) proj_kind="lib" + ;; + --src-path-bare=*) + src_path_bare=$(fix_path "$optval") + src_path_bare=${src_path_bare%/} + ;; + --static-crt) use_static_runtime=true + ;; + --ver=*) + vs_ver="$optval" + case "$optval" in + [789]) + ;; + *) die Unrecognized Visual Studio Version in $opt + ;; + esac + ;; + -I*) + opt=${opt##-I} + opt=$(fix_path "$opt") + opt="${opt%/}" + incs="${incs}${incs:+;}"${opt}"" + yasmincs="${yasmincs} -I"${opt}"" + ;; + -D*) defines="${defines}${defines:+;}${opt##-D}" + ;; + -L*) # fudge . to $(OutDir) + if [ "${opt##-L}" == "." ]; then + libdirs="${libdirs}${libdirs:+;}"\$(OutDir)"" + else + # Also try directories for this platform/configuration + opt=${opt##-L} + opt=$(fix_path "$opt") + libdirs="${libdirs}${libdirs:+;}"${opt}"" + libdirs="${libdirs}${libdirs:+;}"${opt}/\$(PlatformName)/\$(ConfigurationName)"" + libdirs="${libdirs}${libdirs:+;}"${opt}/\$(PlatformName)"" + fi + ;; + -l*) libs="${libs}${libs:+ }${opt##-l}.lib" + ;; + -*) die_unknown $opt + ;; + *) + # The paths in file_list are fixed outside of the loop. + file_list[${#file_list[@]}]="$opt" + case "$opt" in + *.asm) uses_asm=true + ;; + esac + ;; + esac +done + +# Make one call to fix_path for file_list to improve performance. +fix_file_list file_list + +outfile=${outfile:-/dev/stdout} +guid=${guid:-`generate_uuid`} +asm_use_custom_step=false +uses_asm=${uses_asm:-false} +case "${vs_ver:-8}" in + 7) vs_ver_id="7.10" + asm_use_custom_step=$uses_asm + warn_64bit='Detect64BitPortabilityProblems=true' + ;; + 8) vs_ver_id="8.00" + asm_use_custom_step=$uses_asm + warn_64bit='Detect64BitPortabilityProblems=true' + ;; + 9) vs_ver_id="9.00" + asm_use_custom_step=$uses_asm + warn_64bit='Detect64BitPortabilityProblems=false' + ;; +esac + +[ -n "$name" ] || die "Project name (--name) must be specified!" +[ -n "$target" ] || die "Target (--target) must be specified!" + +if ${use_static_runtime:-false}; then + release_runtime=0 + debug_runtime=1 + lib_sfx=mt +else + release_runtime=2 + debug_runtime=3 + lib_sfx=md +fi + +# Calculate debug lib names: If a lib ends in ${lib_sfx}.lib, then rename +# it to ${lib_sfx}d.lib. This precludes linking to release libs from a +# debug exe, so this may need to be refactored later. +for lib in ${libs}; do + if [ "$lib" != "${lib%${lib_sfx}.lib}" ]; then + lib=${lib%.lib}d.lib + fi + debug_libs="${debug_libs}${debug_libs:+ }${lib}" +done + + +# List Keyword for this target +case "$target" in + x86*) keyword="ManagedCProj" + ;; + *) die "Unsupported target $target!" +esac + +# List of all platforms supported for this target +case "$target" in + x86_64*) + platforms[0]="x64" + asm_Debug_cmdline="yasm -Xvc -g cv8 -f win64 ${yasmincs} "\$(InputPath)"" + asm_Release_cmdline="yasm -Xvc -f win64 ${yasmincs} "\$(InputPath)"" + ;; + x86*) + platforms[0]="Win32" + asm_Debug_cmdline="yasm -Xvc -g cv8 -f win32 ${yasmincs} "\$(InputPath)"" + asm_Release_cmdline="yasm -Xvc -f win32 ${yasmincs} "\$(InputPath)"" + ;; + *) die "Unsupported target $target!" + ;; +esac + +generate_vcproj() { + case "$proj_kind" in + exe) vs_ConfigurationType=1 + ;; + dll) vs_ConfigurationType=2 + ;; + *) vs_ConfigurationType=4 + ;; + esac + + echo "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>" + open_tag VisualStudioProject \ + ProjectType="Visual C++" \ + Version="${vs_ver_id}" \ + Name="${name}" \ + ProjectGUID="{${guid}}" \ + RootNamespace="${name}" \ + Keyword="${keyword}" \ + + open_tag Platforms + for plat in "${platforms[@]}"; do + tag Platform Name="$plat" + done + close_tag Platforms + + open_tag Configurations + for plat in "${platforms[@]}"; do + plat_no_ws=`echo $plat | sed 's/[^A-Za-z0-9_]/_/g'` + open_tag Configuration \ + Name="Debug|$plat" \ + OutputDirectory="\$(SolutionDir)$plat_no_ws/\$(ConfigurationName)" \ + IntermediateDirectory="$plat_no_ws/\$(ConfigurationName)/${name}" \ + ConfigurationType="$vs_ConfigurationType" \ + CharacterSet="1" \ + + case "$target" in + x86*) + case "$name" in + vpx) + tag Tool \ + Name="VCCLCompilerTool" \ + Optimization="0" \ + AdditionalIncludeDirectories="$incs" \ + PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \ + RuntimeLibrary="$debug_runtime" \ + UsePrecompiledHeader="0" \ + WarningLevel="3" \ + DebugInformationFormat="2" \ + $warn_64bit \ + + $uses_asm && tag Tool Name="YASM" IncludePaths="$incs" Debug="true" + ;; + *) + tag Tool \ + Name="VCCLCompilerTool" \ + Optimization="0" \ + AdditionalIncludeDirectories="$incs" \ + PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \ + RuntimeLibrary="$debug_runtime" \ + UsePrecompiledHeader="0" \ + WarningLevel="3" \ + DebugInformationFormat="2" \ + $warn_64bit \ + + $uses_asm && tag Tool Name="YASM" IncludePaths="$incs" Debug="true" + ;; + esac + ;; + esac + + case "$proj_kind" in + exe) + case "$target" in + x86*) + case "$name" in + *) + tag Tool \ + Name="VCLinkerTool" \ + AdditionalDependencies="$debug_libs \$(NoInherit)" \ + AdditionalLibraryDirectories="$libdirs" \ + GenerateDebugInformation="true" \ + ProgramDatabaseFile="\$(OutDir)/${name}.pdb" \ + ;; + esac + ;; + esac + ;; + lib) + case "$target" in + x86*) + tag Tool \ + Name="VCLibrarianTool" \ + OutputFile="\$(OutDir)/${name}${lib_sfx}d.lib" \ + + ;; + esac + ;; + dll) + tag Tool \ + Name="VCLinkerTool" \ + AdditionalDependencies="\$(NoInherit)" \ + LinkIncremental="2" \ + GenerateDebugInformation="true" \ + AssemblyDebug="1" \ + TargetMachine="1" \ + $link_opts \ + + ;; + esac + + close_tag Configuration + + open_tag Configuration \ + Name="Release|$plat" \ + OutputDirectory="\$(SolutionDir)$plat_no_ws/\$(ConfigurationName)" \ + IntermediateDirectory="$plat_no_ws/\$(ConfigurationName)/${name}" \ + ConfigurationType="$vs_ConfigurationType" \ + CharacterSet="1" \ + WholeProgramOptimization="0" \ + + case "$target" in + x86*) + case "$name" in + vpx) + tag Tool \ + Name="VCCLCompilerTool" \ + Optimization="2" \ + FavorSizeorSpeed="1" \ + AdditionalIncludeDirectories="$incs" \ + PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \ + RuntimeLibrary="$release_runtime" \ + UsePrecompiledHeader="0" \ + WarningLevel="3" \ + DebugInformationFormat="0" \ + $warn_64bit \ + + $uses_asm && tag Tool Name="YASM" IncludePaths="$incs" + ;; + *) + tag Tool \ + Name="VCCLCompilerTool" \ + AdditionalIncludeDirectories="$incs" \ + Optimization="2" \ + FavorSizeorSpeed="1" \ + PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \ + RuntimeLibrary="$release_runtime" \ + UsePrecompiledHeader="0" \ + WarningLevel="3" \ + DebugInformationFormat="0" \ + $warn_64bit \ + + $uses_asm && tag Tool Name="YASM" IncludePaths="$incs" + ;; + esac + ;; + esac + + case "$proj_kind" in + exe) + case "$target" in + x86*) + case "$name" in + *) + tag Tool \ + Name="VCLinkerTool" \ + AdditionalDependencies="$libs \$(NoInherit)" \ + AdditionalLibraryDirectories="$libdirs" \ + + ;; + esac + ;; + esac + ;; + lib) + case "$target" in + x86*) + tag Tool \ + Name="VCLibrarianTool" \ + OutputFile="\$(OutDir)/${name}${lib_sfx}.lib" \ + + ;; + esac + ;; + dll) # note differences to debug version: LinkIncremental, AssemblyDebug + tag Tool \ + Name="VCLinkerTool" \ + AdditionalDependencies="\$(NoInherit)" \ + LinkIncremental="1" \ + GenerateDebugInformation="true" \ + TargetMachine="1" \ + $link_opts \ + + ;; + esac + + close_tag Configuration + done + close_tag Configurations + + open_tag Files + generate_filter srcs "Source Files" "c;cc;cpp;def;odl;idl;hpj;bat;asm;asmx" + generate_filter hdrs "Header Files" "h;hm;inl;inc;xsd" + generate_filter resrcs "Resource Files" "rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav" + generate_filter resrcs "Build Files" "mk" + close_tag Files + + tag Globals + close_tag VisualStudioProject + + # This must be done from within the {} subshell + echo "Ignored files list (${#file_list[@]} items) is:" >&2 + for f in "${file_list[@]}"; do + echo " $f" >&2 + done +} + +generate_vcproj | + sed -e '/"/s;\([^ "]\)/;\1\\;g' > ${outfile} + +exit +<!-- +TODO: Add any files not captured by filters. + <File + RelativePath=".\ReadMe.txt" + > + </File> +-->
diff --git a/src/third_party/libvpx/build/make/gen_msvs_sln.sh b/src/third_party/libvpx/build/make/gen_msvs_sln.sh new file mode 100755 index 0000000..664b404 --- /dev/null +++ b/src/third_party/libvpx/build/make/gen_msvs_sln.sh
@@ -0,0 +1,327 @@ +#!/bin/bash +## +## Copyright (c) 2010 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## + + +self=$0 +self_basename=${self##*/} +EOL=$'\n' +EOLDOS=$'\r' + +show_help() { + cat <<EOF +Usage: ${self_basename} [options] file1 [file2 ...] + +This script generates a Visual Studio solution file from a list of project +files. + +Options: + --help Print this message + --out=outfile Redirect output to a file + --ver=version Version (7,8,9,10,11,12,14) of visual studio to generate for + --target=isa-os-cc Target specifier +EOF + exit 1 +} + +die() { + echo "${self_basename}: $@" >&2 + [ -f "${outfile}" ] && rm -f ${outfile}{,.mk} + exit 1 +} + +die_unknown(){ + echo "Unknown option \"$1\"." >&2 + echo "See ${self_basename} --help for available options." >&2 + [ -f "${outfile}" ] && rm -f ${outfile}{,.mk} + exit 1 +} + +indent1=$'\t' +indent="" +indent_push() { + indent="${indent}${indent1}" +} +indent_pop() { + indent="${indent%${indent1}}" +} + +parse_project() { + local file=$1 + if [ "$sfx" = "vcproj" ]; then + local name=`grep Name "$file" | awk 'BEGIN {FS="\""}{if (NR==1) print $2}'` + local guid=`grep ProjectGUID "$file" | awk 'BEGIN {FS="\""}{if (NR==1) print $2}'` + else + local name=`grep RootNamespace "$file" | sed 's,.*<.*>\(.*\)</.*>.*,\1,'` + local guid=`grep ProjectGuid "$file" | sed 's,.*<.*>\(.*\)</.*>.*,\1,'` + fi + + # save the project GUID to a varaible, normalizing to the basename of the + # vcproj file without the extension + local var + var=${file##*/} + var=${var%%.${sfx}} + eval "${var}_file=\"$1\"" + eval "${var}_name=$name" + eval "${var}_guid=$guid" + + if [ "$sfx" = "vcproj" ]; then + cur_config_list=`grep -A1 '<Configuration' $file | + grep Name | cut -d\" -f2` + else + cur_config_list=`grep -B1 'Label="Configuration"' $file | + grep Condition | cut -d\' -f4` + fi + new_config_list=$(for i in $config_list $cur_config_list; do + echo $i + done | sort | uniq) + if [ "$config_list" != "" ] && [ "$config_list" != "$new_config_list" ]; then + mixed_platforms=1 + fi + config_list="$new_config_list" + eval "${var}_config_list=\"$cur_config_list\"" + proj_list="${proj_list} ${var}" +} + +process_project() { + eval "local file=\${$1_file}" + eval "local name=\${$1_name}" + eval "local guid=\${$1_guid}" + + # save the project GUID to a varaible, normalizing to the basename of the + # vcproj file without the extension + local var + var=${file##*/} + var=${var%%.${sfx}} + eval "${var}_guid=$guid" + + echo "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"$name\", \"$file\", \"$guid\"" + indent_push + + eval "local deps=\"\${${var}_deps}\"" + if [ -n "$deps" ] && [ "$sfx" = "vcproj" ]; then + echo "${indent}ProjectSection(ProjectDependencies) = postProject" + indent_push + + for dep in $deps; do + eval "local dep_guid=\${${dep}_guid}" + [ -z "${dep_guid}" ] && die "Unknown GUID for $dep (dependency of $var)" + echo "${indent}$dep_guid = $dep_guid" + done + + indent_pop + echo "${indent}EndProjectSection" + + fi + + indent_pop + echo "EndProject" +} + +process_global() { + echo "Global" + indent_push + + # + # Solution Configuration Platforms + # + echo "${indent}GlobalSection(SolutionConfigurationPlatforms) = preSolution" + indent_push + IFS_bak=${IFS} + IFS=$'\r'$'\n' + if [ "$mixed_platforms" != "" ]; then + config_list=" +Release|Mixed Platforms +Debug|Mixed Platforms" + fi + for config in ${config_list}; do + echo "${indent}$config = $config" + done + IFS=${IFS_bak} + indent_pop + echo "${indent}EndGlobalSection" + + # + # Project Configuration Platforms + # + echo "${indent}GlobalSection(ProjectConfigurationPlatforms) = postSolution" + indent_push + for proj in ${proj_list}; do + eval "local proj_guid=\${${proj}_guid}" + eval "local proj_config_list=\${${proj}_config_list}" + IFS=$'\r'$'\n' + for config in ${proj_config_list}; do + if [ "$mixed_platforms" != "" ]; then + local c=${config%%|*} + echo "${indent}${proj_guid}.${c}|Mixed Platforms.ActiveCfg = ${config}" + echo "${indent}${proj_guid}.${c}|Mixed Platforms.Build.0 = ${config}" + else + echo "${indent}${proj_guid}.${config}.ActiveCfg = ${config}" + echo "${indent}${proj_guid}.${config}.Build.0 = ${config}" + fi + + done + IFS=${IFS_bak} + done + indent_pop + echo "${indent}EndGlobalSection" + + # + # Solution Properties + # + echo "${indent}GlobalSection(SolutionProperties) = preSolution" + indent_push + echo "${indent}HideSolutionNode = FALSE" + indent_pop + echo "${indent}EndGlobalSection" + + indent_pop + echo "EndGlobal" +} + +process_makefile() { + IFS_bak=${IFS} + IFS=$'\r'$'\n' + local TAB=$'\t' + cat <<EOF +ifeq (\$(CONFIG_VS_VERSION),7) +MSBUILD_TOOL := devenv.com +else +MSBUILD_TOOL := msbuild.exe +endif +found_devenv := \$(shell which \$(MSBUILD_TOOL) >/dev/null 2>&1 && echo yes) +.nodevenv.once: +${TAB}@echo " * \$(MSBUILD_TOOL) not found in path." +${TAB}@echo " * " +${TAB}@echo " * You will have to build all configurations manually using the" +${TAB}@echo " * Visual Studio IDE. To allow make to build them automatically," +${TAB}@echo " * add the Common7/IDE directory of your Visual Studio" +${TAB}@echo " * installation to your path, eg:" +${TAB}@echo " * C:\Program Files\Microsoft Visual Studio 8\Common7\IDE" +${TAB}@echo " * " +${TAB}@touch \$@ +CLEAN-OBJS += \$(if \$(found_devenv),,.nodevenv.once) + +EOF + + for sln_config in ${config_list}; do + local config=${sln_config%%|*} + local platform=${sln_config##*|} + local nows_sln_config=`echo $sln_config | sed -e 's/[^a-zA-Z0-9]/_/g'` + cat <<EOF +BUILD_TARGETS += \$(if \$(NO_LAUNCH_DEVENV),,$nows_sln_config) +clean:: +${TAB}rm -rf "$platform"/"$config" +.PHONY: $nows_sln_config +ifneq (\$(found_devenv),) + ifeq (\$(CONFIG_VS_VERSION),7) +$nows_sln_config: $outfile +${TAB}\$(MSBUILD_TOOL) $outfile -build "$config" + + else +$nows_sln_config: $outfile +${TAB}\$(MSBUILD_TOOL) $outfile -m -t:Build \\ +${TAB}${TAB}-p:Configuration="$config" -p:Platform="$platform" + + endif +else +$nows_sln_config: $outfile .nodevenv.once +${TAB}@echo " * Skipping build of $sln_config (\$(MSBUILD_TOOL) not in path)." +${TAB}@echo " * " +endif + +EOF + done + IFS=${IFS_bak} +} + +# Process command line +outfile=/dev/stdout +for opt in "$@"; do + optval="${opt#*=}" + case "$opt" in + --help|-h) show_help + ;; + --out=*) outfile="${optval}"; mkoutfile="${optval}".mk + ;; + --dep=*) eval "${optval%%:*}_deps=\"\${${optval%%:*}_deps} ${optval##*:}\"" + ;; + --ver=*) vs_ver="$optval" + case $optval in + [789]|10|11|12|14) + ;; + *) die Unrecognized Visual Studio Version in $opt + ;; + esac + ;; + --ver=*) vs_ver="$optval" + case $optval in + 7) sln_vers="8.00" + sln_vers_str="Visual Studio .NET 2003" + ;; + [89]) + ;; + *) die "Unrecognized Visual Studio Version '$optval' in $opt" + ;; + esac + ;; + --target=*) target="${optval}" + ;; + -*) die_unknown $opt + ;; + *) file_list[${#file_list[@]}]="$opt" + esac +done +outfile=${outfile:-/dev/stdout} +mkoutfile=${mkoutfile:-/dev/stdout} +case "${vs_ver:-8}" in + 7) sln_vers="8.00" + sln_vers_str="Visual Studio .NET 2003" + ;; + 8) sln_vers="9.00" + sln_vers_str="Visual Studio 2005" + ;; + 9) sln_vers="10.00" + sln_vers_str="Visual Studio 2008" + ;; + 10) sln_vers="11.00" + sln_vers_str="Visual Studio 2010" + ;; + 11) sln_vers="12.00" + sln_vers_str="Visual Studio 2012" + ;; + 12) sln_vers="12.00" + sln_vers_str="Visual Studio 2013" + ;; + 14) sln_vers="14.00" + sln_vers_str="Visual Studio 2015" + ;; +esac +case "${vs_ver:-8}" in + [789]) + sfx=vcproj + ;; + 10|11|12|14) + sfx=vcxproj + ;; +esac + +for f in "${file_list[@]}"; do + parse_project $f +done +cat >${outfile} <<EOF +Microsoft Visual Studio Solution File, Format Version $sln_vers${EOLDOS} +# $sln_vers_str${EOLDOS} +EOF +for proj in ${proj_list}; do + process_project $proj >>${outfile} +done +process_global >>${outfile} +process_makefile >${mkoutfile}
diff --git a/src/third_party/libvpx/build/make/gen_msvs_vcxproj.sh b/src/third_party/libvpx/build/make/gen_msvs_vcxproj.sh new file mode 100755 index 0000000..e98611d --- /dev/null +++ b/src/third_party/libvpx/build/make/gen_msvs_vcxproj.sh
@@ -0,0 +1,490 @@ +#!/bin/bash +## +## Copyright (c) 2013 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## + +self=$0 +self_basename=${self##*/} +self_dirname=$(dirname "$0") + +. "$self_dirname/msvs_common.sh"|| exit 127 + +show_help() { + cat <<EOF +Usage: ${self_basename} --name=projname [options] file1 [file2 ...] + +This script generates a Visual Studio project file from a list of source +code files. + +Options: + --help Print this message + --exe Generate a project for building an Application + --lib Generate a project for creating a static library + --dll Generate a project for creating a dll + --static-crt Use the static C runtime (/MT) + --enable-werror Treat warnings as errors (/WX) + --target=isa-os-cc Target specifier (required) + --out=filename Write output to a file [stdout] + --name=project_name Name of the project (required) + --proj-guid=GUID GUID to use for the project + --module-def=filename File containing export definitions (for DLLs) + --ver=version Version (10,11,12,14) of visual studio to generate for + --src-path-bare=dir Path to root of source tree + -Ipath/to/include Additional include directories + -DFLAG[=value] Preprocessor macros to define + -Lpath/to/lib Additional library search paths + -llibname Library to link against +EOF + exit 1 +} + +tag_content() { + local tag=$1 + local content=$2 + shift + shift + if [ $# -ne 0 ]; then + echo "${indent}<${tag}" + indent_push + tag_attributes "$@" + echo "${indent}>${content}</${tag}>" + indent_pop + else + echo "${indent}<${tag}>${content}</${tag}>" + fi +} + +generate_filter() { + local name=$1 + local pats=$2 + local file_list_sz + local i + local f + local saveIFS="$IFS" + local pack + echo "generating filter '$name' from ${#file_list[@]} files" >&2 + IFS=* + + file_list_sz=${#file_list[@]} + for i in ${!file_list[@]}; do + f=${file_list[i]} + for pat in ${pats//;/$IFS}; do + if [ "${f##*.}" == "$pat" ]; then + unset file_list[i] + + objf=$(echo ${f%.*}.obj \ + | sed -e "s,$src_path_bare,," \ + -e 's/^[\./]\+//g' -e 's,[:/ ],_,g') + + if ([ "$pat" == "asm" ] || [ "$pat" == "s" ]) && $asm_use_custom_step; then + # Avoid object file name collisions, i.e. vpx_config.c and + # vpx_config.asm produce the same object file without + # this additional suffix. + objf=${objf%.obj}_asm.obj + open_tag CustomBuild \ + Include="$f" + for plat in "${platforms[@]}"; do + for cfg in Debug Release; do + tag_content Message "Assembling %(Filename)%(Extension)" \ + Condition="'\$(Configuration)|\$(Platform)'=='$cfg|$plat'" + tag_content Command "$(eval echo \$asm_${cfg}_cmdline) -o \$(IntDir)$objf" \ + Condition="'\$(Configuration)|\$(Platform)'=='$cfg|$plat'" + tag_content Outputs "\$(IntDir)$objf" \ + Condition="'\$(Configuration)|\$(Platform)'=='$cfg|$plat'" + done + done + close_tag CustomBuild + elif [ "$pat" == "c" ] || \ + [ "$pat" == "cc" ] || [ "$pat" == "cpp" ]; then + open_tag ClCompile \ + Include="$f" + # Separate file names with Condition? + tag_content ObjectFileName "\$(IntDir)$objf" + # Check for AVX and turn it on to avoid warnings. + if [[ $f =~ avx.?\.c$ ]]; then + tag_content AdditionalOptions "/arch:AVX" + fi + close_tag ClCompile + elif [ "$pat" == "h" ] ; then + tag ClInclude \ + Include="$f" + elif [ "$pat" == "vcxproj" ] ; then + open_tag ProjectReference \ + Include="$f" + depguid=`grep ProjectGuid "$f" | sed 's,.*<.*>\(.*\)</.*>.*,\1,'` + tag_content Project "$depguid" + tag_content ReferenceOutputAssembly false + close_tag ProjectReference + else + tag None \ + Include="$f" + fi + + break + fi + done + done + + IFS="$saveIFS" +} + +# Process command line +unset target +for opt in "$@"; do + optval="${opt#*=}" + case "$opt" in + --help|-h) show_help + ;; + --target=*) target="${optval}" + ;; + --out=*) outfile="$optval" + ;; + --name=*) name="${optval}" + ;; + --proj-guid=*) guid="${optval}" + ;; + --module-def=*) module_def="${optval}" + ;; + --exe) proj_kind="exe" + ;; + --dll) proj_kind="dll" + ;; + --lib) proj_kind="lib" + ;; + --src-path-bare=*) + src_path_bare=$(fix_path "$optval") + src_path_bare=${src_path_bare%/} + ;; + --static-crt) use_static_runtime=true + ;; + --enable-werror) werror=true + ;; + --ver=*) + vs_ver="$optval" + case "$optval" in + 10|11|12|14) + ;; + *) die Unrecognized Visual Studio Version in $opt + ;; + esac + ;; + -I*) + opt=${opt##-I} + opt=$(fix_path "$opt") + opt="${opt%/}" + incs="${incs}${incs:+;}"${opt}"" + yasmincs="${yasmincs} -I"${opt}"" + ;; + -D*) defines="${defines}${defines:+;}${opt##-D}" + ;; + -L*) # fudge . to $(OutDir) + if [ "${opt##-L}" == "." ]; then + libdirs="${libdirs}${libdirs:+;}"\$(OutDir)"" + else + # Also try directories for this platform/configuration + opt=${opt##-L} + opt=$(fix_path "$opt") + libdirs="${libdirs}${libdirs:+;}"${opt}"" + libdirs="${libdirs}${libdirs:+;}"${opt}/\$(PlatformName)/\$(Configuration)"" + libdirs="${libdirs}${libdirs:+;}"${opt}/\$(PlatformName)"" + fi + ;; + -l*) libs="${libs}${libs:+ }${opt##-l}.lib" + ;; + -*) die_unknown $opt + ;; + *) + # The paths in file_list are fixed outside of the loop. + file_list[${#file_list[@]}]="$opt" + case "$opt" in + *.asm|*.s) uses_asm=true + ;; + esac + ;; + esac +done + +# Make one call to fix_path for file_list to improve performance. +fix_file_list file_list + +outfile=${outfile:-/dev/stdout} +guid=${guid:-`generate_uuid`} +asm_use_custom_step=false +uses_asm=${uses_asm:-false} +case "${vs_ver:-11}" in + 10|11|12|14) + asm_use_custom_step=$uses_asm + ;; +esac + +[ -n "$name" ] || die "Project name (--name) must be specified!" +[ -n "$target" ] || die "Target (--target) must be specified!" + +if ${use_static_runtime:-false}; then + release_runtime=MultiThreaded + debug_runtime=MultiThreadedDebug + lib_sfx=mt +else + release_runtime=MultiThreadedDLL + debug_runtime=MultiThreadedDebugDLL + lib_sfx=md +fi + +# Calculate debug lib names: If a lib ends in ${lib_sfx}.lib, then rename +# it to ${lib_sfx}d.lib. This precludes linking to release libs from a +# debug exe, so this may need to be refactored later. +for lib in ${libs}; do + if [ "$lib" != "${lib%${lib_sfx}.lib}" ]; then + lib=${lib%.lib}d.lib + fi + debug_libs="${debug_libs}${debug_libs:+ }${lib}" +done +debug_libs=${debug_libs// /;} +libs=${libs// /;} + + +# List of all platforms supported for this target +case "$target" in + x86_64*) + platforms[0]="x64" + asm_Debug_cmdline="yasm -Xvc -g cv8 -f win64 ${yasmincs} "%(FullPath)"" + asm_Release_cmdline="yasm -Xvc -f win64 ${yasmincs} "%(FullPath)"" + ;; + x86*) + platforms[0]="Win32" + asm_Debug_cmdline="yasm -Xvc -g cv8 -f win32 ${yasmincs} "%(FullPath)"" + asm_Release_cmdline="yasm -Xvc -f win32 ${yasmincs} "%(FullPath)"" + ;; + arm*) + platforms[0]="ARM" + asm_Debug_cmdline="armasm -nologo -oldit "%(FullPath)"" + asm_Release_cmdline="armasm -nologo -oldit "%(FullPath)"" + ;; + *) die "Unsupported target $target!" + ;; +esac + +generate_vcxproj() { + echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + open_tag Project \ + DefaultTargets="Build" \ + ToolsVersion="4.0" \ + xmlns="http://schemas.microsoft.com/developer/msbuild/2003" \ + + open_tag ItemGroup \ + Label="ProjectConfigurations" + for plat in "${platforms[@]}"; do + for config in Debug Release; do + open_tag ProjectConfiguration \ + Include="$config|$plat" + tag_content Configuration $config + tag_content Platform $plat + close_tag ProjectConfiguration + done + done + close_tag ItemGroup + + open_tag PropertyGroup \ + Label="Globals" + tag_content ProjectGuid "{${guid}}" + tag_content RootNamespace ${name} + tag_content Keyword ManagedCProj + if [ $vs_ver -ge 12 ] && [ "${platforms[0]}" = "ARM" ]; then + tag_content AppContainerApplication true + # The application type can be one of "Windows Store", + # "Windows Phone" or "Windows Phone Silverlight". The + # actual value doesn't matter from the libvpx point of view, + # since a static library built for one works on the others. + # The PlatformToolset field needs to be set in sync with this; + # for Windows Store and Windows Phone Silverlight it should be + # v120 while it should be v120_wp81 if the type is Windows Phone. + tag_content ApplicationType "Windows Store" + tag_content ApplicationTypeRevision 8.1 + fi + close_tag PropertyGroup + + tag Import \ + Project="\$(VCTargetsPath)\\Microsoft.Cpp.Default.props" + + for plat in "${platforms[@]}"; do + for config in Release Debug; do + open_tag PropertyGroup \ + Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'" \ + Label="Configuration" + if [ "$proj_kind" = "exe" ]; then + tag_content ConfigurationType Application + elif [ "$proj_kind" = "dll" ]; then + tag_content ConfigurationType DynamicLibrary + else + tag_content ConfigurationType StaticLibrary + fi + if [ "$vs_ver" = "11" ]; then + if [ "$plat" = "ARM" ]; then + # Setting the wp80 toolchain automatically sets the + # WINAPI_FAMILY define, which is required for building + # code for arm with the windows headers. Alternatively, + # one could add AppContainerApplication=true in the Globals + # section and add PrecompiledHeader=NotUsing and + # CompileAsWinRT=false in ClCompile and SubSystem=Console + # in Link. + tag_content PlatformToolset v110_wp80 + else + tag_content PlatformToolset v110 + fi + fi + if [ "$vs_ver" = "12" ]; then + # Setting a PlatformToolset indicating windows phone isn't + # enough to build code for arm with MSVC 2013, one strictly + # has to enable AppContainerApplication as well. + tag_content PlatformToolset v120 + fi + if [ "$vs_ver" = "14" ]; then + tag_content PlatformToolset v140 + fi + tag_content CharacterSet Unicode + if [ "$config" = "Release" ]; then + tag_content WholeProgramOptimization true + fi + close_tag PropertyGroup + done + done + + tag Import \ + Project="\$(VCTargetsPath)\\Microsoft.Cpp.props" + + open_tag ImportGroup \ + Label="PropertySheets" + tag Import \ + Project="\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props" \ + Condition="exists('\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props')" \ + Label="LocalAppDataPlatform" + close_tag ImportGroup + + tag PropertyGroup \ + Label="UserMacros" + + for plat in "${platforms[@]}"; do + plat_no_ws=`echo $plat | sed 's/[^A-Za-z0-9_]/_/g'` + for config in Debug Release; do + open_tag PropertyGroup \ + Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'" + tag_content OutDir "\$(SolutionDir)$plat_no_ws\\\$(Configuration)\\" + tag_content IntDir "$plat_no_ws\\\$(Configuration)\\${name}\\" + if [ "$proj_kind" == "lib" ]; then + if [ "$config" == "Debug" ]; then + config_suffix=d + else + config_suffix="" + fi + tag_content TargetName "${name}${lib_sfx}${config_suffix}" + fi + close_tag PropertyGroup + done + done + + for plat in "${platforms[@]}"; do + for config in Debug Release; do + open_tag ItemDefinitionGroup \ + Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'" + if [ "$name" == "vpx" ]; then + hostplat=$plat + if [ "$hostplat" == "ARM" ]; then + hostplat=Win32 + fi + fi + open_tag ClCompile + if [ "$config" = "Debug" ]; then + opt=Disabled + runtime=$debug_runtime + curlibs=$debug_libs + debug=_DEBUG + else + opt=MaxSpeed + runtime=$release_runtime + curlibs=$libs + tag_content FavorSizeOrSpeed Speed + debug=NDEBUG + fi + extradefines=";$defines" + tag_content Optimization $opt + tag_content AdditionalIncludeDirectories "$incs;%(AdditionalIncludeDirectories)" + tag_content PreprocessorDefinitions "WIN32;$debug;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE$extradefines;%(PreprocessorDefinitions)" + tag_content RuntimeLibrary $runtime + tag_content WarningLevel Level3 + if ${werror:-false}; then + tag_content TreatWarningAsError true + fi + if [ $vs_ver -ge 11 ]; then + # We need to override the defaults for these settings + # if AppContainerApplication is set. + tag_content CompileAsWinRT false + tag_content PrecompiledHeader NotUsing + tag_content SDLCheck false + fi + close_tag ClCompile + case "$proj_kind" in + exe) + open_tag Link + tag_content GenerateDebugInformation true + # Console is the default normally, but if + # AppContainerApplication is set, we need to override it. + tag_content SubSystem Console + close_tag Link + ;; + dll) + open_tag Link + tag_content GenerateDebugInformation true + tag_content ModuleDefinitionFile $module_def + close_tag Link + ;; + lib) + ;; + esac + close_tag ItemDefinitionGroup + done + + done + + open_tag ItemGroup + generate_filter "Source Files" "c;cc;cpp;def;odl;idl;hpj;bat;asm;asmx;s" + close_tag ItemGroup + open_tag ItemGroup + generate_filter "Header Files" "h;hm;inl;inc;xsd" + close_tag ItemGroup + open_tag ItemGroup + generate_filter "Build Files" "mk" + close_tag ItemGroup + open_tag ItemGroup + generate_filter "References" "vcxproj" + close_tag ItemGroup + + tag Import \ + Project="\$(VCTargetsPath)\\Microsoft.Cpp.targets" + + open_tag ImportGroup \ + Label="ExtensionTargets" + close_tag ImportGroup + + close_tag Project + + # This must be done from within the {} subshell + echo "Ignored files list (${#file_list[@]} items) is:" >&2 + for f in "${file_list[@]}"; do + echo " $f" >&2 + done +} + +# This regexp doesn't catch most of the strings in the vcxproj format, +# since they're like <tag>path</tag> instead of <tag attr="path" /> +# as previously. It still seems to work ok despite this. +generate_vcxproj | + sed -e '/"/s;\([^ "]\)/;\1\\;g' | + sed -e '/xmlns/s;\\;/;g' > ${outfile} + +exit
diff --git a/src/third_party/libvpx/build/make/ios-Info.plist b/src/third_party/libvpx/build/make/ios-Info.plist new file mode 100644 index 0000000..d157b11 --- /dev/null +++ b/src/third_party/libvpx/build/make/ios-Info.plist
@@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleExecutable</key> + <string>VPX</string> + <key>CFBundleIdentifier</key> + <string>org.webmproject.VPX</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>VPX</string> + <key>CFBundlePackageType</key> + <string>FMWK</string> + <key>CFBundleShortVersionString</key> + <string>${VERSION}</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleSupportedPlatforms</key> + <array> + <string>iPhoneOS</string> + </array> + <key>CFBundleVersion</key> + <string>${VERSION}</string> + <key>MinimumOSVersion</key> + <string>${IOS_VERSION_MIN}</string> + <key>UIDeviceFamily</key> + <array> + <integer>1</integer> + <integer>2</integer> + </array> + <key>VPXFullVersion</key> + <string>${FULLVERSION}</string> +</dict> +</plist>
diff --git a/src/third_party/libvpx/build/make/iosbuild.sh b/src/third_party/libvpx/build/make/iosbuild.sh new file mode 100755 index 0000000..c703f22 --- /dev/null +++ b/src/third_party/libvpx/build/make/iosbuild.sh
@@ -0,0 +1,383 @@ +#!/bin/sh +## +## Copyright (c) 2014 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## +## +## This script generates 'VPX.framework'. An iOS app can encode and decode VPx +## video by including 'VPX.framework'. +## +## Run iosbuild.sh to create 'VPX.framework' in the current directory. +## +set -e +devnull='> /dev/null 2>&1' + +BUILD_ROOT="_iosbuild" +CONFIGURE_ARGS="--disable-docs + --disable-examples + --disable-libyuv + --disable-unit-tests" +DIST_DIR="_dist" +FRAMEWORK_DIR="VPX.framework" +FRAMEWORK_LIB="VPX.framework/VPX" +HEADER_DIR="${FRAMEWORK_DIR}/Headers/vpx" +SCRIPT_DIR=$(dirname "$0") +LIBVPX_SOURCE_DIR=$(cd ${SCRIPT_DIR}/../..; pwd) +LIPO=$(xcrun -sdk iphoneos${SDK} -find lipo) +ORIG_PWD="$(pwd)" +ARM_TARGETS="arm64-darwin-gcc + armv7-darwin-gcc + armv7s-darwin-gcc" +SIM_TARGETS="x86-iphonesimulator-gcc + x86_64-iphonesimulator-gcc" +OSX_TARGETS="x86-darwin15-gcc + x86_64-darwin15-gcc" +TARGETS="${ARM_TARGETS} ${SIM_TARGETS}" + +# Configures for the target specified by $1, and invokes make with the dist +# target using $DIST_DIR as the distribution output directory. +build_target() { + local target="$1" + local old_pwd="$(pwd)" + local target_specific_flags="" + + vlog "***Building target: ${target}***" + + case "${target}" in + x86-*) + target_specific_flags="--enable-pic" + vlog "Enabled PIC for ${target}" + ;; + esac + + mkdir "${target}" + cd "${target}" + eval "${LIBVPX_SOURCE_DIR}/configure" --target="${target}" \ + ${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS} ${target_specific_flags} \ + ${devnull} + export DIST_DIR + eval make dist ${devnull} + cd "${old_pwd}" + + vlog "***Done building target: ${target}***" +} + +# Returns the preprocessor symbol for the target specified by $1. +target_to_preproc_symbol() { + target="$1" + case "${target}" in + arm64-*) + echo "__aarch64__" + ;; + armv7-*) + echo "__ARM_ARCH_7A__" + ;; + armv7s-*) + echo "__ARM_ARCH_7S__" + ;; + x86-*) + echo "__i386__" + ;; + x86_64-*) + echo "__x86_64__" + ;; + *) + echo "#error ${target} unknown/unsupported" + return 1 + ;; + esac +} + +# Create a vpx_config.h shim that, based on preprocessor settings for the +# current target CPU, includes the real vpx_config.h for the current target. +# $1 is the list of targets. +create_vpx_framework_config_shim() { + local targets="$1" + local config_file="${HEADER_DIR}/vpx_config.h" + local preproc_symbol="" + local target="" + local include_guard="VPX_FRAMEWORK_HEADERS_VPX_VPX_CONFIG_H_" + + local file_header="/* + * Copyright (c) $(date +%Y) The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +/* GENERATED FILE: DO NOT EDIT! */ + +#ifndef ${include_guard} +#define ${include_guard} + +#if defined" + + printf "%s" "${file_header}" > "${config_file}" + for target in ${targets}; do + preproc_symbol=$(target_to_preproc_symbol "${target}") + printf " ${preproc_symbol}\n" >> "${config_file}" + printf "#define VPX_FRAMEWORK_TARGET \"${target}\"\n" >> "${config_file}" + printf "#include \"VPX/vpx/${target}/vpx_config.h\"\n" >> "${config_file}" + printf "#elif defined" >> "${config_file}" + mkdir "${HEADER_DIR}/${target}" + cp -p "${BUILD_ROOT}/${target}/vpx_config.h" "${HEADER_DIR}/${target}" + done + + # Consume the last line of output from the loop: We don't want it. + sed -i '' -e '$d' "${config_file}" + + printf "#endif\n\n" >> "${config_file}" + printf "#endif // ${include_guard}" >> "${config_file}" +} + +# Verifies that $FRAMEWORK_LIB fat library contains requested builds. +verify_framework_targets() { + local requested_cpus="" + local cpu="" + + # Extract CPU from full target name. + for target; do + cpu="${target%%-*}" + if [ "${cpu}" = "x86" ]; then + # lipo -info outputs i386 for libvpx x86 targets. + cpu="i386" + fi + requested_cpus="${requested_cpus}${cpu} " + done + + # Get target CPUs present in framework library. + local targets_built=$(${LIPO} -info ${FRAMEWORK_LIB}) + + # $LIPO -info outputs a string like the following: + # Architectures in the fat file: $FRAMEWORK_LIB <architectures> + # Capture only the architecture strings. + targets_built=${targets_built##*: } + + # Sort CPU strings to make the next step a simple string compare. + local actual=$(echo ${targets_built} | tr " " "\n" | sort | tr "\n" " ") + local requested=$(echo ${requested_cpus} | tr " " "\n" | sort | tr "\n" " ") + + vlog "Requested ${FRAMEWORK_LIB} CPUs: ${requested}" + vlog "Actual ${FRAMEWORK_LIB} CPUs: ${actual}" + + if [ "${requested}" != "${actual}" ]; then + elog "Actual ${FRAMEWORK_LIB} targets do not match requested target list." + elog " Requested target CPUs: ${requested}" + elog " Actual target CPUs: ${actual}" + return 1 + fi +} + +# Configures and builds each target specified by $1, and then builds +# VPX.framework. +build_framework() { + local lib_list="" + local targets="$1" + local target="" + local target_dist_dir="" + + # Clean up from previous build(s). + rm -rf "${BUILD_ROOT}" "${FRAMEWORK_DIR}" + + # Create output dirs. + mkdir -p "${BUILD_ROOT}" + mkdir -p "${HEADER_DIR}" + + cd "${BUILD_ROOT}" + + for target in ${targets}; do + build_target "${target}" + target_dist_dir="${BUILD_ROOT}/${target}/${DIST_DIR}" + if [ "${ENABLE_SHARED}" = "yes" ]; then + local suffix="dylib" + else + local suffix="a" + fi + lib_list="${lib_list} ${target_dist_dir}/lib/libvpx.${suffix}" + done + + cd "${ORIG_PWD}" + + # The basic libvpx API includes are all the same; just grab the most recent + # set. + cp -p "${target_dist_dir}"/include/vpx/* "${HEADER_DIR}" + + # Build the fat library. + ${LIPO} -create ${lib_list} -output ${FRAMEWORK_DIR}/VPX + + # Create the vpx_config.h shim that allows usage of vpx_config.h from + # within VPX.framework. + create_vpx_framework_config_shim "${targets}" + + # Copy in vpx_version.h. + cp -p "${BUILD_ROOT}/${target}/vpx_version.h" "${HEADER_DIR}" + + if [ "${ENABLE_SHARED}" = "yes" ]; then + # Adjust the dylib's name so dynamic linking in apps works as expected. + install_name_tool -id '@rpath/VPX.framework/VPX' ${FRAMEWORK_DIR}/VPX + + # Copy in Info.plist. + cat "${SCRIPT_DIR}/ios-Info.plist" \ + | sed "s/\${FULLVERSION}/${FULLVERSION}/g" \ + | sed "s/\${VERSION}/${VERSION}/g" \ + | sed "s/\${IOS_VERSION_MIN}/${IOS_VERSION_MIN}/g" \ + > "${FRAMEWORK_DIR}/Info.plist" + fi + + # Confirm VPX.framework/VPX contains the targets requested. + verify_framework_targets ${targets} + + vlog "Created fat library ${FRAMEWORK_LIB} containing:" + for lib in ${lib_list}; do + vlog " $(echo ${lib} | awk -F / '{print $2, $NF}')" + done +} + +# Trap function. Cleans up the subtree used to build all targets contained in +# $TARGETS. +cleanup() { + local readonly res=$? + cd "${ORIG_PWD}" + + if [ $res -ne 0 ]; then + elog "build exited with error ($res)" + fi + + if [ "${PRESERVE_BUILD_OUTPUT}" != "yes" ]; then + rm -rf "${BUILD_ROOT}" + fi +} + +print_list() { + local indent="$1" + shift + local list="$@" + for entry in ${list}; do + echo "${indent}${entry}" + done +} + +iosbuild_usage() { +cat << EOF + Usage: ${0##*/} [arguments] + --help: Display this message and exit. + --enable-shared: Build a dynamic framework for use on iOS 8 or later. + --extra-configure-args <args>: Extra args to pass when configuring libvpx. + --macosx: Uses darwin15 targets instead of iphonesimulator targets for x86 + and x86_64. Allows linking to framework when builds target MacOSX + instead of iOS. + --preserve-build-output: Do not delete the build directory. + --show-build-output: Show output from each library build. + --targets <targets>: Override default target list. Defaults: +$(print_list " " ${TARGETS}) + --test-link: Confirms all targets can be linked. Functionally identical to + passing --enable-examples via --extra-configure-args. + --verbose: Output information about the environment and each stage of the + build. +EOF +} + +elog() { + echo "${0##*/} failed because: $@" 1>&2 +} + +vlog() { + if [ "${VERBOSE}" = "yes" ]; then + echo "$@" + fi +} + +trap cleanup EXIT + +# Parse the command line. +while [ -n "$1" ]; do + case "$1" in + --extra-configure-args) + EXTRA_CONFIGURE_ARGS="$2" + shift + ;; + --help) + iosbuild_usage + exit + ;; + --enable-shared) + ENABLE_SHARED=yes + ;; + --preserve-build-output) + PRESERVE_BUILD_OUTPUT=yes + ;; + --show-build-output) + devnull= + ;; + --test-link) + EXTRA_CONFIGURE_ARGS="${EXTRA_CONFIGURE_ARGS} --enable-examples" + ;; + --targets) + TARGETS="$2" + shift + ;; + --macosx) + TARGETS="${ARM_TARGETS} ${OSX_TARGETS}" + ;; + --verbose) + VERBOSE=yes + ;; + *) + iosbuild_usage + exit 1 + ;; + esac + shift +done + +if [ "${ENABLE_SHARED}" = "yes" ]; then + CONFIGURE_ARGS="--enable-shared ${CONFIGURE_ARGS}" +fi + +FULLVERSION=$("${SCRIPT_DIR}"/version.sh --bare "${LIBVPX_SOURCE_DIR}") +VERSION=$(echo "${FULLVERSION}" | sed -E 's/^v([0-9]+\.[0-9]+\.[0-9]+).*$/\1/') + +if [ "$ENABLE_SHARED" = "yes" ]; then + IOS_VERSION_OPTIONS="--enable-shared" + IOS_VERSION_MIN="8.0" +else + IOS_VERSION_OPTIONS="" + IOS_VERSION_MIN="6.0" +fi + +if [ "${VERBOSE}" = "yes" ]; then +cat << EOF + BUILD_ROOT=${BUILD_ROOT} + DIST_DIR=${DIST_DIR} + CONFIGURE_ARGS=${CONFIGURE_ARGS} + EXTRA_CONFIGURE_ARGS=${EXTRA_CONFIGURE_ARGS} + FRAMEWORK_DIR=${FRAMEWORK_DIR} + FRAMEWORK_LIB=${FRAMEWORK_LIB} + HEADER_DIR=${HEADER_DIR} + LIBVPX_SOURCE_DIR=${LIBVPX_SOURCE_DIR} + LIPO=${LIPO} + MAKEFLAGS=${MAKEFLAGS} + ORIG_PWD=${ORIG_PWD} + PRESERVE_BUILD_OUTPUT=${PRESERVE_BUILD_OUTPUT} + TARGETS="$(print_list "" ${TARGETS})" + ENABLE_SHARED=${ENABLE_SHARED} + OSX_TARGETS="${OSX_TARGETS}" + SIM_TARGETS="${SIM_TARGETS}" + SCRIPT_DIR="${SCRIPT_DIR}" + FULLVERSION="${FULLVERSION}" + VERSION="${VERSION}" + IOS_VERSION_MIN="${IOS_VERSION_MIN}" +EOF +fi + +build_framework "${TARGETS}" +echo "Successfully built '${FRAMEWORK_DIR}' for:" +print_list "" ${TARGETS}
diff --git a/src/third_party/libvpx/build/make/msvs_common.sh b/src/third_party/libvpx/build/make/msvs_common.sh new file mode 100644 index 0000000..88f1cf9 --- /dev/null +++ b/src/third_party/libvpx/build/make/msvs_common.sh
@@ -0,0 +1,114 @@ +#!/bin/bash +## +## Copyright (c) 2014 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## + +if [ "$(uname -o 2>/dev/null)" = "Cygwin" ] \ + && cygpath --help >/dev/null 2>&1; then + FIXPATH='cygpath -m' +else + FIXPATH='echo_path' +fi + +die() { + echo "${self_basename}: $@" >&2 + exit 1 +} + +die_unknown(){ + echo "Unknown option \"$1\"." >&2 + echo "See ${self_basename} --help for available options." >&2 + exit 1 +} + +echo_path() { + for path; do + echo "$path" + done +} + +# Output one, possibly changed based on the system, path per line. +fix_path() { + $FIXPATH "$@" +} + +# Corrects the paths in file_list in one pass for efficiency. +# $1 is the name of the array to be modified. +fix_file_list() { + declare -n array_ref=$1 + files=$(fix_path "${array_ref[@]}") + local IFS=$'\n' + array_ref=($files) +} + +generate_uuid() { + local hex="0123456789ABCDEF" + local i + local uuid="" + local j + #93995380-89BD-4b04-88EB-625FBE52EBFB + for ((i=0; i<32; i++)); do + (( j = $RANDOM % 16 )) + uuid="${uuid}${hex:$j:1}" + done + echo "${uuid:0:8}-${uuid:8:4}-${uuid:12:4}-${uuid:16:4}-${uuid:20:12}" +} + +indent1=" " +indent="" +indent_push() { + indent="${indent}${indent1}" +} +indent_pop() { + indent="${indent%${indent1}}" +} + +tag_attributes() { + for opt in "$@"; do + optval="${opt#*=}" + [ -n "${optval}" ] || + die "Missing attribute value in '$opt' while generating $tag tag" + echo "${indent}${opt%%=*}=\"${optval}\"" + done +} + +open_tag() { + local tag=$1 + shift + if [ $# -ne 0 ]; then + echo "${indent}<${tag}" + indent_push + tag_attributes "$@" + echo "${indent}>" + else + echo "${indent}<${tag}>" + indent_push + fi +} + +close_tag() { + local tag=$1 + indent_pop + echo "${indent}</${tag}>" +} + +tag() { + local tag=$1 + shift + if [ $# -ne 0 ]; then + echo "${indent}<${tag}" + indent_push + tag_attributes "$@" + indent_pop + echo "${indent}/>" + else + echo "${indent}<${tag}/>" + fi +} +
diff --git a/src/third_party/libvpx/build/make/rtcd.pl b/src/third_party/libvpx/build/make/rtcd.pl new file mode 100755 index 0000000..991b6ab --- /dev/null +++ b/src/third_party/libvpx/build/make/rtcd.pl
@@ -0,0 +1,426 @@ +#!/usr/bin/env perl + +no strict 'refs'; +use warnings; +use Getopt::Long; +Getopt::Long::Configure("auto_help") if $Getopt::Long::VERSION > 2.32; + +my %ALL_FUNCS = (); +my @ALL_ARCHS; +my @ALL_FORWARD_DECLS; +my @REQUIRES; + +my %opts = (); +my %disabled = (); +my %required = (); + +my @argv; +foreach (@ARGV) { + $disabled{$1} = 1, next if /--disable-(.*)/; + $required{$1} = 1, next if /--require-(.*)/; + push @argv, $_; +} + +# NB: use GetOptions() instead of GetOptionsFromArray() for compatibility. +@ARGV = @argv; +GetOptions( + \%opts, + 'arch=s', + 'sym=s', + 'config=s', +); + +foreach my $opt (qw/arch config/) { + if (!defined($opts{$opt})) { + warn "--$opt is required!\n"; + Getopt::Long::HelpMessage('-exit' => 1); + } +} + +foreach my $defs_file (@ARGV) { + if (!-f $defs_file) { + warn "$defs_file: $!\n"; + Getopt::Long::HelpMessage('-exit' => 1); + } +} + +open CONFIG_FILE, $opts{config} or + die "Error opening config file '$opts{config}': $!\n"; + +my %config = (); +while (<CONFIG_FILE>) { + next if !/^(?:CONFIG_|HAVE_)/; + chomp; + my @pair = split /=/; + $config{$pair[0]} = $pair[1]; +} +close CONFIG_FILE; + +# +# Routines for the RTCD DSL to call +# +sub vpx_config($) { + return (defined $config{$_[0]}) ? $config{$_[0]} : ""; +} + +sub specialize { + my $fn=$_[0]; + shift; + foreach my $opt (@_) { + eval "\$${fn}_${opt}=${fn}_${opt}"; + } +} + +sub add_proto { + my $fn = splice(@_, -2, 1); + $ALL_FUNCS{$fn} = \@_; + specialize $fn, "c"; +} + +sub require { + foreach my $fn (keys %ALL_FUNCS) { + foreach my $opt (@_) { + my $ofn = eval "\$${fn}_${opt}"; + next if !$ofn; + + # if we already have a default, then we can disable it, as we know + # we can do better. + my $best = eval "\$${fn}_default"; + if ($best) { + my $best_ofn = eval "\$${best}"; + if ($best_ofn && "$best_ofn" ne "$ofn") { + eval "\$${best}_link = 'false'"; + } + } + eval "\$${fn}_default=${fn}_${opt}"; + eval "\$${fn}_${opt}_link='true'"; + } + } +} + +sub forward_decls { + push @ALL_FORWARD_DECLS, @_; +} + +# +# Include the user's directives +# +foreach my $f (@ARGV) { + open FILE, "<", $f or die "cannot open $f: $!\n"; + my $contents = join('', <FILE>); + close FILE; + eval $contents or warn "eval failed: $@\n"; +} + +# +# Process the directives according to the command line +# +sub process_forward_decls() { + foreach (@ALL_FORWARD_DECLS) { + $_->(); + } +} + +sub determine_indirection { + vpx_config("CONFIG_RUNTIME_CPU_DETECT") eq "yes" or &require(@ALL_ARCHS); + foreach my $fn (keys %ALL_FUNCS) { + my $n = ""; + my @val = @{$ALL_FUNCS{$fn}}; + my $args = pop @val; + my $rtyp = "@val"; + my $dfn = eval "\$${fn}_default"; + $dfn = eval "\$${dfn}"; + foreach my $opt (@_) { + my $ofn = eval "\$${fn}_${opt}"; + next if !$ofn; + my $link = eval "\$${fn}_${opt}_link"; + next if $link && $link eq "false"; + $n .= "x"; + } + if ($n eq "x") { + eval "\$${fn}_indirect = 'false'"; + } else { + eval "\$${fn}_indirect = 'true'"; + } + } +} + +sub declare_function_pointers { + foreach my $fn (sort keys %ALL_FUNCS) { + my @val = @{$ALL_FUNCS{$fn}}; + my $args = pop @val; + my $rtyp = "@val"; + my $dfn = eval "\$${fn}_default"; + $dfn = eval "\$${dfn}"; + foreach my $opt (@_) { + my $ofn = eval "\$${fn}_${opt}"; + next if !$ofn; + print "$rtyp ${ofn}($args);\n"; + } + if (eval "\$${fn}_indirect" eq "false") { + print "#define ${fn} ${dfn}\n"; + } else { + print "RTCD_EXTERN $rtyp (*${fn})($args);\n"; + } + print "\n"; + } +} + +sub set_function_pointers { + foreach my $fn (sort keys %ALL_FUNCS) { + my @val = @{$ALL_FUNCS{$fn}}; + my $args = pop @val; + my $rtyp = "@val"; + my $dfn = eval "\$${fn}_default"; + $dfn = eval "\$${dfn}"; + if (eval "\$${fn}_indirect" eq "true") { + print " $fn = $dfn;\n"; + foreach my $opt (@_) { + my $ofn = eval "\$${fn}_${opt}"; + next if !$ofn; + next if "$ofn" eq "$dfn"; + my $link = eval "\$${fn}_${opt}_link"; + next if $link && $link eq "false"; + my $cond = eval "\$have_${opt}"; + print " if (${cond}) $fn = $ofn;\n" + } + } + } +} + +sub filter { + my @filtered; + foreach (@_) { push @filtered, $_ unless $disabled{$_}; } + return @filtered; +} + +# +# Helper functions for generating the arch specific RTCD files +# +sub common_top() { + my $include_guard = uc($opts{sym})."_H_"; + print <<EOF; +#ifndef ${include_guard} +#define ${include_guard} + +#ifdef RTCD_C +#define RTCD_EXTERN +#else +#define RTCD_EXTERN extern +#endif + +EOF + +process_forward_decls(); +print <<EOF; + +#ifdef __cplusplus +extern "C" { +#endif + +EOF +declare_function_pointers("c", @ALL_ARCHS); + +print <<EOF; +void $opts{sym}(void); + +EOF +} + +sub common_bottom() { + print <<EOF; + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif +EOF +} + +sub x86() { + determine_indirection("c", @ALL_ARCHS); + + # Assign the helper variable for each enabled extension + foreach my $opt (@ALL_ARCHS) { + my $opt_uc = uc $opt; + eval "\$have_${opt}=\"flags & HAS_${opt_uc}\""; + } + + common_top; + print <<EOF; +#ifdef RTCD_C +#include "vpx_ports/x86.h" +static void setup_rtcd_internal(void) +{ + int flags = x86_simd_caps(); + + (void)flags; + +EOF + + set_function_pointers("c", @ALL_ARCHS); + + print <<EOF; +} +#endif +EOF + common_bottom; +} + +sub arm() { + determine_indirection("c", @ALL_ARCHS); + + # Assign the helper variable for each enabled extension + foreach my $opt (@ALL_ARCHS) { + my $opt_uc = uc $opt; + # Enable neon assembly based on HAVE_NEON logic instead of adding new + # HAVE_NEON_ASM logic + if ($opt eq 'neon_asm') { $opt_uc = 'NEON' } + eval "\$have_${opt}=\"flags & HAS_${opt_uc}\""; + } + + common_top; + print <<EOF; +#include "vpx_config.h" + +#ifdef RTCD_C +#include "vpx_ports/arm.h" +static void setup_rtcd_internal(void) +{ + int flags = arm_cpu_caps(); + + (void)flags; + +EOF + + set_function_pointers("c", @ALL_ARCHS); + + print <<EOF; +} +#endif +EOF + common_bottom; +} + +sub mips() { + determine_indirection("c", @ALL_ARCHS); + common_top; + + print <<EOF; +#include "vpx_config.h" + +#ifdef RTCD_C +static void setup_rtcd_internal(void) +{ +EOF + + set_function_pointers("c", @ALL_ARCHS); + + print <<EOF; +#if HAVE_DSPR2 +void vpx_dsputil_static_init(); +#if CONFIG_VP8 +void dsputil_static_init(); +#endif + +vpx_dsputil_static_init(); +#if CONFIG_VP8 +dsputil_static_init(); +#endif +#endif +} +#endif +EOF + common_bottom; +} + +sub unoptimized() { + determine_indirection "c"; + common_top; + print <<EOF; +#include "vpx_config.h" + +#ifdef RTCD_C +static void setup_rtcd_internal(void) +{ +EOF + + set_function_pointers "c"; + + print <<EOF; +} +#endif +EOF + common_bottom; +} + +# +# Main Driver +# + +&require("c"); +if ($opts{arch} eq 'x86') { + @ALL_ARCHS = filter(qw/mmx sse sse2 sse3 ssse3 sse4_1 avx avx2/); + x86; +} elsif ($opts{arch} eq 'x86_64') { + @ALL_ARCHS = filter(qw/mmx sse sse2 sse3 ssse3 sse4_1 avx avx2/); + @REQUIRES = filter(keys %required ? keys %required : qw/mmx sse sse2/); + &require(@REQUIRES); + x86; +} elsif ($opts{arch} eq 'mips32' || $opts{arch} eq 'mips64') { + @ALL_ARCHS = filter("$opts{arch}"); + open CONFIG_FILE, $opts{config} or + die "Error opening config file '$opts{config}': $!\n"; + while (<CONFIG_FILE>) { + if (/HAVE_DSPR2=yes/) { + @ALL_ARCHS = filter("$opts{arch}", qw/dspr2/); + last; + } + if (/HAVE_MSA=yes/) { + @ALL_ARCHS = filter("$opts{arch}", qw/msa/); + last; + } + } + close CONFIG_FILE; + mips; +} elsif ($opts{arch} eq 'armv6') { + @ALL_ARCHS = filter(qw/media/); + arm; +} elsif ($opts{arch} =~ /armv7\w?/) { + @ALL_ARCHS = filter(qw/media neon_asm neon/); + @REQUIRES = filter(keys %required ? keys %required : qw/media/); + &require(@REQUIRES); + arm; +} elsif ($opts{arch} eq 'armv8' || $opts{arch} eq 'arm64' ) { + @ALL_ARCHS = filter(qw/neon/); + arm; +} else { + unoptimized; +} + +__END__ + +=head1 NAME + +rtcd - + +=head1 SYNOPSIS + +Usage: rtcd.pl [options] FILE + +See 'perldoc rtcd.pl' for more details. + +=head1 DESCRIPTION + +Reads the Run Time CPU Detections definitions from FILE and generates a +C header file on stdout. + +=head1 OPTIONS + +Options: + --arch=ARCH Architecture to generate defs for (required) + --disable-EXT Disable support for EXT extensions + --require-EXT Require support for EXT extensions + --sym=SYMBOL Unique symbol to use for RTCD initialization function + --config=FILE File with CONFIG_FOO=yes lines to parse
diff --git a/src/third_party/libvpx/build/make/thumb.pm b/src/third_party/libvpx/build/make/thumb.pm new file mode 100644 index 0000000..483c253 --- /dev/null +++ b/src/third_party/libvpx/build/make/thumb.pm
@@ -0,0 +1,70 @@ +#!/usr/bin/env perl +## +## Copyright (c) 2013 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## + +package thumb; + +sub FixThumbInstructions($$) +{ + my $short_branches = $_[1]; + my $branch_shift_offset = $short_branches ? 1 : 0; + + # Write additions with shifts, such as "add r10, r11, lsl #8", + # in three operand form, "add r10, r10, r11, lsl #8". + s/(add\s+)(r\d+),\s*(r\d+),\s*(lsl #\d+)/$1$2, $2, $3, $4/g; + + # Convert additions with a non-constant shift into a sequence + # with left shift, addition and a right shift (to restore the + # register to the original value). Currently the right shift + # isn't necessary in the code base since the values in these + # registers aren't used, but doing the shift for consistency. + # This converts instructions such as "add r12, r12, r5, lsl r4" + # into the sequence "lsl r5, r4", "add r12, r12, r5", "lsr r5, r4". + s/^(\s*)(add)(\s+)(r\d+),\s*(r\d+),\s*(r\d+),\s*lsl (r\d+)/$1lsl$3$6, $7\n$1$2$3$4, $5, $6\n$1lsr$3$6, $7/g; + + # Convert loads with right shifts in the indexing into a + # sequence of an add, load and sub. This converts + # "ldrb r4, [r9, lr, asr #1]" into "add r9, r9, lr, asr #1", + # "ldrb r9, [r9]", "sub r9, r9, lr, asr #1". + s/^(\s*)(ldrb)(\s+)(r\d+),\s*\[(\w+),\s*(\w+),\s*(asr #\d+)\]/$1add $3$5, $5, $6, $7\n$1$2$3$4, [$5]\n$1sub $3$5, $5, $6, $7/g; + + # Convert register indexing with writeback into a separate add + # instruction. This converts "ldrb r12, [r1, r2]!" into + # "ldrb r12, [r1, r2]", "add r1, r1, r2". + s/^(\s*)(ldrb)(\s+)(r\d+),\s*\[(\w+),\s*(\w+)\]!/$1$2$3$4, [$5, $6]\n$1add $3$5, $6/g; + + # Convert negative register indexing into separate sub/add instructions. + # This converts "ldrne r4, [src, -pstep, lsl #1]" into + # "subne src, src, pstep, lsl #1", "ldrne r4, [src]", + # "addne src, src, pstep, lsl #1". In a couple of cases where + # this is used, it's used for two subsequent load instructions, + # where a hand-written version of it could merge two subsequent + # add and sub instructions. + s/^(\s*)((ldr|str|pld)(ne)?)(\s+)(r\d+,\s*)?\[(\w+), -([^\]]+)\]/$1sub$4$5$7, $7, $8\n$1$2$5$6\[$7\]\n$1add$4$5$7, $7, $8/g; + + # Convert register post indexing to a separate add instruction. + # This converts "ldrneb r9, [r0], r2" into "ldrneb r9, [r0]", + # "addne r0, r0, r2". + s/^(\s*)((ldr|str)(ne)?[bhd]?)(\s+)(\w+),(\s*\w+,)?\s*\[(\w+)\],\s*(\w+)/$1$2$5$6,$7 [$8]\n$1add$4$5$8, $8, $9/g; + + # Convert a conditional addition to the pc register into a series of + # instructions. This converts "addlt pc, pc, r3, lsl #2" into + # "itttt lt", "movlt.n r12, pc", "addlt.w r12, #12", + # "addlt.w r12, r12, r3, lsl #2", "movlt.n pc, r12". + # This assumes that r12 is free at this point. + s/^(\s*)addlt(\s+)pc,\s*pc,\s*(\w+),\s*lsl\s*#(\d+)/$1itttt$2lt\n$1movlt.n$2r12, pc\n$1addlt.w$2r12, #12\n$1addlt.w$2r12, r12, $3, lsl #($4-$branch_shift_offset)\n$1movlt.n$2pc, r12/g; + + # Convert "mov pc, lr" into "bx lr", since the former only works + # for switching from arm to thumb (and only in armv7), but not + # from thumb to arm. + s/mov(\s*)pc\s*,\s*lr/bx$1lr/g; +} + +1;
diff --git a/src/third_party/libvpx/build/make/version.sh b/src/third_party/libvpx/build/make/version.sh new file mode 100755 index 0000000..6967527 --- /dev/null +++ b/src/third_party/libvpx/build/make/version.sh
@@ -0,0 +1,77 @@ +#!/bin/sh +## +## Copyright (c) 2010 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## + + + +for opt in "$@"; do + optval="${opt#*=}" + case "$opt" in + --bare) bare=true ;; + *) break ;; + esac + shift +done +source_path=${1:-.} +out_file=${2} +id=${3:-VERSION_STRING} + +git_version_id="" +if [ -e "${source_path}/.git" ]; then + # Source Path is a git working copy. Check for local modifications. + # Note that git submodules may have a file as .git, not a directory. + export GIT_DIR="${source_path}/.git" + git_version_id=`git describe --match=v[0-9]* 2>/dev/null` +fi + +changelog_version="" +for p in "${source_path}" "${source_path}/.."; do + if [ -z "$git_version_id" -a -f "${p}/CHANGELOG" ]; then + changelog_version=`head -n1 "${p}/CHANGELOG" | awk '{print $2}'` + changelog_version="${changelog_version}" + break + fi +done +version_str="${changelog_version}${git_version_id}" +bare_version=${version_str#v} +major_version=${bare_version%%.*} +bare_version=${bare_version#*.} +minor_version=${bare_version%%.*} +bare_version=${bare_version#*.} +patch_version=${bare_version%%-*} +bare_version=${bare_version#${patch_version}} +extra_version=${bare_version##-} + +#since they'll be used as integers below make sure they are or force to 0 +for v in major_version minor_version patch_version; do + if eval echo \$$v |grep -E -q '[^[:digit:]]'; then + eval $v=0 + fi +done + +if [ ${bare} ]; then + echo "${changelog_version}${git_version_id}" > $$.tmp +else + cat<<EOF>$$.tmp +#define VERSION_MAJOR $major_version +#define VERSION_MINOR $minor_version +#define VERSION_PATCH $patch_version +#define VERSION_EXTRA "$extra_version" +#define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH)) +#define ${id}_NOSP "${version_str}" +#define ${id} " ${version_str}" +EOF +fi +if [ -n "$out_file" ]; then +diff $$.tmp ${out_file} >/dev/null 2>&1 || cat $$.tmp > ${out_file} +else +cat $$.tmp +fi +rm $$.tmp
diff --git a/src/third_party/libvpx/codereview.settings b/src/third_party/libvpx/codereview.settings new file mode 100644 index 0000000..d7c8d39 --- /dev/null +++ b/src/third_party/libvpx/codereview.settings
@@ -0,0 +1,4 @@ +# This file is used by gcl to get repository specific information. +GERRIT_HOST: chromium-review.googlesource.com +GERRIT_PORT: 29418 +CODE_REVIEW_SERVER: chromium-review.googlesource.com
diff --git a/src/third_party/libvpx/configure b/src/third_party/libvpx/configure new file mode 100755 index 0000000..fb6dfca --- /dev/null +++ b/src/third_party/libvpx/configure
@@ -0,0 +1,751 @@ +#!/bin/sh +## +## configure +## +## This script is the front-end to the build system. It provides a similar +## interface to standard configure scripts with some extra bits for dealing +## with toolchains that differ from the standard POSIX interface and +## for extracting subsets of the source tree. In theory, reusable parts +## of this script were intended to live in build/make/configure.sh, +## but in practice, the line is pretty blurry. +## +## This build system is based in part on the FFmpeg configure script. +## + +#source_path="`dirname \"$0\"`" +source_path=${0%/*} +. "${source_path}/build/make/configure.sh" + +show_help(){ + show_help_pre + cat << EOF +Advanced options: + ${toggle_libs} libraries + ${toggle_examples} examples + ${toggle_docs} documentation + ${toggle_unit_tests} unit tests + ${toggle_decode_perf_tests} build decoder perf tests with unit tests + ${toggle_encode_perf_tests} build encoder perf tests with unit tests + --cpu=CPU tune for the specified CPU (ARM: cortex-a8, X86: sse3) + --libc=PATH path to alternate libc + --size-limit=WxH max size to allow in the decoder + --as={yasm|nasm|auto} use specified assembler [auto, yasm preferred] + --sdk-path=PATH path to root of sdk (android builds only) + ${toggle_codec_srcs} in/exclude codec library source code + ${toggle_debug_libs} in/exclude debug version of libraries + ${toggle_static_msvcrt} use static MSVCRT (VS builds only) + ${toggle_vp9_highbitdepth} use VP9 high bit depth (10/12) profiles + ${toggle_better_hw_compatibility} + enable encoder to produce streams with better + hardware decoder compatibility + ${toggle_vp8} VP8 codec support + ${toggle_vp9} VP9 codec support + ${toggle_vp10} VP10 codec support + ${toggle_internal_stats} output of encoder internal stats for debug, if supported (encoders) + ${toggle_postproc} postprocessing + ${toggle_vp9_postproc} vp9 specific postprocessing + ${toggle_multithread} multithreaded encoding and decoding + ${toggle_spatial_resampling} spatial sampling (scaling) support + ${toggle_realtime_only} enable this option while building for real-time encoding + ${toggle_onthefly_bitpacking} enable on-the-fly bitpacking in real-time encoding + ${toggle_error_concealment} enable this option to get a decoder which is able to conceal losses + ${toggle_coefficient_range_checking} + enable decoder to check if intermediate + transform coefficients are in valid range + ${toggle_runtime_cpu_detect} runtime cpu detection + ${toggle_shared} shared library support + ${toggle_static} static library support + ${toggle_small} favor smaller size over speed + ${toggle_postproc_visualizer} macro block / block level visualizers + ${toggle_multi_res_encoding} enable multiple-resolution encoding + ${toggle_temporal_denoising} enable temporal denoising and disable the spatial denoiser + ${toggle_vp9_temporal_denoising} + enable vp9 temporal denoising + ${toggle_webm_io} enable input from and output to WebM container + ${toggle_libyuv} enable libyuv + +Codecs: + Codecs can be selectively enabled or disabled individually, or by family: + --disable-<codec> + is equivalent to: + --disable-<codec>-encoder + --disable-<codec>-decoder + + Codecs available in this distribution: +EOF +#restore editor state ' + + family=""; + last_family=""; + c=""; + str=""; + for c in ${CODECS}; do + family=${c%_*} + if [ "${family}" != "${last_family}" ]; then + [ -z "${str}" ] || echo "${str}" + str="$(printf ' %10s:' ${family})" + fi + str="${str} $(printf '%10s' ${c#*_})" + last_family=${family} + done + echo "${str}" + show_help_post +} + +## +## BEGIN APPLICATION SPECIFIC CONFIGURATION +## + +# all_platforms is a list of all supported target platforms. Maintain +# alphabetically by architecture, generic-gnu last. +all_platforms="${all_platforms} armv6-linux-rvct" +all_platforms="${all_platforms} armv6-linux-gcc" +all_platforms="${all_platforms} armv6-none-rvct" +all_platforms="${all_platforms} arm64-darwin-gcc" +all_platforms="${all_platforms} arm64-linux-gcc" +all_platforms="${all_platforms} armv7-android-gcc" #neon Cortex-A8 +all_platforms="${all_platforms} armv7-darwin-gcc" #neon Cortex-A8 +all_platforms="${all_platforms} armv7-linux-rvct" #neon Cortex-A8 +all_platforms="${all_platforms} armv7-linux-gcc" #neon Cortex-A8 +all_platforms="${all_platforms} armv7-none-rvct" #neon Cortex-A8 +all_platforms="${all_platforms} armv7-win32-vs11" +all_platforms="${all_platforms} armv7-win32-vs12" +all_platforms="${all_platforms} armv7-win32-vs14" +all_platforms="${all_platforms} armv7s-darwin-gcc" +all_platforms="${all_platforms} mips32-linux-gcc" +all_platforms="${all_platforms} mips64-linux-gcc" +all_platforms="${all_platforms} sparc-solaris-gcc" +all_platforms="${all_platforms} x86-android-gcc" +all_platforms="${all_platforms} x86-darwin8-gcc" +all_platforms="${all_platforms} x86-darwin8-icc" +all_platforms="${all_platforms} x86-darwin9-gcc" +all_platforms="${all_platforms} x86-darwin9-icc" +all_platforms="${all_platforms} x86-darwin10-gcc" +all_platforms="${all_platforms} x86-darwin11-gcc" +all_platforms="${all_platforms} x86-darwin12-gcc" +all_platforms="${all_platforms} x86-darwin13-gcc" +all_platforms="${all_platforms} x86-darwin14-gcc" +all_platforms="${all_platforms} x86-darwin15-gcc" +all_platforms="${all_platforms} x86-iphonesimulator-gcc" +all_platforms="${all_platforms} x86-linux-gcc" +all_platforms="${all_platforms} x86-linux-icc" +all_platforms="${all_platforms} x86-os2-gcc" +all_platforms="${all_platforms} x86-solaris-gcc" +all_platforms="${all_platforms} x86-win32-gcc" +all_platforms="${all_platforms} x86-win32-vs7" +all_platforms="${all_platforms} x86-win32-vs8" +all_platforms="${all_platforms} x86-win32-vs9" +all_platforms="${all_platforms} x86-win32-vs10" +all_platforms="${all_platforms} x86-win32-vs11" +all_platforms="${all_platforms} x86-win32-vs12" +all_platforms="${all_platforms} x86-win32-vs14" +all_platforms="${all_platforms} x86_64-android-gcc" +all_platforms="${all_platforms} x86_64-darwin9-gcc" +all_platforms="${all_platforms} x86_64-darwin10-gcc" +all_platforms="${all_platforms} x86_64-darwin11-gcc" +all_platforms="${all_platforms} x86_64-darwin12-gcc" +all_platforms="${all_platforms} x86_64-darwin13-gcc" +all_platforms="${all_platforms} x86_64-darwin14-gcc" +all_platforms="${all_platforms} x86_64-darwin15-gcc" +all_platforms="${all_platforms} x86_64-iphonesimulator-gcc" +all_platforms="${all_platforms} x86_64-linux-gcc" +all_platforms="${all_platforms} x86_64-linux-icc" +all_platforms="${all_platforms} x86_64-orbis-clang" +all_platforms="${all_platforms} x86_64-solaris-gcc" +all_platforms="${all_platforms} x86_64-win64-gcc" +all_platforms="${all_platforms} x86_64-win64-vs8" +all_platforms="${all_platforms} x86_64-win64-vs9" +all_platforms="${all_platforms} x86_64-win64-vs10" +all_platforms="${all_platforms} x86_64-win64-vs11" +all_platforms="${all_platforms} x86_64-win64-vs12" +all_platforms="${all_platforms} x86_64-win64-vs14" +all_platforms="${all_platforms} generic-gnu" + +# all_targets is a list of all targets that can be configured +# note that these should be in dependency order for now. +all_targets="libs examples docs" + +# all targets available are enabled, by default. +for t in ${all_targets}; do + [ -f "${source_path}/${t}.mk" ] && enable_feature ${t} +done + +if ! perl --version >/dev/null; then + die "Perl is required to build" +fi + + +if [ "`cd \"${source_path}\" && pwd`" != "`pwd`" ]; then + # test to see if source_path already configured + if [ -f "${source_path}/vpx_config.h" ]; then + die "source directory already configured; run 'make distclean' there first" + fi +fi + +# check installed doxygen version +doxy_version=$(doxygen --version 2>/dev/null) +doxy_major=${doxy_version%%.*} +if [ ${doxy_major:-0} -ge 1 ]; then + doxy_version=${doxy_version#*.} + doxy_minor=${doxy_version%%.*} + doxy_patch=${doxy_version##*.} + + [ $doxy_major -gt 1 ] && enable_feature doxygen + [ $doxy_minor -gt 5 ] && enable_feature doxygen + [ $doxy_minor -eq 5 ] && [ $doxy_patch -ge 3 ] && enable_feature doxygen +fi + +# disable codecs when their source directory does not exist +[ -d "${source_path}/vp8" ] || disable_codec vp8 +[ -d "${source_path}/vp9" ] || disable_codec vp9 +[ -d "${source_path}/vp10" ] || disable_codec vp10 + +# disable vp10 codec by default +disable_codec vp10 + +# install everything except the sources, by default. sources will have +# to be enabled when doing dist builds, since that's no longer a common +# case. +enabled doxygen && enable_feature install_docs +enable_feature install_bins +enable_feature install_libs + +enable_feature static +enable_feature optimizations +enable_feature dependency_tracking +enable_feature spatial_resampling +enable_feature multithread +enable_feature os_support +enable_feature temporal_denoising + +CODECS=" + vp8_encoder + vp8_decoder + vp9_encoder + vp9_decoder + vp10_encoder + vp10_decoder +" +CODEC_FAMILIES=" + vp8 + vp9 + vp10 +" + +ARCH_LIST=" + arm + mips + x86 + x86_64 +" +ARCH_EXT_LIST_X86=" + mmx + sse + sse2 + sse3 + ssse3 + sse4_1 + avx + avx2 +" +ARCH_EXT_LIST=" + edsp + media + neon + neon_asm + + mips32 + dspr2 + msa + mips64 + + ${ARCH_EXT_LIST_X86} +" +HAVE_LIST=" + ${ARCH_EXT_LIST} + vpx_ports + pthread_h + unistd_h +" +EXPERIMENT_LIST=" + spatial_svc + fp_mb_stats + emulate_hardware + misc_fixes +" +CONFIG_LIST=" + dependency_tracking + external_build + install_docs + install_bins + install_libs + install_srcs + use_x86inc + debug + gprof + gcov + rvct + gcc + msvs + pic + big_endian + + codec_srcs + debug_libs + + dequant_tokens + dc_recon + runtime_cpu_detect + postproc + vp9_postproc + multithread + internal_stats + ${CODECS} + ${CODEC_FAMILIES} + encoders + decoders + static_msvcrt + spatial_resampling + realtime_only + onthefly_bitpacking + error_concealment + shared + static + small + postproc_visualizer + os_support + unit_tests + webm_io + libyuv + decode_perf_tests + encode_perf_tests + multi_res_encoding + temporal_denoising + vp9_temporal_denoising + coefficient_range_checking + vp9_highbitdepth + better_hw_compatibility + experimental + size_limit + ${EXPERIMENT_LIST} +" +CMDLINE_SELECT=" + dependency_tracking + external_build + extra_warnings + werror + install_docs + install_bins + install_libs + install_srcs + debug + gprof + gcov + pic + use_x86inc + optimizations + ccache + runtime_cpu_detect + thumb + + libs + examples + docs + libc + as + size_limit + codec_srcs + debug_libs + + dequant_tokens + dc_recon + postproc + vp9_postproc + multithread + internal_stats + ${CODECS} + ${CODEC_FAMILIES} + static_msvcrt + spatial_resampling + realtime_only + onthefly_bitpacking + error_concealment + shared + static + small + postproc_visualizer + unit_tests + webm_io + libyuv + decode_perf_tests + encode_perf_tests + multi_res_encoding + temporal_denoising + vp9_temporal_denoising + coefficient_range_checking + better_hw_compatibility + vp9_highbitdepth + experimental +" + +process_cmdline() { + for opt do + optval="${opt#*=}" + case "$opt" in + --disable-codecs) + for c in ${CODEC_FAMILIES}; do disable_codec $c; done + ;; + --enable-?*|--disable-?*) + eval `echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g'` + if is_in ${option} ${EXPERIMENT_LIST}; then + if enabled experimental; then + ${action}_feature $option + else + log_echo "Ignoring $opt -- not in experimental mode." + fi + elif is_in ${option} "${CODECS} ${CODEC_FAMILIES}"; then + ${action}_codec ${option} + else + process_common_cmdline $opt + fi + ;; + *) process_common_cmdline "$opt" + ;; + esac + done +} + +post_process_cmdline() { + c="" + + # Enable all detected codecs, if they haven't been disabled + for c in ${CODECS}; do soft_enable $c; done + + # Enable the codec family if any component of that family is enabled + for c in ${CODECS}; do + enabled $c && enable_feature ${c%_*} + done + + # Set the {en,de}coders variable if any algorithm in that class is enabled + for c in ${CODECS}; do + enabled ${c} && enable_feature ${c##*_}s + done +} + + +process_targets() { + enabled child || write_common_config_banner + write_common_target_config_h ${BUILD_PFX}vpx_config.h + write_common_config_targets + + # Calculate the default distribution name, based on the enabled features + cf="" + DIST_DIR=vpx + for cf in $CODEC_FAMILIES; do + if enabled ${cf}_encoder && enabled ${cf}_decoder; then + DIST_DIR="${DIST_DIR}-${cf}" + elif enabled ${cf}_encoder; then + DIST_DIR="${DIST_DIR}-${cf}cx" + elif enabled ${cf}_decoder; then + DIST_DIR="${DIST_DIR}-${cf}dx" + fi + done + enabled debug_libs && DIST_DIR="${DIST_DIR}-debug" + enabled codec_srcs && DIST_DIR="${DIST_DIR}-src" + ! enabled postproc && ! enabled vp9_postproc && DIST_DIR="${DIST_DIR}-nopost" + ! enabled multithread && DIST_DIR="${DIST_DIR}-nomt" + ! enabled install_docs && DIST_DIR="${DIST_DIR}-nodocs" + DIST_DIR="${DIST_DIR}-${tgt_isa}-${tgt_os}" + case "${tgt_os}" in + win*) enabled static_msvcrt && DIST_DIR="${DIST_DIR}mt" || DIST_DIR="${DIST_DIR}md" + DIST_DIR="${DIST_DIR}-${tgt_cc}" + ;; + esac + if [ -f "${source_path}/build/make/version.sh" ]; then + ver=`"$source_path/build/make/version.sh" --bare "$source_path"` + DIST_DIR="${DIST_DIR}-${ver}" + VERSION_STRING=${ver} + ver=${ver%%-*} + VERSION_PATCH=${ver##*.} + ver=${ver%.*} + VERSION_MINOR=${ver##*.} + ver=${ver#v} + VERSION_MAJOR=${ver%.*} + fi + enabled child || cat <<EOF >> config.mk + +PREFIX=${prefix} +ifeq (\$(MAKECMDGOALS),dist) +DIST_DIR?=${DIST_DIR} +else +DIST_DIR?=\$(DESTDIR)${prefix} +endif +LIBSUBDIR=${libdir##${prefix}/} + +VERSION_STRING=${VERSION_STRING} + +VERSION_MAJOR=${VERSION_MAJOR} +VERSION_MINOR=${VERSION_MINOR} +VERSION_PATCH=${VERSION_PATCH} + +CONFIGURE_ARGS=${CONFIGURE_ARGS} +EOF + enabled child || echo "CONFIGURE_ARGS?=${CONFIGURE_ARGS}" >> config.mk + + # + # Write makefiles for all enabled targets + # + for tgt in libs examples docs solution; do + tgt_fn="$tgt-$toolchain.mk" + + if enabled $tgt; then + echo "Creating makefiles for ${toolchain} ${tgt}" + write_common_target_config_mk $tgt_fn ${BUILD_PFX}vpx_config.h + #write_${tgt}_config + fi + done + +} + +process_detect() { + if enabled shared; then + # Can only build shared libs on a subset of platforms. Doing this check + # here rather than at option parse time because the target auto-detect + # magic happens after the command line has been parsed. + case "${tgt_os}" in + linux|os2|darwin*|iphonesimulator*) + # Supported platforms + ;; + *) + if enabled gnu; then + echo "--enable-shared is only supported on ELF; assuming this is OK" + else + die "--enable-shared only supported on ELF, OS/2, and Darwin for now" + fi + ;; + esac + fi + if [ -z "$CC" ] || enabled external_build; then + echo "Bypassing toolchain for environment detection." + enable_feature external_build + check_header() { + log fake_check_header "$@" + header=$1 + shift + var=`echo $header | sed 's/[^A-Za-z0-9_]/_/g'` + disable_feature $var + # Headers common to all environments + case $header in + stdio.h) + true; + ;; + *) + result=false + for d in "$@"; do + [ -f "${d##-I}/$header" ] && result=true && break + done + ${result:-true} + esac && enable_feature $var + + # Specialize windows and POSIX environments. + case $toolchain in + *-win*-*) + # Don't check for any headers in Windows builds. + false + ;; + *) + case $header in + pthread.h) true;; + unistd.h) true;; + *) false;; + esac && enable_feature $var + esac + enabled $var + } + check_ld() { + true + } + fi + check_header stdio.h || die "Unable to invoke compiler: ${CC} ${CFLAGS}" + check_ld <<EOF || die "Toolchain is unable to link executables" +int main(void) {return 0;} +EOF + # check system headers + check_header pthread.h + check_header unistd.h # for sysconf(3) and friends. + + check_header vpx/vpx_integer.h -I${source_path} && enable_feature vpx_ports +} + +process_toolchain() { + process_common_toolchain + + # Enable some useful compiler flags + if enabled gcc; then + enabled werror && check_add_cflags -Werror + check_add_cflags -Wall + check_add_cflags -Wdeclaration-after-statement + check_add_cflags -Wdisabled-optimization + check_add_cflags -Wpointer-arith + check_add_cflags -Wtype-limits + check_add_cflags -Wcast-qual + check_add_cflags -Wvla + check_add_cflags -Wimplicit-function-declaration + check_add_cflags -Wuninitialized + check_add_cflags -Wunused-variable + case ${CC} in + *clang*) + # libvpx and/or clang have issues with aliasing: + # https://code.google.com/p/webm/issues/detail?id=603 + # work around them until they are fixed + check_add_cflags -fno-strict-aliasing + ;; + *) check_add_cflags -Wunused-but-set-variable ;; + esac + if enabled mips || [ -z "${INLINE}" ]; then + enabled extra_warnings || check_add_cflags -Wno-unused-function + else + check_add_cflags -Wunused-function + fi + fi + + if enabled icc; then + enabled werror && check_add_cflags -Werror + check_add_cflags -Wall + check_add_cflags -Wpointer-arith + + # ICC has a number of floating point optimizations that we disable + # in favor of deterministic output WRT to other compilers + add_cflags -fp-model precise + fi + + # Enable extra, harmless warnings. These might provide additional insight + # to what the compiler is doing and why, but in general, but they shouldn't + # be treated as fatal, even if we're treating warnings as errors. + GCC_EXTRA_WARNINGS=" + -Wdisabled-optimization + -Winline + " + enabled gcc && EXTRA_WARNINGS="${GCC_EXTRA_WARNINGS}" + RVCT_EXTRA_WARNINGS=" + --remarks + " + enabled rvct && EXTRA_WARNINGS="${RVCT_EXTRA_WARNINGS}" + if enabled extra_warnings; then + for w in ${EXTRA_WARNINGS}; do + check_add_cflags ${w} + enabled gcc && enabled werror && check_add_cflags -Wno-error=${w} + done + fi + + # ccache only really works on gcc toolchains + enabled gcc || soft_disable ccache + if enabled mips; then + enable_feature dequant_tokens + enable_feature dc_recon + fi + + if enabled internal_stats; then + enable_feature vp9_postproc + fi + + # Enable the postbuild target if building for visual studio. + case "$tgt_cc" in + vs*) enable_feature msvs + enable_feature solution + vs_version=${tgt_cc##vs} + case $vs_version in + [789]) + VCPROJ_SFX=vcproj + gen_vcproj_cmd=${source_path}/build/make/gen_msvs_proj.sh + ;; + 10|11|12|14) + VCPROJ_SFX=vcxproj + gen_vcproj_cmd=${source_path}/build/make/gen_msvs_vcxproj.sh + enabled werror && gen_vcproj_cmd="${gen_vcproj_cmd} --enable-werror" + ;; + esac + all_targets="${all_targets} solution" + INLINE="__forceinline" + ;; + esac + + # Other toolchain specific defaults + case $toolchain in x86*) soft_enable postproc;; esac + + if enabled postproc_visualizer; then + enabled postproc || die "postproc_visualizer requires postproc to be enabled" + fi + + # Enable unit tests by default if we have a working C++ compiler. + case "$toolchain" in + *-vs*) + soft_enable unit_tests + soft_enable webm_io + soft_enable libyuv + ;; + *-android-*) + soft_enable webm_io + soft_enable libyuv + # GTestLog must be modified to use Android logging utilities. + ;; + *-darwin-*) + # iOS/ARM builds do not work with gtest. This does not match + # x86 targets. + ;; + *-iphonesimulator-*) + soft_enable webm_io + soft_enable libyuv + ;; + *-win*) + # Some mingw toolchains don't have pthread available by default. + # Treat these more like visual studio where threading in gtest + # would be disabled for the same reason. + check_cxx "$@" <<EOF && soft_enable unit_tests +int z; +EOF + check_cxx "$@" <<EOF && soft_enable webm_io +int z; +EOF + check_cxx "$@" <<EOF && soft_enable libyuv +int z; +EOF + ;; + *) + enabled pthread_h && check_cxx "$@" <<EOF && soft_enable unit_tests +int z; +EOF + check_cxx "$@" <<EOF && soft_enable webm_io +int z; +EOF + check_cxx "$@" <<EOF && soft_enable libyuv +int z; +EOF + ;; + esac + # libwebm needs to be linked with C++ standard library + enabled webm_io && LD=${CXX} + + # append any user defined extra cflags + if [ -n "${extra_cflags}" ] ; then + check_add_cflags ${extra_cflags} || \ + die "Requested extra CFLAGS '${extra_cflags}' not supported by compiler" + fi + if [ -n "${extra_cxxflags}" ]; then + check_add_cxxflags ${extra_cxxflags} || \ + die "Requested extra CXXFLAGS '${extra_cxxflags}' not supported by compiler" + fi +} + + +## +## END APPLICATION SPECIFIC CONFIGURATION +## +CONFIGURE_ARGS="$@" +process "$@" +print_webm_license ${BUILD_PFX}vpx_config.c "/*" " */" +cat <<EOF >> ${BUILD_PFX}vpx_config.c +#include "vpx/vpx_codec.h" +static const char* const cfg = "$CONFIGURE_ARGS"; +const char *vpx_codec_build_config(void) {return cfg;} +EOF
diff --git a/src/third_party/libvpx/docs.mk b/src/third_party/libvpx/docs.mk new file mode 100644 index 0000000..889d182 --- /dev/null +++ b/src/third_party/libvpx/docs.mk
@@ -0,0 +1,48 @@ +## +## Copyright (c) 2010 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## + + +INSTALL_MAPS += docs/% docs/% +INSTALL_MAPS += src/% % +INSTALL_MAPS += % % + +# Static documentation authored in doxygen +CODEC_DOX := mainpage.dox \ + keywords.dox \ + usage.dox \ + usage_cx.dox \ + usage_dx.dox \ + +# Other doxy files sourced in Markdown +TXT_DOX = $(call enabled,TXT_DOX) + +EXAMPLE_PATH += $(SRC_PATH_BARE) #for CHANGELOG, README, etc +EXAMPLE_PATH += $(SRC_PATH_BARE)/examples + +doxyfile: $(if $(findstring examples, $(ALL_TARGETS)),examples.doxy) +doxyfile: libs.doxy_template libs.doxy + @echo " [CREATE] $@" + @cat $^ > $@ + @echo "STRIP_FROM_PATH += $(SRC_PATH_BARE) $(BUILD_ROOT)" >> $@ + @echo "INPUT += $(addprefix $(SRC_PATH_BARE)/,$(CODEC_DOX))" >> $@; + @echo "INPUT += $(TXT_DOX)" >> $@; + @echo "EXAMPLE_PATH += $(EXAMPLE_PATH)" >> $@ + +CLEAN-OBJS += doxyfile $(wildcard docs/html/*) +docs/html/index.html: doxyfile $(CODEC_DOX) $(TXT_DOX) + @echo " [DOXYGEN] $<" + @doxygen $< +DOCS-yes += docs/html/index.html + +DIST-DOCS-yes = $(wildcard docs/html/*) +DIST-DOCS-$(CONFIG_CODEC_SRCS) += $(addprefix src/,$(CODEC_DOX)) +DIST-DOCS-$(CONFIG_CODEC_SRCS) += src/libs.doxy_template +DIST-DOCS-yes += CHANGELOG +DIST-DOCS-yes += README
diff --git a/src/third_party/libvpx/examples.mk b/src/third_party/libvpx/examples.mk new file mode 100644 index 0000000..c891a54 --- /dev/null +++ b/src/third_party/libvpx/examples.mk
@@ -0,0 +1,393 @@ +## +## Copyright (c) 2010 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## + +LIBYUV_SRCS += third_party/libyuv/include/libyuv/basic_types.h \ + third_party/libyuv/include/libyuv/convert.h \ + third_party/libyuv/include/libyuv/convert_argb.h \ + third_party/libyuv/include/libyuv/convert_from.h \ + third_party/libyuv/include/libyuv/cpu_id.h \ + third_party/libyuv/include/libyuv/planar_functions.h \ + third_party/libyuv/include/libyuv/rotate.h \ + third_party/libyuv/include/libyuv/row.h \ + third_party/libyuv/include/libyuv/scale.h \ + third_party/libyuv/include/libyuv/scale_row.h \ + third_party/libyuv/source/cpu_id.cc \ + third_party/libyuv/source/planar_functions.cc \ + third_party/libyuv/source/row_any.cc \ + third_party/libyuv/source/row_common.cc \ + third_party/libyuv/source/row_gcc.cc \ + third_party/libyuv/source/row_mips.cc \ + third_party/libyuv/source/row_neon.cc \ + third_party/libyuv/source/row_neon64.cc \ + third_party/libyuv/source/row_win.cc \ + third_party/libyuv/source/scale.cc \ + third_party/libyuv/source/scale_any.cc \ + third_party/libyuv/source/scale_common.cc \ + third_party/libyuv/source/scale_gcc.cc \ + third_party/libyuv/source/scale_mips.cc \ + third_party/libyuv/source/scale_neon.cc \ + third_party/libyuv/source/scale_neon64.cc \ + third_party/libyuv/source/scale_win.cc \ + +LIBWEBM_COMMON_SRCS += third_party/libwebm/common/hdr_util.cc \ + third_party/libwebm/common/hdr_util.h \ + third_party/libwebm/common/webmids.h + +LIBWEBM_MUXER_SRCS += third_party/libwebm/mkvmuxer/mkvmuxer.cc \ + third_party/libwebm/mkvmuxer/mkvmuxerutil.cc \ + third_party/libwebm/mkvmuxer/mkvwriter.cc \ + third_party/libwebm/mkvmuxer/mkvmuxer.h \ + third_party/libwebm/mkvmuxer/mkvmuxertypes.h \ + third_party/libwebm/mkvmuxer/mkvmuxerutil.h \ + third_party/libwebm/mkvparser/mkvparser.h \ + third_party/libwebm/mkvmuxer/mkvwriter.h + +LIBWEBM_PARSER_SRCS = third_party/libwebm/mkvparser/mkvparser.cc \ + third_party/libwebm/mkvparser/mkvreader.cc \ + third_party/libwebm/mkvparser/mkvparser.h \ + third_party/libwebm/mkvparser/mkvreader.h + +# Add compile flags and include path for libwebm sources. +ifeq ($(CONFIG_WEBM_IO),yes) + CXXFLAGS += -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS + INC_PATH-yes += $(SRC_PATH_BARE)/third_party/libwebm +endif + + +# List of examples to build. UTILS are tools meant for distribution +# while EXAMPLES demonstrate specific portions of the API. +UTILS-$(CONFIG_DECODERS) += vpxdec.c +vpxdec.SRCS += md5_utils.c md5_utils.h +vpxdec.SRCS += vpx_ports/mem_ops.h +vpxdec.SRCS += vpx_ports/mem_ops_aligned.h +vpxdec.SRCS += vpx_ports/msvc.h +vpxdec.SRCS += vpx_ports/vpx_timer.h +vpxdec.SRCS += vpx/vpx_integer.h +vpxdec.SRCS += args.c args.h +vpxdec.SRCS += ivfdec.c ivfdec.h +vpxdec.SRCS += tools_common.c tools_common.h +vpxdec.SRCS += y4menc.c y4menc.h +ifeq ($(CONFIG_LIBYUV),yes) + vpxdec.SRCS += $(LIBYUV_SRCS) +endif +ifeq ($(CONFIG_WEBM_IO),yes) + vpxdec.SRCS += $(LIBWEBM_COMMON_SRCS) + vpxdec.SRCS += $(LIBWEBM_MUXER_SRCS) + vpxdec.SRCS += $(LIBWEBM_PARSER_SRCS) + vpxdec.SRCS += webmdec.cc webmdec.h +endif +vpxdec.GUID = BA5FE66F-38DD-E034-F542-B1578C5FB950 +vpxdec.DESCRIPTION = Full featured decoder +UTILS-$(CONFIG_ENCODERS) += vpxenc.c +vpxenc.SRCS += args.c args.h y4minput.c y4minput.h vpxenc.h +vpxenc.SRCS += ivfdec.c ivfdec.h +vpxenc.SRCS += ivfenc.c ivfenc.h +vpxenc.SRCS += rate_hist.c rate_hist.h +vpxenc.SRCS += tools_common.c tools_common.h +vpxenc.SRCS += warnings.c warnings.h +vpxenc.SRCS += vpx_ports/mem_ops.h +vpxenc.SRCS += vpx_ports/mem_ops_aligned.h +vpxenc.SRCS += vpx_ports/msvc.h +vpxenc.SRCS += vpx_ports/vpx_timer.h +vpxenc.SRCS += vpxstats.c vpxstats.h +ifeq ($(CONFIG_LIBYUV),yes) + vpxenc.SRCS += $(LIBYUV_SRCS) +endif +ifeq ($(CONFIG_WEBM_IO),yes) + vpxenc.SRCS += $(LIBWEBM_COMMON_SRCS) + vpxenc.SRCS += $(LIBWEBM_MUXER_SRCS) + vpxenc.SRCS += $(LIBWEBM_PARSER_SRCS) + vpxenc.SRCS += webmenc.cc webmenc.h +endif +vpxenc.GUID = 548DEC74-7A15-4B2B-AFC3-AA102E7C25C1 +vpxenc.DESCRIPTION = Full featured encoder +ifeq ($(CONFIG_SPATIAL_SVC),yes) + EXAMPLES-$(CONFIG_VP9_ENCODER) += vp9_spatial_svc_encoder.c + vp9_spatial_svc_encoder.SRCS += args.c args.h + vp9_spatial_svc_encoder.SRCS += ivfenc.c ivfenc.h + vp9_spatial_svc_encoder.SRCS += tools_common.c tools_common.h + vp9_spatial_svc_encoder.SRCS += video_common.h + vp9_spatial_svc_encoder.SRCS += video_writer.h video_writer.c + vp9_spatial_svc_encoder.SRCS += vpx_ports/msvc.h + vp9_spatial_svc_encoder.SRCS += vpxstats.c vpxstats.h + vp9_spatial_svc_encoder.GUID = 4A38598D-627D-4505-9C7B-D4020C84100D + vp9_spatial_svc_encoder.DESCRIPTION = VP9 Spatial SVC Encoder +endif + +ifneq ($(CONFIG_SHARED),yes) +EXAMPLES-$(CONFIG_VP9_ENCODER) += resize_util.c +endif + +EXAMPLES-$(CONFIG_ENCODERS) += vpx_temporal_svc_encoder.c +vpx_temporal_svc_encoder.SRCS += ivfenc.c ivfenc.h +vpx_temporal_svc_encoder.SRCS += tools_common.c tools_common.h +vpx_temporal_svc_encoder.SRCS += video_common.h +vpx_temporal_svc_encoder.SRCS += video_writer.h video_writer.c +vpx_temporal_svc_encoder.SRCS += vpx_ports/msvc.h +vpx_temporal_svc_encoder.GUID = B18C08F2-A439-4502-A78E-849BE3D60947 +vpx_temporal_svc_encoder.DESCRIPTION = Temporal SVC Encoder +EXAMPLES-$(CONFIG_DECODERS) += simple_decoder.c +simple_decoder.GUID = D3BBF1E9-2427-450D-BBFF-B2843C1D44CC +simple_decoder.SRCS += ivfdec.h ivfdec.c +simple_decoder.SRCS += tools_common.h tools_common.c +simple_decoder.SRCS += video_common.h +simple_decoder.SRCS += video_reader.h video_reader.c +simple_decoder.SRCS += vpx_ports/mem_ops.h +simple_decoder.SRCS += vpx_ports/mem_ops_aligned.h +simple_decoder.SRCS += vpx_ports/msvc.h +simple_decoder.DESCRIPTION = Simplified decoder loop +EXAMPLES-$(CONFIG_DECODERS) += postproc.c +postproc.SRCS += ivfdec.h ivfdec.c +postproc.SRCS += tools_common.h tools_common.c +postproc.SRCS += video_common.h +postproc.SRCS += video_reader.h video_reader.c +postproc.SRCS += vpx_ports/mem_ops.h +postproc.SRCS += vpx_ports/mem_ops_aligned.h +postproc.SRCS += vpx_ports/msvc.h +postproc.GUID = 65E33355-F35E-4088-884D-3FD4905881D7 +postproc.DESCRIPTION = Decoder postprocessor control +EXAMPLES-$(CONFIG_DECODERS) += decode_to_md5.c +decode_to_md5.SRCS += md5_utils.h md5_utils.c +decode_to_md5.SRCS += ivfdec.h ivfdec.c +decode_to_md5.SRCS += tools_common.h tools_common.c +decode_to_md5.SRCS += video_common.h +decode_to_md5.SRCS += video_reader.h video_reader.c +decode_to_md5.SRCS += vpx_ports/mem_ops.h +decode_to_md5.SRCS += vpx_ports/mem_ops_aligned.h +decode_to_md5.SRCS += vpx_ports/msvc.h +decode_to_md5.GUID = 59120B9B-2735-4BFE-B022-146CA340FE42 +decode_to_md5.DESCRIPTION = Frame by frame MD5 checksum +EXAMPLES-$(CONFIG_ENCODERS) += simple_encoder.c +simple_encoder.SRCS += ivfenc.h ivfenc.c +simple_encoder.SRCS += tools_common.h tools_common.c +simple_encoder.SRCS += video_common.h +simple_encoder.SRCS += video_writer.h video_writer.c +simple_encoder.SRCS += vpx_ports/msvc.h +simple_encoder.GUID = 4607D299-8A71-4D2C-9B1D-071899B6FBFD +simple_encoder.DESCRIPTION = Simplified encoder loop +EXAMPLES-$(CONFIG_VP9_ENCODER) += vp9_lossless_encoder.c +vp9_lossless_encoder.SRCS += ivfenc.h ivfenc.c +vp9_lossless_encoder.SRCS += tools_common.h tools_common.c +vp9_lossless_encoder.SRCS += video_common.h +vp9_lossless_encoder.SRCS += video_writer.h video_writer.c +vp9_lossless_encoder.SRCS += vpx_ports/msvc.h +vp9_lossless_encoder.GUID = B63C7C88-5348-46DC-A5A6-CC151EF93366 +vp9_lossless_encoder.DESCRIPTION = Simplified lossless VP9 encoder +EXAMPLES-$(CONFIG_ENCODERS) += twopass_encoder.c +twopass_encoder.SRCS += ivfenc.h ivfenc.c +twopass_encoder.SRCS += tools_common.h tools_common.c +twopass_encoder.SRCS += video_common.h +twopass_encoder.SRCS += video_writer.h video_writer.c +twopass_encoder.SRCS += vpx_ports/msvc.h +twopass_encoder.GUID = 73494FA6-4AF9-4763-8FBB-265C92402FD8 +twopass_encoder.DESCRIPTION = Two-pass encoder loop +EXAMPLES-$(CONFIG_DECODERS) += decode_with_drops.c +decode_with_drops.SRCS += ivfdec.h ivfdec.c +decode_with_drops.SRCS += tools_common.h tools_common.c +decode_with_drops.SRCS += video_common.h +decode_with_drops.SRCS += video_reader.h video_reader.c +decode_with_drops.SRCS += vpx_ports/mem_ops.h +decode_with_drops.SRCS += vpx_ports/mem_ops_aligned.h +decode_with_drops.SRCS += vpx_ports/msvc.h +decode_with_drops.GUID = CE5C53C4-8DDA-438A-86ED-0DDD3CDB8D26 +decode_with_drops.DESCRIPTION = Drops frames while decoding +EXAMPLES-$(CONFIG_ENCODERS) += set_maps.c +set_maps.SRCS += ivfenc.h ivfenc.c +set_maps.SRCS += tools_common.h tools_common.c +set_maps.SRCS += video_common.h +set_maps.SRCS += video_writer.h video_writer.c +set_maps.SRCS += vpx_ports/msvc.h +set_maps.GUID = ECB2D24D-98B8-4015-A465-A4AF3DCC145F +set_maps.DESCRIPTION = Set active and ROI maps +EXAMPLES-$(CONFIG_VP8_ENCODER) += vp8cx_set_ref.c +vp8cx_set_ref.SRCS += ivfenc.h ivfenc.c +vp8cx_set_ref.SRCS += tools_common.h tools_common.c +vp8cx_set_ref.SRCS += video_common.h +vp8cx_set_ref.SRCS += video_writer.h video_writer.c +vp8cx_set_ref.SRCS += vpx_ports/msvc.h +vp8cx_set_ref.GUID = C5E31F7F-96F6-48BD-BD3E-10EBF6E8057A +vp8cx_set_ref.DESCRIPTION = VP8 set encoder reference frame + + +ifeq ($(CONFIG_MULTI_RES_ENCODING),yes) +ifeq ($(CONFIG_LIBYUV),yes) +EXAMPLES-$(CONFIG_VP8_ENCODER) += vp8_multi_resolution_encoder.c +vp8_multi_resolution_encoder.SRCS += ivfenc.h ivfenc.c +vp8_multi_resolution_encoder.SRCS += tools_common.h tools_common.c +vp8_multi_resolution_encoder.SRCS += video_writer.h video_writer.c +vp8_multi_resolution_encoder.SRCS += vpx_ports/msvc.h +vp8_multi_resolution_encoder.SRCS += $(LIBYUV_SRCS) +vp8_multi_resolution_encoder.GUID = 04f8738e-63c8-423b-90fa-7c2703a374de +vp8_multi_resolution_encoder.DESCRIPTION = VP8 Multiple-resolution Encoding +endif +endif + +# Handle extra library flags depending on codec configuration + +# We should not link to math library (libm) on RVCT +# when building for bare-metal targets +ifeq ($(CONFIG_OS_SUPPORT), yes) +CODEC_EXTRA_LIBS-$(CONFIG_VP8) += m +CODEC_EXTRA_LIBS-$(CONFIG_VP9) += m +else + ifeq ($(CONFIG_GCC), yes) + CODEC_EXTRA_LIBS-$(CONFIG_VP8) += m + CODEC_EXTRA_LIBS-$(CONFIG_VP9) += m + endif +endif +# +# End of specified files. The rest of the build rules should happen +# automagically from here. +# + + +# Examples need different flags based on whether we're building +# from an installed tree or a version controlled tree. Determine +# the proper paths. +ifeq ($(HAVE_ALT_TREE_LAYOUT),yes) + LIB_PATH-yes := $(SRC_PATH_BARE)/../lib + INC_PATH-yes := $(SRC_PATH_BARE)/../include +else + LIB_PATH-yes += $(if $(BUILD_PFX),$(BUILD_PFX),.) + INC_PATH-$(CONFIG_VP8_DECODER) += $(SRC_PATH_BARE)/vp8 + INC_PATH-$(CONFIG_VP8_ENCODER) += $(SRC_PATH_BARE)/vp8 + INC_PATH-$(CONFIG_VP9_DECODER) += $(SRC_PATH_BARE)/vp9 + INC_PATH-$(CONFIG_VP9_ENCODER) += $(SRC_PATH_BARE)/vp9 +endif +INC_PATH-$(CONFIG_LIBYUV) += $(SRC_PATH_BARE)/third_party/libyuv/include +LIB_PATH := $(call enabled,LIB_PATH) +INC_PATH := $(call enabled,INC_PATH) +INTERNAL_CFLAGS = $(addprefix -I,$(INC_PATH)) +INTERNAL_LDFLAGS += $(addprefix -L,$(LIB_PATH)) + + +# Expand list of selected examples to build (as specified above) +UTILS = $(call enabled,UTILS) +EXAMPLES = $(addprefix examples/,$(call enabled,EXAMPLES)) +ALL_EXAMPLES = $(UTILS) $(EXAMPLES) +UTIL_SRCS = $(foreach ex,$(UTILS),$($(ex:.c=).SRCS)) +ALL_SRCS = $(foreach ex,$(ALL_EXAMPLES),$($(notdir $(ex:.c=)).SRCS)) +CODEC_EXTRA_LIBS=$(sort $(call enabled,CODEC_EXTRA_LIBS)) + + +# Expand all example sources into a variable containing all sources +# for that example (not just them main one specified in UTILS/EXAMPLES) +# and add this file to the list (for MSVS workspace generation) +$(foreach ex,$(ALL_EXAMPLES),$(eval $(notdir $(ex:.c=)).SRCS += $(ex) examples.mk)) + + +# Create build/install dependencies for all examples. The common case +# is handled here. The MSVS case is handled below. +NOT_MSVS = $(if $(CONFIG_MSVS),,yes) +DIST-BINS-$(NOT_MSVS) += $(addprefix bin/,$(ALL_EXAMPLES:.c=$(EXE_SFX))) +INSTALL-BINS-$(NOT_MSVS) += $(addprefix bin/,$(UTILS:.c=$(EXE_SFX))) +DIST-SRCS-yes += $(ALL_SRCS) +INSTALL-SRCS-yes += $(UTIL_SRCS) +OBJS-$(NOT_MSVS) += $(call objs,$(ALL_SRCS)) +BINS-$(NOT_MSVS) += $(addprefix $(BUILD_PFX),$(ALL_EXAMPLES:.c=$(EXE_SFX))) + + +# Instantiate linker template for all examples. +CODEC_LIB=$(if $(CONFIG_DEBUG_LIBS),vpx_g,vpx) +ifneq ($(filter darwin%,$(TGT_OS)),) +SHARED_LIB_SUF=.dylib +else +ifneq ($(filter os2%,$(TGT_OS)),) +SHARED_LIB_SUF=_dll.a +else +SHARED_LIB_SUF=.so +endif +endif +CODEC_LIB_SUF=$(if $(CONFIG_SHARED),$(SHARED_LIB_SUF),.a) +$(foreach bin,$(BINS-yes),\ + $(eval $(bin):$(LIB_PATH)/lib$(CODEC_LIB)$(CODEC_LIB_SUF))\ + $(eval $(call linker_template,$(bin),\ + $(call objs,$($(notdir $(bin:$(EXE_SFX)=)).SRCS)) \ + -l$(CODEC_LIB) $(addprefix -l,$(CODEC_EXTRA_LIBS))\ + ))) + +# The following pairs define a mapping of locations in the distribution +# tree to locations in the source/build trees. +INSTALL_MAPS += src/%.c %.c +INSTALL_MAPS += src/% $(SRC_PATH_BARE)/% +INSTALL_MAPS += bin/% % +INSTALL_MAPS += % % + + +# Set up additional MSVS environment +ifeq ($(CONFIG_MSVS),yes) +CODEC_LIB=$(if $(CONFIG_SHARED),vpx,$(if $(CONFIG_STATIC_MSVCRT),vpxmt,vpxmd)) +# This variable uses deferred expansion intentionally, since the results of +# $(wildcard) may change during the course of the Make. +VS_PLATFORMS = $(foreach d,$(wildcard */Release/$(CODEC_LIB).lib),$(word 1,$(subst /, ,$(d)))) +INSTALL_MAPS += $(foreach p,$(VS_PLATFORMS),bin/$(p)/% $(p)/Release/%) +endif + +# Build Visual Studio Projects. We use a template here to instantiate +# explicit rules rather than using an implicit rule because we want to +# leverage make's VPATH searching rather than specifying the paths on +# each file in ALL_EXAMPLES. This has the unfortunate side effect that +# touching the source files trigger a rebuild of the project files +# even though there is no real dependency there (the dependency is on +# the makefiles). We may want to revisit this. +define vcproj_template +$(1): $($(1:.$(VCPROJ_SFX)=).SRCS) vpx.$(VCPROJ_SFX) + $(if $(quiet),@echo " [vcproj] $$@") + $(qexec)$$(GEN_VCPROJ)\ + --exe\ + --target=$$(TOOLCHAIN)\ + --name=$$(@:.$(VCPROJ_SFX)=)\ + --ver=$$(CONFIG_VS_VERSION)\ + --proj-guid=$$($$(@:.$(VCPROJ_SFX)=).GUID)\ + --src-path-bare="$(SRC_PATH_BARE)" \ + $$(if $$(CONFIG_STATIC_MSVCRT),--static-crt) \ + --out=$$@ $$(INTERNAL_CFLAGS) $$(CFLAGS) \ + $$(INTERNAL_LDFLAGS) $$(LDFLAGS) -l$$(CODEC_LIB) $$^ +endef +ALL_EXAMPLES_BASENAME := $(notdir $(ALL_EXAMPLES)) +PROJECTS-$(CONFIG_MSVS) += $(ALL_EXAMPLES_BASENAME:.c=.$(VCPROJ_SFX)) +INSTALL-BINS-$(CONFIG_MSVS) += $(foreach p,$(VS_PLATFORMS),\ + $(addprefix bin/$(p)/,$(ALL_EXAMPLES_BASENAME:.c=.exe))) +$(foreach proj,$(call enabled,PROJECTS),\ + $(eval $(call vcproj_template,$(proj)))) + +# +# Documentation Rules +# +%.dox: %.c + @echo " [DOXY] $@" + @mkdir -p $(dir $@) + @echo "/*!\page example_$(@F:.dox=) $(@F:.dox=)" > $@ + @echo " \includelineno $(<F)" >> $@ + @echo "*/" >> $@ + +samples.dox: examples.mk + @echo " [DOXY] $@" + @echo "/*!\page samples Sample Code" > $@ + @echo " This SDK includes a number of sample applications."\ + "Each sample documents a feature of the SDK in both prose"\ + "and the associated C code."\ + "The following samples are included: ">>$@ + @$(foreach ex,$(sort $(notdir $(EXAMPLES:.c=))),\ + echo " - \subpage example_$(ex) $($(ex).DESCRIPTION)" >> $@;) + @echo >> $@ + @echo " In addition, the SDK contains a number of utilities."\ + "Since these utilities are built upon the concepts described"\ + "in the sample code listed above, they are not documented in"\ + "pieces like the samples are. Their source is included here"\ + "for reference. The following utilities are included:" >> $@ + @$(foreach ex,$(sort $(UTILS:.c=)),\ + echo " - \subpage example_$(ex) $($(ex).DESCRIPTION)" >> $@;) + @echo "*/" >> $@ + +CLEAN-OBJS += examples.doxy samples.dox $(ALL_EXAMPLES:.c=.dox) +DOCS-yes += examples.doxy samples.dox +examples.doxy: samples.dox $(ALL_EXAMPLES:.c=.dox) + @echo "INPUT += $^" > $@
diff --git a/src/third_party/libvpx/examples/decode_to_md5.c b/src/third_party/libvpx/examples/decode_to_md5.c new file mode 100644 index 0000000..1ae7a4b --- /dev/null +++ b/src/third_party/libvpx/examples/decode_to_md5.c
@@ -0,0 +1,137 @@ +/* + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// Frame-by-frame MD5 Checksum +// =========================== +// +// This example builds upon the simple decoder loop to show how checksums +// of the decoded output can be generated. These are used for validating +// decoder implementations against the reference implementation, for example. +// +// MD5 algorithm +// ------------- +// The Message-Digest 5 (MD5) is a well known hash function. We have provided +// an implementation derived from the RSA Data Security, Inc. MD5 Message-Digest +// Algorithm for your use. Our implmentation only changes the interface of this +// reference code. You must include the `md5_utils.h` header for access to these +// functions. +// +// Processing The Decoded Data +// --------------------------- +// Each row of the image is passed to the MD5 accumulator. First the Y plane +// is processed, then U, then V. It is important to honor the image's `stride` +// values. + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "vpx/vp8dx.h" +#include "vpx/vpx_decoder.h" + +#include "../md5_utils.h" +#include "../tools_common.h" +#include "../video_reader.h" +#include "./vpx_config.h" + +static void get_image_md5(const vpx_image_t *img, unsigned char digest[16]) { + int plane, y; + MD5Context md5; + + MD5Init(&md5); + + for (plane = 0; plane < 3; ++plane) { + const unsigned char *buf = img->planes[plane]; + const int stride = img->stride[plane]; + const int w = plane ? (img->d_w + 1) >> 1 : img->d_w; + const int h = plane ? (img->d_h + 1) >> 1 : img->d_h; + + for (y = 0; y < h; ++y) { + MD5Update(&md5, buf, w); + buf += stride; + } + } + + MD5Final(digest, &md5); +} + +static void print_md5(FILE *stream, unsigned char digest[16]) { + int i; + + for (i = 0; i < 16; ++i) + fprintf(stream, "%02x", digest[i]); +} + +static const char *exec_name; + +void usage_exit(void) { + fprintf(stderr, "Usage: %s <infile> <outfile>\n", exec_name); + exit(EXIT_FAILURE); +} + +int main(int argc, char **argv) { + int frame_cnt = 0; + FILE *outfile = NULL; + vpx_codec_ctx_t codec; + VpxVideoReader *reader = NULL; + const VpxVideoInfo *info = NULL; + const VpxInterface *decoder = NULL; + + exec_name = argv[0]; + + if (argc != 3) + die("Invalid number of arguments."); + + reader = vpx_video_reader_open(argv[1]); + if (!reader) + die("Failed to open %s for reading.", argv[1]); + + if (!(outfile = fopen(argv[2], "wb"))) + die("Failed to open %s for writing.", argv[2]); + + info = vpx_video_reader_get_info(reader); + + decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc); + if (!decoder) + die("Unknown input codec."); + + printf("Using %s\n", vpx_codec_iface_name(decoder->codec_interface())); + + if (vpx_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0)) + die_codec(&codec, "Failed to initialize decoder"); + + while (vpx_video_reader_read_frame(reader)) { + vpx_codec_iter_t iter = NULL; + vpx_image_t *img = NULL; + size_t frame_size = 0; + const unsigned char *frame = vpx_video_reader_get_frame(reader, + &frame_size); + if (vpx_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0)) + die_codec(&codec, "Failed to decode frame"); + + while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL) { + unsigned char digest[16]; + + get_image_md5(img, digest); + print_md5(outfile, digest); + fprintf(outfile, " img-%dx%d-%04d.i420\n", + img->d_w, img->d_h, ++frame_cnt); + } + } + + printf("Processed %d frames.\n", frame_cnt); + if (vpx_codec_destroy(&codec)) + die_codec(&codec, "Failed to destroy codec."); + + vpx_video_reader_close(reader); + + fclose(outfile); + return EXIT_SUCCESS; +}
diff --git a/src/third_party/libvpx/examples/decode_with_drops.c b/src/third_party/libvpx/examples/decode_with_drops.c new file mode 100644 index 0000000..2233e47 --- /dev/null +++ b/src/third_party/libvpx/examples/decode_with_drops.c
@@ -0,0 +1,152 @@ +/* + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// Decode With Drops Example +// ========================= +// +// This is an example utility which drops a series of frames, as specified +// on the command line. This is useful for observing the error recovery +// features of the codec. +// +// Usage +// ----- +// This example adds a single argument to the `simple_decoder` example, +// which specifies the range or pattern of frames to drop. The parameter is +// parsed as follows: +// +// Dropping A Range Of Frames +// -------------------------- +// To drop a range of frames, specify the starting frame and the ending +// frame to drop, separated by a dash. The following command will drop +// frames 5 through 10 (base 1). +// +// $ ./decode_with_drops in.ivf out.i420 5-10 +// +// +// Dropping A Pattern Of Frames +// ---------------------------- +// To drop a pattern of frames, specify the number of frames to drop and +// the number of frames after which to repeat the pattern, separated by +// a forward-slash. The following command will drop 3 of 7 frames. +// Specifically, it will decode 4 frames, then drop 3 frames, and then +// repeat. +// +// $ ./decode_with_drops in.ivf out.i420 3/7 +// +// +// Extra Variables +// --------------- +// This example maintains the pattern passed on the command line in the +// `n`, `m`, and `is_range` variables: +// +// +// Making The Drop Decision +// ------------------------ +// The example decides whether to drop the frame based on the current +// frame number, immediately before decoding the frame. + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "vpx/vp8dx.h" +#include "vpx/vpx_decoder.h" + +#include "../tools_common.h" +#include "../video_reader.h" +#include "./vpx_config.h" + +static const char *exec_name; + +void usage_exit(void) { + fprintf(stderr, "Usage: %s <infile> <outfile> <N-M|N/M>\n", exec_name); + exit(EXIT_FAILURE); +} + +int main(int argc, char **argv) { + int frame_cnt = 0; + FILE *outfile = NULL; + vpx_codec_ctx_t codec; + const VpxInterface *decoder = NULL; + VpxVideoReader *reader = NULL; + const VpxVideoInfo *info = NULL; + int n = 0; + int m = 0; + int is_range = 0; + char *nptr = NULL; + + exec_name = argv[0]; + + if (argc != 4) + die("Invalid number of arguments."); + + reader = vpx_video_reader_open(argv[1]); + if (!reader) + die("Failed to open %s for reading.", argv[1]); + + if (!(outfile = fopen(argv[2], "wb"))) + die("Failed to open %s for writing.", argv[2]); + + n = strtol(argv[3], &nptr, 0); + m = strtol(nptr + 1, NULL, 0); + is_range = (*nptr == '-'); + if (!n || !m || (*nptr != '-' && *nptr != '/')) + die("Couldn't parse pattern %s.\n", argv[3]); + + info = vpx_video_reader_get_info(reader); + + decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc); + if (!decoder) + die("Unknown input codec."); + + printf("Using %s\n", vpx_codec_iface_name(decoder->codec_interface())); + + if (vpx_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0)) + die_codec(&codec, "Failed to initialize decoder."); + + while (vpx_video_reader_read_frame(reader)) { + vpx_codec_iter_t iter = NULL; + vpx_image_t *img = NULL; + size_t frame_size = 0; + int skip; + const unsigned char *frame = vpx_video_reader_get_frame(reader, + &frame_size); + if (vpx_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0)) + die_codec(&codec, "Failed to decode frame."); + + ++frame_cnt; + + skip = (is_range && frame_cnt >= n && frame_cnt <= m) || + (!is_range && m - (frame_cnt - 1) % m <= n); + + if (!skip) { + putc('.', stdout); + + while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL) + vpx_img_write(img, outfile); + } else { + putc('X', stdout); + } + + fflush(stdout); + } + + printf("Processed %d frames.\n", frame_cnt); + if (vpx_codec_destroy(&codec)) + die_codec(&codec, "Failed to destroy codec."); + + printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n", + info->frame_width, info->frame_height, argv[2]); + + vpx_video_reader_close(reader); + fclose(outfile); + + return EXIT_SUCCESS; +}
diff --git a/src/third_party/libvpx/examples/postproc.c b/src/third_party/libvpx/examples/postproc.c new file mode 100644 index 0000000..a8ac208 --- /dev/null +++ b/src/third_party/libvpx/examples/postproc.c
@@ -0,0 +1,138 @@ +/* + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// Postprocessing Decoder +// ====================== +// +// This example adds postprocessing to the simple decoder loop. +// +// Initializing Postprocessing +// --------------------------- +// You must inform the codec that you might request postprocessing at +// initialization time. This is done by passing the VPX_CODEC_USE_POSTPROC +// flag to `vpx_codec_dec_init`. If the codec does not support +// postprocessing, this call will return VPX_CODEC_INCAPABLE. For +// demonstration purposes, we also fall back to default initialization if +// the codec does not provide support. +// +// Using Adaptive Postprocessing +// ----------------------------- +// VP6 provides "adaptive postprocessing." It will automatically select the +// best postprocessing filter on a frame by frame basis based on the amount +// of time remaining before the user's specified deadline expires. The +// special value 0 indicates that the codec should take as long as +// necessary to provide the best quality frame. This example gives the +// codec 15ms (15000us) to return a frame. Remember that this is a soft +// deadline, and the codec may exceed it doing its regular processing. In +// these cases, no additional postprocessing will be done. +// +// Codec Specific Postprocessing Controls +// -------------------------------------- +// Some codecs provide fine grained controls over their built-in +// postprocessors. VP8 is one example. The following sample code toggles +// postprocessing on and off every 15 frames. + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "vpx/vp8dx.h" +#include "vpx/vpx_decoder.h" + +#include "../tools_common.h" +#include "../video_reader.h" +#include "./vpx_config.h" + +static const char *exec_name; + +void usage_exit(void) { + fprintf(stderr, "Usage: %s <infile> <outfile>\n", exec_name); + exit(EXIT_FAILURE); +} + +int main(int argc, char **argv) { + int frame_cnt = 0; + FILE *outfile = NULL; + vpx_codec_ctx_t codec; + vpx_codec_err_t res; + VpxVideoReader *reader = NULL; + const VpxInterface *decoder = NULL; + const VpxVideoInfo *info = NULL; + + exec_name = argv[0]; + + if (argc != 3) + die("Invalid number of arguments."); + + reader = vpx_video_reader_open(argv[1]); + if (!reader) + die("Failed to open %s for reading.", argv[1]); + + if (!(outfile = fopen(argv[2], "wb"))) + die("Failed to open %s for writing", argv[2]); + + info = vpx_video_reader_get_info(reader); + + decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc); + if (!decoder) + die("Unknown input codec."); + + printf("Using %s\n", vpx_codec_iface_name(decoder->codec_interface())); + + res = vpx_codec_dec_init(&codec, decoder->codec_interface(), NULL, + VPX_CODEC_USE_POSTPROC); + if (res == VPX_CODEC_INCAPABLE) + die_codec(&codec, "Postproc not supported by this decoder."); + + if (res) + die_codec(&codec, "Failed to initialize decoder."); + + while (vpx_video_reader_read_frame(reader)) { + vpx_codec_iter_t iter = NULL; + vpx_image_t *img = NULL; + size_t frame_size = 0; + const unsigned char *frame = vpx_video_reader_get_frame(reader, + &frame_size); + + ++frame_cnt; + + if (frame_cnt % 30 == 1) { + vp8_postproc_cfg_t pp = {0, 0, 0}; + + if (vpx_codec_control(&codec, VP8_SET_POSTPROC, &pp)) + die_codec(&codec, "Failed to turn off postproc."); + } else if (frame_cnt % 30 == 16) { + vp8_postproc_cfg_t pp = {VP8_DEBLOCK | VP8_DEMACROBLOCK | VP8_MFQE, + 4, 0}; + if (vpx_codec_control(&codec, VP8_SET_POSTPROC, &pp)) + die_codec(&codec, "Failed to turn on postproc."); + }; + + // Decode the frame with 15ms deadline + if (vpx_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 15000)) + die_codec(&codec, "Failed to decode frame"); + + while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL) { + vpx_img_write(img, outfile); + } + } + + printf("Processed %d frames.\n", frame_cnt); + if (vpx_codec_destroy(&codec)) + die_codec(&codec, "Failed to destroy codec"); + + printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n", + info->frame_width, info->frame_height, argv[2]); + + vpx_video_reader_close(reader); + + fclose(outfile); + return EXIT_SUCCESS; +}
diff --git a/src/third_party/libvpx/examples/resize_util.c b/src/third_party/libvpx/examples/resize_util.c new file mode 100644 index 0000000..e6fdd5b --- /dev/null +++ b/src/third_party/libvpx/examples/resize_util.c
@@ -0,0 +1,130 @@ +/* + * Copyright (c) 2014 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <assert.h> +#include <limits.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "../tools_common.h" +#include "../vp9/encoder/vp9_resize.h" + +static const char *exec_name = NULL; + +static void usage() { + printf("Usage:\n"); + printf("%s <input_yuv> <width>x<height> <target_width>x<target_height> ", + exec_name); + printf("<output_yuv> [<frames>]\n"); +} + +void usage_exit(void) { + usage(); + exit(EXIT_FAILURE); +} + +static int parse_dim(char *v, int *width, int *height) { + char *x = strchr(v, 'x'); + if (x == NULL) + x = strchr(v, 'X'); + if (x == NULL) + return 0; + *width = atoi(v); + *height = atoi(&x[1]); + if (*width <= 0 || *height <= 0) + return 0; + else + return 1; +} + +int main(int argc, char *argv[]) { + char *fin, *fout; + FILE *fpin, *fpout; + uint8_t *inbuf, *outbuf; + uint8_t *inbuf_u, *outbuf_u; + uint8_t *inbuf_v, *outbuf_v; + int f, frames; + int width, height, target_width, target_height; + + exec_name = argv[0]; + + if (argc < 5) { + printf("Incorrect parameters:\n"); + usage(); + return 1; + } + + fin = argv[1]; + fout = argv[4]; + if (!parse_dim(argv[2], &width, &height)) { + printf("Incorrect parameters: %s\n", argv[2]); + usage(); + return 1; + } + if (!parse_dim(argv[3], &target_width, &target_height)) { + printf("Incorrect parameters: %s\n", argv[3]); + usage(); + return 1; + } + + fpin = fopen(fin, "rb"); + if (fpin == NULL) { + printf("Can't open file %s to read\n", fin); + usage(); + return 1; + } + fpout = fopen(fout, "wb"); + if (fpout == NULL) { + printf("Can't open file %s to write\n", fout); + usage(); + return 1; + } + if (argc >= 6) + frames = atoi(argv[5]); + else + frames = INT_MAX; + + printf("Input size: %dx%d\n", + width, height); + printf("Target size: %dx%d, Frames: ", + target_width, target_height); + if (frames == INT_MAX) + printf("All\n"); + else + printf("%d\n", frames); + + inbuf = (uint8_t*)malloc(width * height * 3 / 2); + outbuf = (uint8_t*)malloc(target_width * target_height * 3 / 2); + inbuf_u = inbuf + width * height; + inbuf_v = inbuf_u + width * height / 4; + outbuf_u = outbuf + target_width * target_height; + outbuf_v = outbuf_u + target_width * target_height / 4; + f = 0; + while (f < frames) { + if (fread(inbuf, width * height * 3 / 2, 1, fpin) != 1) + break; + vp9_resize_frame420(inbuf, width, inbuf_u, inbuf_v, width / 2, + height, width, + outbuf, target_width, outbuf_u, outbuf_v, + target_width / 2, + target_height, target_width); + fwrite(outbuf, target_width * target_height * 3 / 2, 1, fpout); + f++; + } + printf("%d frames processed\n", f); + fclose(fpin); + fclose(fpout); + + free(inbuf); + free(outbuf); + return 0; +}
diff --git a/src/third_party/libvpx/examples/set_maps.c b/src/third_party/libvpx/examples/set_maps.c new file mode 100644 index 0000000..1dc3ac0 --- /dev/null +++ b/src/third_party/libvpx/examples/set_maps.c
@@ -0,0 +1,255 @@ +/* + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + + +// VP8 Set Active and ROI Maps +// =========================== +// +// This is an example demonstrating how to control the VP8 encoder's +// ROI and Active maps. +// +// ROI (Reigon of Interest) maps are a way for the application to assign +// each macroblock in the image to a region, and then set quantizer and +// filtering parameters on that image. +// +// Active maps are a way for the application to specify on a +// macroblock-by-macroblock basis whether there is any activity in that +// macroblock. +// +// +// Configuration +// ------------- +// An ROI map is set on frame 22. If the width of the image in macroblocks +// is evenly divisble by 4, then the output will appear to have distinct +// columns, where the quantizer, loopfilter, and static threshold differ +// from column to column. +// +// An active map is set on frame 33. If the width of the image in macroblocks +// is evenly divisble by 4, then the output will appear to have distinct +// columns, where one column will have motion and the next will not. +// +// The active map is cleared on frame 44. +// +// Observing The Effects +// --------------------- +// Use the `simple_decoder` example to decode this sample, and observe +// the change in the image at frames 22, 33, and 44. + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "vpx/vp8cx.h" +#include "vpx/vpx_encoder.h" + +#include "../tools_common.h" +#include "../video_writer.h" + +static const char *exec_name; + +void usage_exit(void) { + fprintf(stderr, "Usage: %s <codec> <width> <height> <infile> <outfile>\n", + exec_name); + exit(EXIT_FAILURE); +} + +static void set_roi_map(const vpx_codec_enc_cfg_t *cfg, + vpx_codec_ctx_t *codec) { + unsigned int i; + vpx_roi_map_t roi; + memset(&roi, 0, sizeof(roi)); + + roi.rows = (cfg->g_h + 15) / 16; + roi.cols = (cfg->g_w + 15) / 16; + + roi.delta_q[0] = 0; + roi.delta_q[1] = -2; + roi.delta_q[2] = -4; + roi.delta_q[3] = -6; + + roi.delta_lf[0] = 0; + roi.delta_lf[1] = 1; + roi.delta_lf[2] = 2; + roi.delta_lf[3] = 3; + + roi.static_threshold[0] = 1500; + roi.static_threshold[1] = 1000; + roi.static_threshold[2] = 500; + roi.static_threshold[3] = 0; + + roi.roi_map = (uint8_t *)malloc(roi.rows * roi.cols); + for (i = 0; i < roi.rows * roi.cols; ++i) + roi.roi_map[i] = i % 4; + + if (vpx_codec_control(codec, VP8E_SET_ROI_MAP, &roi)) + die_codec(codec, "Failed to set ROI map"); + + free(roi.roi_map); +} + +static void set_active_map(const vpx_codec_enc_cfg_t *cfg, + vpx_codec_ctx_t *codec) { + unsigned int i; + vpx_active_map_t map = {0, 0, 0}; + + map.rows = (cfg->g_h + 15) / 16; + map.cols = (cfg->g_w + 15) / 16; + + map.active_map = (uint8_t *)malloc(map.rows * map.cols); + for (i = 0; i < map.rows * map.cols; ++i) + map.active_map[i] = i % 2; + + if (vpx_codec_control(codec, VP8E_SET_ACTIVEMAP, &map)) + die_codec(codec, "Failed to set active map"); + + free(map.active_map); +} + +static void unset_active_map(const vpx_codec_enc_cfg_t *cfg, + vpx_codec_ctx_t *codec) { + vpx_active_map_t map = {0, 0, 0}; + + map.rows = (cfg->g_h + 15) / 16; + map.cols = (cfg->g_w + 15) / 16; + map.active_map = NULL; + + if (vpx_codec_control(codec, VP8E_SET_ACTIVEMAP, &map)) + die_codec(codec, "Failed to set active map"); +} + +static int encode_frame(vpx_codec_ctx_t *codec, + vpx_image_t *img, + int frame_index, + VpxVideoWriter *writer) { + int got_pkts = 0; + vpx_codec_iter_t iter = NULL; + const vpx_codec_cx_pkt_t *pkt = NULL; + const vpx_codec_err_t res = vpx_codec_encode(codec, img, frame_index, 1, 0, + VPX_DL_GOOD_QUALITY); + if (res != VPX_CODEC_OK) + die_codec(codec, "Failed to encode frame"); + + while ((pkt = vpx_codec_get_cx_data(codec, &iter)) != NULL) { + got_pkts = 1; + + if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { + const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0; + if (!vpx_video_writer_write_frame(writer, + pkt->data.frame.buf, + pkt->data.frame.sz, + pkt->data.frame.pts)) { + die_codec(codec, "Failed to write compressed frame"); + } + + printf(keyframe ? "K" : "."); + fflush(stdout); + } + } + + return got_pkts; +} + +int main(int argc, char **argv) { + FILE *infile = NULL; + vpx_codec_ctx_t codec; + vpx_codec_enc_cfg_t cfg; + int frame_count = 0; + vpx_image_t raw; + vpx_codec_err_t res; + VpxVideoInfo info; + VpxVideoWriter *writer = NULL; + const VpxInterface *encoder = NULL; + const int fps = 2; // TODO(dkovalev) add command line argument + const double bits_per_pixel_per_frame = 0.067; + + exec_name = argv[0]; + if (argc != 6) + die("Invalid number of arguments"); + + memset(&info, 0, sizeof(info)); + + encoder = get_vpx_encoder_by_name(argv[1]); + if (encoder == NULL) { + die("Unsupported codec."); + } + assert(encoder != NULL); + info.codec_fourcc = encoder->fourcc; + info.frame_width = strtol(argv[2], NULL, 0); + info.frame_height = strtol(argv[3], NULL, 0); + info.time_base.numerator = 1; + info.time_base.denominator = fps; + + if (info.frame_width <= 0 || + info.frame_height <= 0 || + (info.frame_width % 2) != 0 || + (info.frame_height % 2) != 0) { + die("Invalid frame size: %dx%d", info.frame_width, info.frame_height); + } + + if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width, + info.frame_height, 1)) { + die("Failed to allocate image."); + } + + printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface())); + + res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0); + if (res) + die_codec(&codec, "Failed to get default codec config."); + + cfg.g_w = info.frame_width; + cfg.g_h = info.frame_height; + cfg.g_timebase.num = info.time_base.numerator; + cfg.g_timebase.den = info.time_base.denominator; + cfg.rc_target_bitrate = (unsigned int)(bits_per_pixel_per_frame * cfg.g_w * + cfg.g_h * fps / 1000); + cfg.g_lag_in_frames = 0; + + writer = vpx_video_writer_open(argv[5], kContainerIVF, &info); + if (!writer) + die("Failed to open %s for writing.", argv[5]); + + if (!(infile = fopen(argv[4], "rb"))) + die("Failed to open %s for reading.", argv[4]); + + if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0)) + die_codec(&codec, "Failed to initialize encoder"); + + // Encode frames. + while (vpx_img_read(&raw, infile)) { + ++frame_count; + + if (frame_count == 22 && encoder->fourcc == VP8_FOURCC) { + set_roi_map(&cfg, &codec); + } else if (frame_count == 33) { + set_active_map(&cfg, &codec); + } else if (frame_count == 44) { + unset_active_map(&cfg, &codec); + } + + encode_frame(&codec, &raw, frame_count, writer); + } + + // Flush encoder. + while (encode_frame(&codec, NULL, -1, writer)) {} + + printf("\n"); + fclose(infile); + printf("Processed %d frames.\n", frame_count); + + vpx_img_free(&raw); + if (vpx_codec_destroy(&codec)) + die_codec(&codec, "Failed to destroy codec."); + + vpx_video_writer_close(writer); + + return EXIT_SUCCESS; +}
diff --git a/src/third_party/libvpx/examples/simple_decoder.c b/src/third_party/libvpx/examples/simple_decoder.c new file mode 100644 index 0000000..8ccc810 --- /dev/null +++ b/src/third_party/libvpx/examples/simple_decoder.c
@@ -0,0 +1,154 @@ +/* + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + + +// Simple Decoder +// ============== +// +// This is an example of a simple decoder loop. It takes an input file +// containing the compressed data (in IVF format), passes it through the +// decoder, and writes the decompressed frames to disk. Other decoder +// examples build upon this one. +// +// The details of the IVF format have been elided from this example for +// simplicity of presentation, as IVF files will not generally be used by +// your application. In general, an IVF file consists of a file header, +// followed by a variable number of frames. Each frame consists of a frame +// header followed by a variable length payload. The length of the payload +// is specified in the first four bytes of the frame header. The payload is +// the raw compressed data. +// +// Standard Includes +// ----------------- +// For decoders, you only have to include `vpx_decoder.h` and then any +// header files for the specific codecs you use. In this case, we're using +// vp8. +// +// Initializing The Codec +// ---------------------- +// The libvpx decoder is initialized by the call to vpx_codec_dec_init(). +// Determining the codec interface to use is handled by VpxVideoReader and the +// functions prefixed with vpx_video_reader_. Discussion of those functions is +// beyond the scope of this example, but the main gist is to open the input file +// and parse just enough of it to determine if it's a VPx file and which VPx +// codec is contained within the file. +// Note the NULL pointer passed to vpx_codec_dec_init(). We do that in this +// example because we want the algorithm to determine the stream configuration +// (width/height) and allocate memory automatically. +// +// Decoding A Frame +// ---------------- +// Once the frame has been read into memory, it is decoded using the +// `vpx_codec_decode` function. The call takes a pointer to the data +// (`frame`) and the length of the data (`frame_size`). No application data +// is associated with the frame in this example, so the `user_priv` +// parameter is NULL. The `deadline` parameter is left at zero for this +// example. This parameter is generally only used when doing adaptive post +// processing. +// +// Codecs may produce a variable number of output frames for every call to +// `vpx_codec_decode`. These frames are retrieved by the +// `vpx_codec_get_frame` iterator function. The iterator variable `iter` is +// initialized to NULL each time `vpx_codec_decode` is called. +// `vpx_codec_get_frame` is called in a loop, returning a pointer to a +// decoded image or NULL to indicate the end of list. +// +// Processing The Decoded Data +// --------------------------- +// In this example, we simply write the encoded data to disk. It is +// important to honor the image's `stride` values. +// +// Cleanup +// ------- +// The `vpx_codec_destroy` call frees any memory allocated by the codec. +// +// Error Handling +// -------------- +// This example does not special case any error return codes. If there was +// an error, a descriptive message is printed and the program exits. With +// few exceptions, vpx_codec functions return an enumerated error status, +// with the value `0` indicating success. + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "vpx/vpx_decoder.h" + +#include "../tools_common.h" +#include "../video_reader.h" +#include "./vpx_config.h" + +static const char *exec_name; + +void usage_exit(void) { + fprintf(stderr, "Usage: %s <infile> <outfile>\n", exec_name); + exit(EXIT_FAILURE); +} + +int main(int argc, char **argv) { + int frame_cnt = 0; + FILE *outfile = NULL; + vpx_codec_ctx_t codec; + VpxVideoReader *reader = NULL; + const VpxInterface *decoder = NULL; + const VpxVideoInfo *info = NULL; + + exec_name = argv[0]; + + if (argc != 3) + die("Invalid number of arguments."); + + reader = vpx_video_reader_open(argv[1]); + if (!reader) + die("Failed to open %s for reading.", argv[1]); + + if (!(outfile = fopen(argv[2], "wb"))) + die("Failed to open %s for writing.", argv[2]); + + info = vpx_video_reader_get_info(reader); + + decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc); + if (!decoder) + die("Unknown input codec."); + + printf("Using %s\n", vpx_codec_iface_name(decoder->codec_interface())); + + if (vpx_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0)) + die_codec(&codec, "Failed to initialize decoder."); + + while (vpx_video_reader_read_frame(reader)) { + vpx_codec_iter_t iter = NULL; + vpx_image_t *img = NULL; + size_t frame_size = 0; + const unsigned char *frame = vpx_video_reader_get_frame(reader, + &frame_size); + if (vpx_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0)) + die_codec(&codec, "Failed to decode frame."); + + while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL) { + vpx_img_write(img, outfile); + ++frame_cnt; + } + } + + printf("Processed %d frames.\n", frame_cnt); + if (vpx_codec_destroy(&codec)) + die_codec(&codec, "Failed to destroy codec"); + + printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n", + info->frame_width, info->frame_height, argv[2]); + + vpx_video_reader_close(reader); + + fclose(outfile); + + return EXIT_SUCCESS; +}
diff --git a/src/third_party/libvpx/examples/simple_encoder.c b/src/third_party/libvpx/examples/simple_encoder.c new file mode 100644 index 0000000..64f0a01 --- /dev/null +++ b/src/third_party/libvpx/examples/simple_encoder.c
@@ -0,0 +1,260 @@ +/* + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// Simple Encoder +// ============== +// +// This is an example of a simple encoder loop. It takes an input file in +// YV12 format, passes it through the encoder, and writes the compressed +// frames to disk in IVF format. Other decoder examples build upon this +// one. +// +// The details of the IVF format have been elided from this example for +// simplicity of presentation, as IVF files will not generally be used by +// your application. In general, an IVF file consists of a file header, +// followed by a variable number of frames. Each frame consists of a frame +// header followed by a variable length payload. The length of the payload +// is specified in the first four bytes of the frame header. The payload is +// the raw compressed data. +// +// Standard Includes +// ----------------- +// For encoders, you only have to include `vpx_encoder.h` and then any +// header files for the specific codecs you use. In this case, we're using +// vp8. +// +// Getting The Default Configuration +// --------------------------------- +// Encoders have the notion of "usage profiles." For example, an encoder +// may want to publish default configurations for both a video +// conferencing application and a best quality offline encoder. These +// obviously have very different default settings. Consult the +// documentation for your codec to see if it provides any default +// configurations. All codecs provide a default configuration, number 0, +// which is valid for material in the vacinity of QCIF/QVGA. +// +// Updating The Configuration +// --------------------------------- +// Almost all applications will want to update the default configuration +// with settings specific to their usage. Here we set the width and height +// of the video file to that specified on the command line. We also scale +// the default bitrate based on the ratio between the default resolution +// and the resolution specified on the command line. +// +// Initializing The Codec +// ---------------------- +// The encoder is initialized by the following code. +// +// Encoding A Frame +// ---------------- +// The frame is read as a continuous block (size width * height * 3 / 2) +// from the input file. If a frame was read (the input file has not hit +// EOF) then the frame is passed to the encoder. Otherwise, a NULL +// is passed, indicating the End-Of-Stream condition to the encoder. The +// `frame_cnt` is reused as the presentation time stamp (PTS) and each +// frame is shown for one frame-time in duration. The flags parameter is +// unused in this example. The deadline is set to VPX_DL_REALTIME to +// make the example run as quickly as possible. + +// Forced Keyframes +// ---------------- +// Keyframes can be forced by setting the VPX_EFLAG_FORCE_KF bit of the +// flags passed to `vpx_codec_control()`. In this example, we force a +// keyframe every <keyframe-interval> frames. Note, the output stream can +// contain additional keyframes beyond those that have been forced using the +// VPX_EFLAG_FORCE_KF flag because of automatic keyframe placement by the +// encoder. +// +// Processing The Encoded Data +// --------------------------- +// Each packet of type `VPX_CODEC_CX_FRAME_PKT` contains the encoded data +// for this frame. We write a IVF frame header, followed by the raw data. +// +// Cleanup +// ------- +// The `vpx_codec_destroy` call frees any memory allocated by the codec. +// +// Error Handling +// -------------- +// This example does not special case any error return codes. If there was +// an error, a descriptive message is printed and the program exits. With +// few exeptions, vpx_codec functions return an enumerated error status, +// with the value `0` indicating success. +// +// Error Resiliency Features +// ------------------------- +// Error resiliency is controlled by the g_error_resilient member of the +// configuration structure. Use the `decode_with_drops` example to decode with +// frames 5-10 dropped. Compare the output for a file encoded with this example +// versus one encoded with the `simple_encoder` example. + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "vpx/vpx_encoder.h" + +#include "../tools_common.h" +#include "../video_writer.h" + +static const char *exec_name; + +void usage_exit(void) { + fprintf(stderr, + "Usage: %s <codec> <width> <height> <infile> <outfile> " + "<keyframe-interval> <error-resilient> <frames to encode>\n" + "See comments in simple_encoder.c for more information.\n", + exec_name); + exit(EXIT_FAILURE); +} + +static int encode_frame(vpx_codec_ctx_t *codec, + vpx_image_t *img, + int frame_index, + int flags, + VpxVideoWriter *writer) { + int got_pkts = 0; + vpx_codec_iter_t iter = NULL; + const vpx_codec_cx_pkt_t *pkt = NULL; + const vpx_codec_err_t res = vpx_codec_encode(codec, img, frame_index, 1, + flags, VPX_DL_GOOD_QUALITY); + if (res != VPX_CODEC_OK) + die_codec(codec, "Failed to encode frame"); + + while ((pkt = vpx_codec_get_cx_data(codec, &iter)) != NULL) { + got_pkts = 1; + + if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { + const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0; + if (!vpx_video_writer_write_frame(writer, + pkt->data.frame.buf, + pkt->data.frame.sz, + pkt->data.frame.pts)) { + die_codec(codec, "Failed to write compressed frame"); + } + printf(keyframe ? "K" : "."); + fflush(stdout); + } + } + + return got_pkts; +} + +// TODO(tomfinegan): Improve command line parsing and add args for bitrate/fps. +int main(int argc, char **argv) { + FILE *infile = NULL; + vpx_codec_ctx_t codec; + vpx_codec_enc_cfg_t cfg; + int frame_count = 0; + vpx_image_t raw; + vpx_codec_err_t res; + VpxVideoInfo info = {0}; + VpxVideoWriter *writer = NULL; + const VpxInterface *encoder = NULL; + const int fps = 30; + const int bitrate = 200; + int keyframe_interval = 0; + int max_frames = 0; + int frames_encoded = 0; + const char *codec_arg = NULL; + const char *width_arg = NULL; + const char *height_arg = NULL; + const char *infile_arg = NULL; + const char *outfile_arg = NULL; + const char *keyframe_interval_arg = NULL; + + exec_name = argv[0]; + + if (argc != 9) + die("Invalid number of arguments"); + + codec_arg = argv[1]; + width_arg = argv[2]; + height_arg = argv[3]; + infile_arg = argv[4]; + outfile_arg = argv[5]; + keyframe_interval_arg = argv[6]; + max_frames = strtol(argv[8], NULL, 0); + + encoder = get_vpx_encoder_by_name(codec_arg); + if (!encoder) + die("Unsupported codec."); + + info.codec_fourcc = encoder->fourcc; + info.frame_width = strtol(width_arg, NULL, 0); + info.frame_height = strtol(height_arg, NULL, 0); + info.time_base.numerator = 1; + info.time_base.denominator = fps; + + if (info.frame_width <= 0 || + info.frame_height <= 0 || + (info.frame_width % 2) != 0 || + (info.frame_height % 2) != 0) { + die("Invalid frame size: %dx%d", info.frame_width, info.frame_height); + } + + if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width, + info.frame_height, 1)) { + die("Failed to allocate image."); + } + + keyframe_interval = strtol(keyframe_interval_arg, NULL, 0); + if (keyframe_interval < 0) + die("Invalid keyframe interval value."); + + printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface())); + + res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0); + if (res) + die_codec(&codec, "Failed to get default codec config."); + + cfg.g_w = info.frame_width; + cfg.g_h = info.frame_height; + cfg.g_timebase.num = info.time_base.numerator; + cfg.g_timebase.den = info.time_base.denominator; + cfg.rc_target_bitrate = bitrate; + cfg.g_error_resilient = strtol(argv[7], NULL, 0); + + writer = vpx_video_writer_open(outfile_arg, kContainerIVF, &info); + if (!writer) + die("Failed to open %s for writing.", outfile_arg); + + if (!(infile = fopen(infile_arg, "rb"))) + die("Failed to open %s for reading.", infile_arg); + + if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0)) + die_codec(&codec, "Failed to initialize encoder"); + + // Encode frames. + while (vpx_img_read(&raw, infile)) { + int flags = 0; + if (keyframe_interval > 0 && frame_count % keyframe_interval == 0) + flags |= VPX_EFLAG_FORCE_KF; + encode_frame(&codec, &raw, frame_count++, flags, writer); + frames_encoded++; + if (max_frames > 0 && frames_encoded >= max_frames) + break; + } + + // Flush encoder. + while (encode_frame(&codec, NULL, -1, 0, writer)) {}; + + printf("\n"); + fclose(infile); + printf("Processed %d frames.\n", frame_count); + + vpx_img_free(&raw); + if (vpx_codec_destroy(&codec)) + die_codec(&codec, "Failed to destroy codec."); + + vpx_video_writer_close(writer); + + return EXIT_SUCCESS; +}
diff --git a/src/third_party/libvpx/examples/twopass_encoder.c b/src/third_party/libvpx/examples/twopass_encoder.c new file mode 100644 index 0000000..15a6617 --- /dev/null +++ b/src/third_party/libvpx/examples/twopass_encoder.c
@@ -0,0 +1,277 @@ +/* + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// Two Pass Encoder +// ================ +// +// This is an example of a two pass encoder loop. It takes an input file in +// YV12 format, passes it through the encoder twice, and writes the compressed +// frames to disk in IVF format. It builds upon the simple_encoder example. +// +// Twopass Variables +// ----------------- +// Twopass mode needs to track the current pass number and the buffer of +// statistics packets. +// +// Updating The Configuration +// --------------------------------- +// In two pass mode, the configuration has to be updated on each pass. The +// statistics buffer is passed on the last pass. +// +// Encoding A Frame +// ---------------- +// Encoding a frame in two pass mode is identical to the simple encoder +// example. To increase the quality while sacrificing encoding speed, +// VPX_DL_BEST_QUALITY can be used in place of VPX_DL_GOOD_QUALITY. +// +// Processing Statistics Packets +// ----------------------------- +// Each packet of type `VPX_CODEC_CX_FRAME_PKT` contains the encoded data +// for this frame. We write a IVF frame header, followed by the raw data. +// +// +// Pass Progress Reporting +// ----------------------------- +// It's sometimes helpful to see when each pass completes. +// +// +// Clean-up +// ----------------------------- +// Destruction of the encoder instance must be done on each pass. The +// raw image should be destroyed at the end as usual. + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "vpx/vpx_encoder.h" + +#include "../tools_common.h" +#include "../video_writer.h" + +static const char *exec_name; + +void usage_exit(void) { + fprintf(stderr, + "Usage: %s <codec> <width> <height> <infile> <outfile> " + "<frame limit>\n", + exec_name); + exit(EXIT_FAILURE); +} + +static int get_frame_stats(vpx_codec_ctx_t *ctx, + const vpx_image_t *img, + vpx_codec_pts_t pts, + unsigned int duration, + vpx_enc_frame_flags_t flags, + unsigned int deadline, + vpx_fixed_buf_t *stats) { + int got_pkts = 0; + vpx_codec_iter_t iter = NULL; + const vpx_codec_cx_pkt_t *pkt = NULL; + const vpx_codec_err_t res = vpx_codec_encode(ctx, img, pts, duration, flags, + deadline); + if (res != VPX_CODEC_OK) + die_codec(ctx, "Failed to get frame stats."); + + while ((pkt = vpx_codec_get_cx_data(ctx, &iter)) != NULL) { + got_pkts = 1; + + if (pkt->kind == VPX_CODEC_STATS_PKT) { + const uint8_t *const pkt_buf = pkt->data.twopass_stats.buf; + const size_t pkt_size = pkt->data.twopass_stats.sz; + stats->buf = realloc(stats->buf, stats->sz + pkt_size); + memcpy((uint8_t *)stats->buf + stats->sz, pkt_buf, pkt_size); + stats->sz += pkt_size; + } + } + + return got_pkts; +} + +static int encode_frame(vpx_codec_ctx_t *ctx, + const vpx_image_t *img, + vpx_codec_pts_t pts, + unsigned int duration, + vpx_enc_frame_flags_t flags, + unsigned int deadline, + VpxVideoWriter *writer) { + int got_pkts = 0; + vpx_codec_iter_t iter = NULL; + const vpx_codec_cx_pkt_t *pkt = NULL; + const vpx_codec_err_t res = vpx_codec_encode(ctx, img, pts, duration, flags, + deadline); + if (res != VPX_CODEC_OK) + die_codec(ctx, "Failed to encode frame."); + + while ((pkt = vpx_codec_get_cx_data(ctx, &iter)) != NULL) { + got_pkts = 1; + if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { + const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0; + + if (!vpx_video_writer_write_frame(writer, pkt->data.frame.buf, + pkt->data.frame.sz, + pkt->data.frame.pts)) + die_codec(ctx, "Failed to write compressed frame."); + printf(keyframe ? "K" : "."); + fflush(stdout); + } + } + + return got_pkts; +} + +static vpx_fixed_buf_t pass0(vpx_image_t *raw, + FILE *infile, + const VpxInterface *encoder, + const vpx_codec_enc_cfg_t *cfg, + int max_frames) { + vpx_codec_ctx_t codec; + int frame_count = 0; + vpx_fixed_buf_t stats = {NULL, 0}; + + if (vpx_codec_enc_init(&codec, encoder->codec_interface(), cfg, 0)) + die_codec(&codec, "Failed to initialize encoder"); + + // Calculate frame statistics. + while (vpx_img_read(raw, infile)) { + ++frame_count; + get_frame_stats(&codec, raw, frame_count, 1, 0, VPX_DL_GOOD_QUALITY, + &stats); + if (max_frames > 0 && frame_count >= max_frames) + break; + } + + // Flush encoder. + while (get_frame_stats(&codec, NULL, frame_count, 1, 0, + VPX_DL_GOOD_QUALITY, &stats)) {} + + printf("Pass 0 complete. Processed %d frames.\n", frame_count); + if (vpx_codec_destroy(&codec)) + die_codec(&codec, "Failed to destroy codec."); + + return stats; +} + +static void pass1(vpx_image_t *raw, + FILE *infile, + const char *outfile_name, + const VpxInterface *encoder, + const vpx_codec_enc_cfg_t *cfg, + int max_frames) { + VpxVideoInfo info = { + encoder->fourcc, + cfg->g_w, + cfg->g_h, + {cfg->g_timebase.num, cfg->g_timebase.den} + }; + VpxVideoWriter *writer = NULL; + vpx_codec_ctx_t codec; + int frame_count = 0; + + writer = vpx_video_writer_open(outfile_name, kContainerIVF, &info); + if (!writer) + die("Failed to open %s for writing", outfile_name); + + if (vpx_codec_enc_init(&codec, encoder->codec_interface(), cfg, 0)) + die_codec(&codec, "Failed to initialize encoder"); + + // Encode frames. + while (vpx_img_read(raw, infile)) { + ++frame_count; + encode_frame(&codec, raw, frame_count, 1, 0, VPX_DL_GOOD_QUALITY, writer); + + if (max_frames > 0 && frame_count >= max_frames) + break; + } + + // Flush encoder. + while (encode_frame(&codec, NULL, -1, 1, 0, VPX_DL_GOOD_QUALITY, writer)) {} + + printf("\n"); + + if (vpx_codec_destroy(&codec)) + die_codec(&codec, "Failed to destroy codec."); + + vpx_video_writer_close(writer); + + printf("Pass 1 complete. Processed %d frames.\n", frame_count); +} + +int main(int argc, char **argv) { + FILE *infile = NULL; + int w, h; + vpx_codec_ctx_t codec; + vpx_codec_enc_cfg_t cfg; + vpx_image_t raw; + vpx_codec_err_t res; + vpx_fixed_buf_t stats; + + const VpxInterface *encoder = NULL; + const int fps = 30; // TODO(dkovalev) add command line argument + const int bitrate = 200; // kbit/s TODO(dkovalev) add command line argument + const char *const codec_arg = argv[1]; + const char *const width_arg = argv[2]; + const char *const height_arg = argv[3]; + const char *const infile_arg = argv[4]; + const char *const outfile_arg = argv[5]; + int max_frames = 0; + exec_name = argv[0]; + + if (argc != 7) + die("Invalid number of arguments."); + + max_frames = strtol(argv[6], NULL, 0); + + encoder = get_vpx_encoder_by_name(codec_arg); + if (!encoder) + die("Unsupported codec."); + + w = strtol(width_arg, NULL, 0); + h = strtol(height_arg, NULL, 0); + + if (w <= 0 || h <= 0 || (w % 2) != 0 || (h % 2) != 0) + die("Invalid frame size: %dx%d", w, h); + + if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, w, h, 1)) + die("Failed to allocate image", w, h); + + printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface())); + + // Configuration + res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0); + if (res) + die_codec(&codec, "Failed to get default codec config."); + + cfg.g_w = w; + cfg.g_h = h; + cfg.g_timebase.num = 1; + cfg.g_timebase.den = fps; + cfg.rc_target_bitrate = bitrate; + + if (!(infile = fopen(infile_arg, "rb"))) + die("Failed to open %s for reading", infile_arg); + + // Pass 0 + cfg.g_pass = VPX_RC_FIRST_PASS; + stats = pass0(&raw, infile, encoder, &cfg, max_frames); + + // Pass 1 + rewind(infile); + cfg.g_pass = VPX_RC_LAST_PASS; + cfg.rc_twopass_stats_in = stats; + pass1(&raw, infile, outfile_arg, encoder, &cfg, max_frames); + free(stats.buf); + + vpx_img_free(&raw); + fclose(infile); + + return EXIT_SUCCESS; +}
diff --git a/src/third_party/libvpx/examples/vp8_multi_resolution_encoder.c b/src/third_party/libvpx/examples/vp8_multi_resolution_encoder.c new file mode 100644 index 0000000..fc775ef --- /dev/null +++ b/src/third_party/libvpx/examples/vp8_multi_resolution_encoder.c
@@ -0,0 +1,731 @@ +/* + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +/* + * This is an example demonstrating multi-resolution encoding in VP8. + * High-resolution input video is down-sampled to lower-resolutions. The + * encoder then encodes the video and outputs multiple bitstreams with + * different resolutions. + * + * This test also allows for settings temporal layers for each spatial layer. + * Different number of temporal layers per spatial stream may be used. + * Currently up to 3 temporal layers per spatial stream (encoder) are supported + * in this test. + */ + +#include "./vpx_config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <math.h> +#include <assert.h> +#include <sys/time.h> +#include "vpx_ports/vpx_timer.h" +#include "vpx/vpx_encoder.h" +#include "vpx/vp8cx.h" +#include "vpx_ports/mem_ops.h" +#include "../tools_common.h" +#define interface (vpx_codec_vp8_cx()) +#define fourcc 0x30385056 + +void usage_exit(void) { + exit(EXIT_FAILURE); +} + +/* + * The input video frame is downsampled several times to generate a multi-level + * hierarchical structure. NUM_ENCODERS is defined as the number of encoding + * levels required. For example, if the size of input video is 1280x720, + * NUM_ENCODERS is 3, and down-sampling factor is 2, the encoder outputs 3 + * bitstreams with resolution of 1280x720(level 0), 640x360(level 1), and + * 320x180(level 2) respectively. + */ + +/* Number of encoders (spatial resolutions) used in this test. */ +#define NUM_ENCODERS 3 + +/* Maximum number of temporal layers allowed for this test. */ +#define MAX_NUM_TEMPORAL_LAYERS 3 + +/* This example uses the scaler function in libyuv. */ +#include "third_party/libyuv/include/libyuv/basic_types.h" +#include "third_party/libyuv/include/libyuv/scale.h" +#include "third_party/libyuv/include/libyuv/cpu_id.h" + +int (*read_frame_p)(FILE *f, vpx_image_t *img); + +static int read_frame(FILE *f, vpx_image_t *img) { + size_t nbytes, to_read; + int res = 1; + + to_read = img->w*img->h*3/2; + nbytes = fread(img->planes[0], 1, to_read, f); + if(nbytes != to_read) { + res = 0; + if(nbytes > 0) + printf("Warning: Read partial frame. Check your width & height!\n"); + } + return res; +} + +static int read_frame_by_row(FILE *f, vpx_image_t *img) { + size_t nbytes, to_read; + int res = 1; + int plane; + + for (plane = 0; plane < 3; plane++) + { + unsigned char *ptr; + int w = (plane ? (1 + img->d_w) / 2 : img->d_w); + int h = (plane ? (1 + img->d_h) / 2 : img->d_h); + int r; + + /* Determine the correct plane based on the image format. The for-loop + * always counts in Y,U,V order, but this may not match the order of + * the data on disk. + */ + switch (plane) + { + case 1: + ptr = img->planes[img->fmt==VPX_IMG_FMT_YV12? VPX_PLANE_V : VPX_PLANE_U]; + break; + case 2: + ptr = img->planes[img->fmt==VPX_IMG_FMT_YV12?VPX_PLANE_U : VPX_PLANE_V]; + break; + default: + ptr = img->planes[plane]; + } + + for (r = 0; r < h; r++) + { + to_read = w; + + nbytes = fread(ptr, 1, to_read, f); + if(nbytes != to_read) { + res = 0; + if(nbytes > 0) + printf("Warning: Read partial frame. Check your width & height!\n"); + break; + } + + ptr += img->stride[plane]; + } + if (!res) + break; + } + + return res; +} + +static void write_ivf_file_header(FILE *outfile, + const vpx_codec_enc_cfg_t *cfg, + int frame_cnt) { + char header[32]; + + if(cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS) + return; + header[0] = 'D'; + header[1] = 'K'; + header[2] = 'I'; + header[3] = 'F'; + mem_put_le16(header+4, 0); /* version */ + mem_put_le16(header+6, 32); /* headersize */ + mem_put_le32(header+8, fourcc); /* headersize */ + mem_put_le16(header+12, cfg->g_w); /* width */ + mem_put_le16(header+14, cfg->g_h); /* height */ + mem_put_le32(header+16, cfg->g_timebase.den); /* rate */ + mem_put_le32(header+20, cfg->g_timebase.num); /* scale */ + mem_put_le32(header+24, frame_cnt); /* length */ + mem_put_le32(header+28, 0); /* unused */ + + (void) fwrite(header, 1, 32, outfile); +} + +static void write_ivf_frame_header(FILE *outfile, + const vpx_codec_cx_pkt_t *pkt) +{ + char header[12]; + vpx_codec_pts_t pts; + + if(pkt->kind != VPX_CODEC_CX_FRAME_PKT) + return; + + pts = pkt->data.frame.pts; + mem_put_le32(header, pkt->data.frame.sz); + mem_put_le32(header+4, pts&0xFFFFFFFF); + mem_put_le32(header+8, pts >> 32); + + (void) fwrite(header, 1, 12, outfile); +} + +/* Temporal scaling parameters */ +/* This sets all the temporal layer parameters given |num_temporal_layers|, + * including the target bit allocation across temporal layers. Bit allocation + * parameters will be passed in as user parameters in another version. + */ +static void set_temporal_layer_pattern(int num_temporal_layers, + vpx_codec_enc_cfg_t *cfg, + int bitrate, + int *layer_flags) +{ + assert(num_temporal_layers <= MAX_NUM_TEMPORAL_LAYERS); + switch (num_temporal_layers) + { + case 1: + { + /* 1-layer */ + cfg->ts_number_layers = 1; + cfg->ts_periodicity = 1; + cfg->ts_rate_decimator[0] = 1; + cfg->ts_layer_id[0] = 0; + cfg->ts_target_bitrate[0] = bitrate; + + // Update L only. + layer_flags[0] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; + break; + } + + case 2: + { + /* 2-layers, with sync point at first frame of layer 1. */ + cfg->ts_number_layers = 2; + cfg->ts_periodicity = 2; + cfg->ts_rate_decimator[0] = 2; + cfg->ts_rate_decimator[1] = 1; + cfg->ts_layer_id[0] = 0; + cfg->ts_layer_id[1] = 1; + // Use 60/40 bit allocation as example. + cfg->ts_target_bitrate[0] = 0.6f * bitrate; + cfg->ts_target_bitrate[1] = bitrate; + + /* 0=L, 1=GF */ + // ARF is used as predictor for all frames, and is only updated on + // key frame. Sync point every 8 frames. + + // Layer 0: predict from L and ARF, update L and G. + layer_flags[0] = VP8_EFLAG_NO_REF_GF | + VP8_EFLAG_NO_UPD_ARF; + + // Layer 1: sync point: predict from L and ARF, and update G. + layer_flags[1] = VP8_EFLAG_NO_REF_GF | + VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_UPD_ARF; + + // Layer 0, predict from L and ARF, update L. + layer_flags[2] = VP8_EFLAG_NO_REF_GF | + VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF; + + // Layer 1: predict from L, G and ARF, and update G. + layer_flags[3] = VP8_EFLAG_NO_UPD_ARF | + VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_UPD_ENTROPY; + + // Layer 0 + layer_flags[4] = layer_flags[2]; + + // Layer 1 + layer_flags[5] = layer_flags[3]; + + // Layer 0 + layer_flags[6] = layer_flags[4]; + + // Layer 1 + layer_flags[7] = layer_flags[5]; + break; + } + + case 3: + default: + { + // 3-layers structure where ARF is used as predictor for all frames, + // and is only updated on key frame. + // Sync points for layer 1 and 2 every 8 frames. + cfg->ts_number_layers = 3; + cfg->ts_periodicity = 4; + cfg->ts_rate_decimator[0] = 4; + cfg->ts_rate_decimator[1] = 2; + cfg->ts_rate_decimator[2] = 1; + cfg->ts_layer_id[0] = 0; + cfg->ts_layer_id[1] = 2; + cfg->ts_layer_id[2] = 1; + cfg->ts_layer_id[3] = 2; + // Use 40/20/40 bit allocation as example. + cfg->ts_target_bitrate[0] = 0.4f * bitrate; + cfg->ts_target_bitrate[1] = 0.6f * bitrate; + cfg->ts_target_bitrate[2] = bitrate; + + /* 0=L, 1=GF, 2=ARF */ + + // Layer 0: predict from L and ARF; update L and G. + layer_flags[0] = VP8_EFLAG_NO_UPD_ARF | + VP8_EFLAG_NO_REF_GF; + + // Layer 2: sync point: predict from L and ARF; update none. + layer_flags[1] = VP8_EFLAG_NO_REF_GF | + VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF | + VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_UPD_ENTROPY; + + // Layer 1: sync point: predict from L and ARF; update G. + layer_flags[2] = VP8_EFLAG_NO_REF_GF | + VP8_EFLAG_NO_UPD_ARF | + VP8_EFLAG_NO_UPD_LAST; + + // Layer 2: predict from L, G, ARF; update none. + layer_flags[3] = VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF | + VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_UPD_ENTROPY; + + // Layer 0: predict from L and ARF; update L. + layer_flags[4] = VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF | + VP8_EFLAG_NO_REF_GF; + + // Layer 2: predict from L, G, ARF; update none. + layer_flags[5] = layer_flags[3]; + + // Layer 1: predict from L, G, ARF; update G. + layer_flags[6] = VP8_EFLAG_NO_UPD_ARF | + VP8_EFLAG_NO_UPD_LAST; + + // Layer 2: predict from L, G, ARF; update none. + layer_flags[7] = layer_flags[3]; + break; + } + } +} + +/* The periodicity of the pattern given the number of temporal layers. */ +static int periodicity_to_num_layers[MAX_NUM_TEMPORAL_LAYERS] = {1, 8, 8}; + +int main(int argc, char **argv) +{ + FILE *infile, *outfile[NUM_ENCODERS]; + FILE *downsampled_input[NUM_ENCODERS - 1]; + char filename[50]; + vpx_codec_ctx_t codec[NUM_ENCODERS]; + vpx_codec_enc_cfg_t cfg[NUM_ENCODERS]; + int frame_cnt = 0; + vpx_image_t raw[NUM_ENCODERS]; + vpx_codec_err_t res[NUM_ENCODERS]; + + int i; + long width; + long height; + int length_frame; + int frame_avail; + int got_data; + int flags = 0; + int layer_id = 0; + + int layer_flags[VPX_TS_MAX_PERIODICITY * NUM_ENCODERS] + = {0}; + int flag_periodicity; + + /*Currently, only realtime mode is supported in multi-resolution encoding.*/ + int arg_deadline = VPX_DL_REALTIME; + + /* Set show_psnr to 1/0 to show/not show PSNR. Choose show_psnr=0 if you + don't need to know PSNR, which will skip PSNR calculation and save + encoding time. */ + int show_psnr = 0; + int key_frame_insert = 0; + uint64_t psnr_sse_total[NUM_ENCODERS] = {0}; + uint64_t psnr_samples_total[NUM_ENCODERS] = {0}; + double psnr_totals[NUM_ENCODERS][4] = {{0,0}}; + int psnr_count[NUM_ENCODERS] = {0}; + + int64_t cx_time = 0; + + /* Set the required target bitrates for each resolution level. + * If target bitrate for highest-resolution level is set to 0, + * (i.e. target_bitrate[0]=0), we skip encoding at that level. + */ + unsigned int target_bitrate[NUM_ENCODERS]={1000, 500, 100}; + + /* Enter the frame rate of the input video */ + int framerate = 30; + + /* Set down-sampling factor for each resolution level. + dsf[0] controls down sampling from level 0 to level 1; + dsf[1] controls down sampling from level 1 to level 2; + dsf[2] is not used. */ + vpx_rational_t dsf[NUM_ENCODERS] = {{2, 1}, {2, 1}, {1, 1}}; + + /* Set the number of temporal layers for each encoder/resolution level, + * starting from highest resoln down to lowest resoln. */ + unsigned int num_temporal_layers[NUM_ENCODERS] = {3, 3, 3}; + + if(argc!= (7 + 3 * NUM_ENCODERS)) + die("Usage: %s <width> <height> <frame_rate> <infile> <outfile(s)> " + "<rate_encoder(s)> <temporal_layer(s)> <key_frame_insert> <output psnr?> \n", + argv[0]); + + printf("Using %s\n",vpx_codec_iface_name(interface)); + + width = strtol(argv[1], NULL, 0); + height = strtol(argv[2], NULL, 0); + framerate = strtol(argv[3], NULL, 0); + + if(width < 16 || width%2 || height <16 || height%2) + die("Invalid resolution: %ldx%ld", width, height); + + /* Open input video file for encoding */ + if(!(infile = fopen(argv[4], "rb"))) + die("Failed to open %s for reading", argv[4]); + + /* Open output file for each encoder to output bitstreams */ + for (i=0; i< NUM_ENCODERS; i++) + { + if(!target_bitrate[i]) + { + outfile[i] = NULL; + continue; + } + + if(!(outfile[i] = fopen(argv[i+5], "wb"))) + die("Failed to open %s for writing", argv[i+4]); + } + + // Bitrates per spatial layer: overwrite default rates above. + for (i=0; i< NUM_ENCODERS; i++) + { + target_bitrate[i] = strtol(argv[NUM_ENCODERS + 5 + i], NULL, 0); + } + + // Temporal layers per spatial layers: overwrite default settings above. + for (i=0; i< NUM_ENCODERS; i++) + { + num_temporal_layers[i] = strtol(argv[2 * NUM_ENCODERS + 5 + i], NULL, 0); + if (num_temporal_layers[i] < 1 || num_temporal_layers[i] > 3) + die("Invalid temporal layers: %d, Must be 1, 2, or 3. \n", + num_temporal_layers); + } + + /* Open file to write out each spatially downsampled input stream. */ + for (i=0; i< NUM_ENCODERS - 1; i++) + { + // Highest resoln is encoder 0. + if (sprintf(filename,"ds%d.yuv",NUM_ENCODERS - i) < 0) + { + return EXIT_FAILURE; + } + downsampled_input[i] = fopen(filename,"wb"); + } + + key_frame_insert = strtol(argv[3 * NUM_ENCODERS + 5], NULL, 0); + + show_psnr = strtol(argv[3 * NUM_ENCODERS + 6], NULL, 0); + + + /* Populate default encoder configuration */ + for (i=0; i< NUM_ENCODERS; i++) + { + res[i] = vpx_codec_enc_config_default(interface, &cfg[i], 0); + if(res[i]) { + printf("Failed to get config: %s\n", vpx_codec_err_to_string(res[i])); + return EXIT_FAILURE; + } + } + + /* + * Update the default configuration according to needs of the application. + */ + /* Highest-resolution encoder settings */ + cfg[0].g_w = width; + cfg[0].g_h = height; + cfg[0].rc_dropframe_thresh = 0; + cfg[0].rc_end_usage = VPX_CBR; + cfg[0].rc_resize_allowed = 0; + cfg[0].rc_min_quantizer = 2; + cfg[0].rc_max_quantizer = 56; + cfg[0].rc_undershoot_pct = 100; + cfg[0].rc_overshoot_pct = 15; + cfg[0].rc_buf_initial_sz = 500; + cfg[0].rc_buf_optimal_sz = 600; + cfg[0].rc_buf_sz = 1000; + cfg[0].g_error_resilient = 1; /* Enable error resilient mode */ + cfg[0].g_lag_in_frames = 0; + + /* Disable automatic keyframe placement */ + /* Note: These 3 settings are copied to all levels. But, except the lowest + * resolution level, all other levels are set to VPX_KF_DISABLED internally. + */ + cfg[0].kf_mode = VPX_KF_AUTO; + cfg[0].kf_min_dist = 3000; + cfg[0].kf_max_dist = 3000; + + cfg[0].rc_target_bitrate = target_bitrate[0]; /* Set target bitrate */ + cfg[0].g_timebase.num = 1; /* Set fps */ + cfg[0].g_timebase.den = framerate; + + /* Other-resolution encoder settings */ + for (i=1; i< NUM_ENCODERS; i++) + { + memcpy(&cfg[i], &cfg[0], sizeof(vpx_codec_enc_cfg_t)); + + cfg[i].rc_target_bitrate = target_bitrate[i]; + + /* Note: Width & height of other-resolution encoders are calculated + * from the highest-resolution encoder's size and the corresponding + * down_sampling_factor. + */ + { + unsigned int iw = cfg[i-1].g_w*dsf[i-1].den + dsf[i-1].num - 1; + unsigned int ih = cfg[i-1].g_h*dsf[i-1].den + dsf[i-1].num - 1; + cfg[i].g_w = iw/dsf[i-1].num; + cfg[i].g_h = ih/dsf[i-1].num; + } + + /* Make width & height to be multiplier of 2. */ + // Should support odd size ??? + if((cfg[i].g_w)%2)cfg[i].g_w++; + if((cfg[i].g_h)%2)cfg[i].g_h++; + } + + + // Set the number of threads per encode/spatial layer. + // (1, 1, 1) means no encoder threading. + cfg[0].g_threads = 2; + cfg[1].g_threads = 1; + cfg[2].g_threads = 1; + + /* Allocate image for each encoder */ + for (i=0; i< NUM_ENCODERS; i++) + if(!vpx_img_alloc(&raw[i], VPX_IMG_FMT_I420, cfg[i].g_w, cfg[i].g_h, 32)) + die("Failed to allocate image", cfg[i].g_w, cfg[i].g_h); + + if (raw[0].stride[VPX_PLANE_Y] == raw[0].d_w) + read_frame_p = read_frame; + else + read_frame_p = read_frame_by_row; + + for (i=0; i< NUM_ENCODERS; i++) + if(outfile[i]) + write_ivf_file_header(outfile[i], &cfg[i], 0); + + /* Temporal layers settings */ + for ( i=0; i<NUM_ENCODERS; i++) + { + set_temporal_layer_pattern(num_temporal_layers[i], + &cfg[i], + cfg[i].rc_target_bitrate, + &layer_flags[i * VPX_TS_MAX_PERIODICITY]); + } + + /* Initialize multi-encoder */ + if(vpx_codec_enc_init_multi(&codec[0], interface, &cfg[0], NUM_ENCODERS, + (show_psnr ? VPX_CODEC_USE_PSNR : 0), &dsf[0])) + die_codec(&codec[0], "Failed to initialize encoder"); + + /* The extra encoding configuration parameters can be set as follows. */ + /* Set encoding speed */ + for ( i=0; i<NUM_ENCODERS; i++) + { + int speed = -6; + /* Lower speed for the lowest resolution. */ + if (i == NUM_ENCODERS - 1) speed = -4; + if(vpx_codec_control(&codec[i], VP8E_SET_CPUUSED, speed)) + die_codec(&codec[i], "Failed to set cpu_used"); + } + + /* Set static threshold = 1 for all encoders */ + for ( i=0; i<NUM_ENCODERS; i++) + { + if(vpx_codec_control(&codec[i], VP8E_SET_STATIC_THRESHOLD, 1)) + die_codec(&codec[i], "Failed to set static threshold"); + } + + /* Set NOISE_SENSITIVITY to do TEMPORAL_DENOISING */ + /* Enable denoising for the highest-resolution encoder. */ + if(vpx_codec_control(&codec[0], VP8E_SET_NOISE_SENSITIVITY, 1)) + die_codec(&codec[0], "Failed to set noise_sensitivity"); + for ( i=1; i< NUM_ENCODERS; i++) + { + if(vpx_codec_control(&codec[i], VP8E_SET_NOISE_SENSITIVITY, 0)) + die_codec(&codec[i], "Failed to set noise_sensitivity"); + } + + /* Set the number of token partitions */ + for ( i=0; i<NUM_ENCODERS; i++) + { + if(vpx_codec_control(&codec[i], VP8E_SET_TOKEN_PARTITIONS, 1)) + die_codec(&codec[i], "Failed to set static threshold"); + } + + /* Set the max intra target bitrate */ + for ( i=0; i<NUM_ENCODERS; i++) + { + unsigned int max_intra_size_pct = + (int)(((double)cfg[0].rc_buf_optimal_sz * 0.5) * framerate / 10); + if(vpx_codec_control(&codec[i], VP8E_SET_MAX_INTRA_BITRATE_PCT, + max_intra_size_pct)) + die_codec(&codec[i], "Failed to set static threshold"); + //printf("%d %d \n",i,max_intra_size_pct); + } + + frame_avail = 1; + got_data = 0; + + while(frame_avail || got_data) + { + struct vpx_usec_timer timer; + vpx_codec_iter_t iter[NUM_ENCODERS]={NULL}; + const vpx_codec_cx_pkt_t *pkt[NUM_ENCODERS]; + + flags = 0; + frame_avail = read_frame_p(infile, &raw[0]); + + if(frame_avail) + { + for ( i=1; i<NUM_ENCODERS; i++) + { + /*Scale the image down a number of times by downsampling factor*/ + /* FilterMode 1 or 2 give better psnr than FilterMode 0. */ + I420Scale(raw[i-1].planes[VPX_PLANE_Y], raw[i-1].stride[VPX_PLANE_Y], + raw[i-1].planes[VPX_PLANE_U], raw[i-1].stride[VPX_PLANE_U], + raw[i-1].planes[VPX_PLANE_V], raw[i-1].stride[VPX_PLANE_V], + raw[i-1].d_w, raw[i-1].d_h, + raw[i].planes[VPX_PLANE_Y], raw[i].stride[VPX_PLANE_Y], + raw[i].planes[VPX_PLANE_U], raw[i].stride[VPX_PLANE_U], + raw[i].planes[VPX_PLANE_V], raw[i].stride[VPX_PLANE_V], + raw[i].d_w, raw[i].d_h, 1); + /* Write out down-sampled input. */ + length_frame = cfg[i].g_w * cfg[i].g_h *3/2; + if (fwrite(raw[i].planes[0], 1, length_frame, + downsampled_input[NUM_ENCODERS - i - 1]) != + length_frame) + { + return EXIT_FAILURE; + } + } + } + + /* Set the flags (reference and update) for all the encoders.*/ + for ( i=0; i<NUM_ENCODERS; i++) + { + layer_id = cfg[i].ts_layer_id[frame_cnt % cfg[i].ts_periodicity]; + flags = 0; + flag_periodicity = periodicity_to_num_layers + [num_temporal_layers[i] - 1]; + flags = layer_flags[i * VPX_TS_MAX_PERIODICITY + + frame_cnt % flag_periodicity]; + // Key frame flag for first frame. + if (frame_cnt == 0) + { + flags |= VPX_EFLAG_FORCE_KF; + } + if (frame_cnt > 0 && frame_cnt == key_frame_insert) + { + flags = VPX_EFLAG_FORCE_KF; + } + + vpx_codec_control(&codec[i], VP8E_SET_FRAME_FLAGS, flags); + vpx_codec_control(&codec[i], VP8E_SET_TEMPORAL_LAYER_ID, layer_id); + } + + /* Encode each frame at multi-levels */ + /* Note the flags must be set to 0 in the encode call if they are set + for each frame with the vpx_codec_control(), as done above. */ + vpx_usec_timer_start(&timer); + if(vpx_codec_encode(&codec[0], frame_avail? &raw[0] : NULL, + frame_cnt, 1, 0, arg_deadline)) + { + die_codec(&codec[0], "Failed to encode frame"); + } + vpx_usec_timer_mark(&timer); + cx_time += vpx_usec_timer_elapsed(&timer); + + for (i=NUM_ENCODERS-1; i>=0 ; i--) + { + got_data = 0; + while( (pkt[i] = vpx_codec_get_cx_data(&codec[i], &iter[i])) ) + { + got_data = 1; + switch(pkt[i]->kind) { + case VPX_CODEC_CX_FRAME_PKT: + write_ivf_frame_header(outfile[i], pkt[i]); + (void) fwrite(pkt[i]->data.frame.buf, 1, + pkt[i]->data.frame.sz, outfile[i]); + break; + case VPX_CODEC_PSNR_PKT: + if (show_psnr) + { + int j; + + psnr_sse_total[i] += pkt[i]->data.psnr.sse[0]; + psnr_samples_total[i] += pkt[i]->data.psnr.samples[0]; + for (j = 0; j < 4; j++) + { + psnr_totals[i][j] += pkt[i]->data.psnr.psnr[j]; + } + psnr_count[i]++; + } + + break; + default: + break; + } + printf(pkt[i]->kind == VPX_CODEC_CX_FRAME_PKT + && (pkt[i]->data.frame.flags & VPX_FRAME_IS_KEY)? "K":""); + fflush(stdout); + } + } + frame_cnt++; + } + printf("\n"); + printf("Frame cnt and encoding time/FPS stats for encoding: %d %f %f \n", + frame_cnt, + 1000 * (float)cx_time / (double)(frame_cnt * 1000000), + 1000000 * (double)frame_cnt / (double)cx_time); + + fclose(infile); + + printf("Processed %ld frames.\n",(long int)frame_cnt-1); + for (i=0; i< NUM_ENCODERS; i++) + { + /* Calculate PSNR and print it out */ + if ( (show_psnr) && (psnr_count[i]>0) ) + { + int j; + double ovpsnr = sse_to_psnr(psnr_samples_total[i], 255.0, + psnr_sse_total[i]); + + fprintf(stderr, "\n ENC%d PSNR (Overall/Avg/Y/U/V)", i); + + fprintf(stderr, " %.3lf", ovpsnr); + for (j = 0; j < 4; j++) + { + fprintf(stderr, " %.3lf", psnr_totals[i][j]/psnr_count[i]); + } + } + + if(vpx_codec_destroy(&codec[i])) + die_codec(&codec[i], "Failed to destroy codec"); + + vpx_img_free(&raw[i]); + + if(!outfile[i]) + continue; + + /* Try to rewrite the file header with the actual frame count */ + if(!fseek(outfile[i], 0, SEEK_SET)) + write_ivf_file_header(outfile[i], &cfg[i], frame_cnt-1); + fclose(outfile[i]); + } + printf("\n"); + + return EXIT_SUCCESS; +}
diff --git a/src/third_party/libvpx/examples/vp8cx_set_ref.c b/src/third_party/libvpx/examples/vp8cx_set_ref.c new file mode 100644 index 0000000..8b4cc30 --- /dev/null +++ b/src/third_party/libvpx/examples/vp8cx_set_ref.c
@@ -0,0 +1,194 @@ +/* + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + + +// VP8 Set Reference Frame +// ======================= +// +// This is an example demonstrating how to overwrite the VP8 encoder's +// internal reference frame. In the sample we set the last frame to the +// current frame. If this is done at a cut scene it will avoid a keyframe. +// This technique could be used to bounce between two cameras. +// +// Note that the decoder would also have to set the reference frame to the +// same value on the same frame, or the video will become corrupt. +// +// Usage +// ----- +// This example adds a single argument to the `simple_encoder` example, +// which specifies the frame number to update the reference frame on. +// The parameter is parsed as follows: +// +// +// Extra Variables +// --------------- +// This example maintains the frame number passed on the command line +// in the `update_frame_num` variable. +// +// +// Configuration +// ------------- +// +// The reference frame is updated on the frame specified on the command +// line. +// +// Observing The Effects +// --------------------- +// Use the `simple_encoder` example to encode a sample with a cut scene. +// Determine the frame number of the cut scene by looking for a generated +// key-frame (indicated by a 'K'). Supply that frame number as an argument +// to this example, and observe that no key-frame is generated. + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "vpx/vp8cx.h" +#include "vpx/vpx_encoder.h" + +#include "../tools_common.h" +#include "../video_writer.h" + +static const char *exec_name; + +void usage_exit(void) { + fprintf(stderr, "Usage: %s <width> <height> <infile> <outfile> <frame>\n", + exec_name); + exit(EXIT_FAILURE); +} + +static int encode_frame(vpx_codec_ctx_t *codec, + vpx_image_t *img, + int frame_index, + VpxVideoWriter *writer) { + int got_pkts = 0; + vpx_codec_iter_t iter = NULL; + const vpx_codec_cx_pkt_t *pkt = NULL; + const vpx_codec_err_t res = vpx_codec_encode(codec, img, frame_index, 1, 0, + VPX_DL_GOOD_QUALITY); + if (res != VPX_CODEC_OK) + die_codec(codec, "Failed to encode frame"); + + while ((pkt = vpx_codec_get_cx_data(codec, &iter)) != NULL) { + got_pkts = 1; + + if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { + const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0; + if (!vpx_video_writer_write_frame(writer, + pkt->data.frame.buf, + pkt->data.frame.sz, + pkt->data.frame.pts)) { + die_codec(codec, "Failed to write compressed frame"); + } + + printf(keyframe ? "K" : "."); + fflush(stdout); + } + } + + return got_pkts; +} + +int main(int argc, char **argv) { + FILE *infile = NULL; + vpx_codec_ctx_t codec = {0}; + vpx_codec_enc_cfg_t cfg = {0}; + int frame_count = 0; + vpx_image_t raw; + vpx_codec_err_t res; + VpxVideoInfo info = {0}; + VpxVideoWriter *writer = NULL; + const VpxInterface *encoder = NULL; + int update_frame_num = 0; + const int fps = 30; // TODO(dkovalev) add command line argument + const int bitrate = 200; // kbit/s TODO(dkovalev) add command line argument + + exec_name = argv[0]; + + if (argc != 6) + die("Invalid number of arguments"); + + // TODO(dkovalev): add vp9 support and rename the file accordingly + encoder = get_vpx_encoder_by_name("vp8"); + if (!encoder) + die("Unsupported codec."); + + update_frame_num = atoi(argv[5]); + if (!update_frame_num) + die("Couldn't parse frame number '%s'\n", argv[5]); + + info.codec_fourcc = encoder->fourcc; + info.frame_width = strtol(argv[1], NULL, 0); + info.frame_height = strtol(argv[2], NULL, 0); + info.time_base.numerator = 1; + info.time_base.denominator = fps; + + if (info.frame_width <= 0 || + info.frame_height <= 0 || + (info.frame_width % 2) != 0 || + (info.frame_height % 2) != 0) { + die("Invalid frame size: %dx%d", info.frame_width, info.frame_height); + } + + if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width, + info.frame_height, 1)) { + die("Failed to allocate image."); + } + + printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface())); + + res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0); + if (res) + die_codec(&codec, "Failed to get default codec config."); + + cfg.g_w = info.frame_width; + cfg.g_h = info.frame_height; + cfg.g_timebase.num = info.time_base.numerator; + cfg.g_timebase.den = info.time_base.denominator; + cfg.rc_target_bitrate = bitrate; + + writer = vpx_video_writer_open(argv[4], kContainerIVF, &info); + if (!writer) + die("Failed to open %s for writing.", argv[4]); + + if (!(infile = fopen(argv[3], "rb"))) + die("Failed to open %s for reading.", argv[3]); + + if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0)) + die_codec(&codec, "Failed to initialize encoder"); + + // Encode frames. + while (vpx_img_read(&raw, infile)) { + if (frame_count + 1 == update_frame_num) { + vpx_ref_frame_t ref; + ref.frame_type = VP8_LAST_FRAME; + ref.img = raw; + if (vpx_codec_control(&codec, VP8_SET_REFERENCE, &ref)) + die_codec(&codec, "Failed to set reference frame"); + } + + encode_frame(&codec, &raw, frame_count++, writer); + } + + // Flush encoder. + while (encode_frame(&codec, NULL, -1, writer)) {} + + printf("\n"); + fclose(infile); + printf("Processed %d frames.\n", frame_count); + + vpx_img_free(&raw); + if (vpx_codec_destroy(&codec)) + die_codec(&codec, "Failed to destroy codec."); + + vpx_video_writer_close(writer); + + return EXIT_SUCCESS; +}
diff --git a/src/third_party/libvpx/examples/vp9_lossless_encoder.c b/src/third_party/libvpx/examples/vp9_lossless_encoder.c new file mode 100644 index 0000000..8272516 --- /dev/null +++ b/src/third_party/libvpx/examples/vp9_lossless_encoder.c
@@ -0,0 +1,144 @@ +/* + * Copyright (c) 2014 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "vpx/vpx_encoder.h" +#include "vpx/vp8cx.h" + +#include "../tools_common.h" +#include "../video_writer.h" + +static const char *exec_name; + +void usage_exit(void) { + fprintf(stderr, "vp9_lossless_encoder: Example demonstrating VP9 lossless " + "encoding feature. Supports raw input only.\n"); + fprintf(stderr, "Usage: %s <width> <height> <infile> <outfile>\n", exec_name); + exit(EXIT_FAILURE); +} + +static int encode_frame(vpx_codec_ctx_t *codec, + vpx_image_t *img, + int frame_index, + int flags, + VpxVideoWriter *writer) { + int got_pkts = 0; + vpx_codec_iter_t iter = NULL; + const vpx_codec_cx_pkt_t *pkt = NULL; + const vpx_codec_err_t res = vpx_codec_encode(codec, img, frame_index, 1, + flags, VPX_DL_GOOD_QUALITY); + if (res != VPX_CODEC_OK) + die_codec(codec, "Failed to encode frame"); + + while ((pkt = vpx_codec_get_cx_data(codec, &iter)) != NULL) { + got_pkts = 1; + + if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { + const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0; + if (!vpx_video_writer_write_frame(writer, + pkt->data.frame.buf, + pkt->data.frame.sz, + pkt->data.frame.pts)) { + die_codec(codec, "Failed to write compressed frame"); + } + printf(keyframe ? "K" : "."); + fflush(stdout); + } + } + + return got_pkts; +} + +int main(int argc, char **argv) { + FILE *infile = NULL; + vpx_codec_ctx_t codec; + vpx_codec_enc_cfg_t cfg; + int frame_count = 0; + vpx_image_t raw; + vpx_codec_err_t res; + VpxVideoInfo info = {0}; + VpxVideoWriter *writer = NULL; + const VpxInterface *encoder = NULL; + const int fps = 30; + + exec_name = argv[0]; + + if (argc < 5) + die("Invalid number of arguments"); + + encoder = get_vpx_encoder_by_name("vp9"); + if (!encoder) + die("Unsupported codec."); + + info.codec_fourcc = encoder->fourcc; + info.frame_width = strtol(argv[1], NULL, 0); + info.frame_height = strtol(argv[2], NULL, 0); + info.time_base.numerator = 1; + info.time_base.denominator = fps; + + if (info.frame_width <= 0 || + info.frame_height <= 0 || + (info.frame_width % 2) != 0 || + (info.frame_height % 2) != 0) { + die("Invalid frame size: %dx%d", info.frame_width, info.frame_height); + } + + if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width, + info.frame_height, 1)) { + die("Failed to allocate image."); + } + + printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface())); + + res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0); + if (res) + die_codec(&codec, "Failed to get default codec config."); + + cfg.g_w = info.frame_width; + cfg.g_h = info.frame_height; + cfg.g_timebase.num = info.time_base.numerator; + cfg.g_timebase.den = info.time_base.denominator; + + writer = vpx_video_writer_open(argv[4], kContainerIVF, &info); + if (!writer) + die("Failed to open %s for writing.", argv[4]); + + if (!(infile = fopen(argv[3], "rb"))) + die("Failed to open %s for reading.", argv[3]); + + if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0)) + die_codec(&codec, "Failed to initialize encoder"); + + if (vpx_codec_control_(&codec, VP9E_SET_LOSSLESS, 1)) + die_codec(&codec, "Failed to use lossless mode"); + + // Encode frames. + while (vpx_img_read(&raw, infile)) { + encode_frame(&codec, &raw, frame_count++, 0, writer); + } + + // Flush encoder. + while (encode_frame(&codec, NULL, -1, 0, writer)) {} + + printf("\n"); + fclose(infile); + printf("Processed %d frames.\n", frame_count); + + vpx_img_free(&raw); + if (vpx_codec_destroy(&codec)) + die_codec(&codec, "Failed to destroy codec."); + + vpx_video_writer_close(writer); + + return EXIT_SUCCESS; +}
diff --git a/src/third_party/libvpx/examples/vp9_spatial_svc_encoder.c b/src/third_party/libvpx/examples/vp9_spatial_svc_encoder.c new file mode 100644 index 0000000..271ab70 --- /dev/null +++ b/src/third_party/libvpx/examples/vp9_spatial_svc_encoder.c
@@ -0,0 +1,919 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +/* + * This is an example demonstrating how to implement a multi-layer + * VP9 encoding scheme based on spatial scalability for video applications + * that benefit from a scalable bitstream. + */ + +#include <math.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + + +#include "../args.h" +#include "../tools_common.h" +#include "../video_writer.h" + +#include "../vpx_ports/vpx_timer.h" +#include "vpx/svc_context.h" +#include "vpx/vp8cx.h" +#include "vpx/vpx_encoder.h" +#include "../vpxstats.h" +#include "vp9/encoder/vp9_encoder.h" +#define OUTPUT_RC_STATS 1 + +static const arg_def_t skip_frames_arg = + ARG_DEF("s", "skip-frames", 1, "input frames to skip"); +static const arg_def_t frames_arg = + ARG_DEF("f", "frames", 1, "number of frames to encode"); +static const arg_def_t threads_arg = + ARG_DEF("th", "threads", 1, "number of threads to use"); +#if OUTPUT_RC_STATS +static const arg_def_t output_rc_stats_arg = + ARG_DEF("rcstat", "output_rc_stats", 1, "output rc stats"); +#endif +static const arg_def_t width_arg = ARG_DEF("w", "width", 1, "source width"); +static const arg_def_t height_arg = ARG_DEF("h", "height", 1, "source height"); +static const arg_def_t timebase_arg = + ARG_DEF("t", "timebase", 1, "timebase (num/den)"); +static const arg_def_t bitrate_arg = ARG_DEF( + "b", "target-bitrate", 1, "encoding bitrate, in kilobits per second"); +static const arg_def_t spatial_layers_arg = + ARG_DEF("sl", "spatial-layers", 1, "number of spatial SVC layers"); +static const arg_def_t temporal_layers_arg = + ARG_DEF("tl", "temporal-layers", 1, "number of temporal SVC layers"); +static const arg_def_t temporal_layering_mode_arg = + ARG_DEF("tlm", "temporal-layering-mode", 1, "temporal layering scheme." + "VP9E_TEMPORAL_LAYERING_MODE"); +static const arg_def_t kf_dist_arg = + ARG_DEF("k", "kf-dist", 1, "number of frames between keyframes"); +static const arg_def_t scale_factors_arg = + ARG_DEF("r", "scale-factors", 1, "scale factors (lowest to highest layer)"); +static const arg_def_t passes_arg = + ARG_DEF("p", "passes", 1, "Number of passes (1/2)"); +static const arg_def_t pass_arg = + ARG_DEF(NULL, "pass", 1, "Pass to execute (1/2)"); +static const arg_def_t fpf_name_arg = + ARG_DEF(NULL, "fpf", 1, "First pass statistics file name"); +static const arg_def_t min_q_arg = + ARG_DEF(NULL, "min-q", 1, "Minimum quantizer"); +static const arg_def_t max_q_arg = + ARG_DEF(NULL, "max-q", 1, "Maximum quantizer"); +static const arg_def_t min_bitrate_arg = + ARG_DEF(NULL, "min-bitrate", 1, "Minimum bitrate"); +static const arg_def_t max_bitrate_arg = + ARG_DEF(NULL, "max-bitrate", 1, "Maximum bitrate"); +static const arg_def_t lag_in_frame_arg = + ARG_DEF(NULL, "lag-in-frames", 1, "Number of frame to input before " + "generating any outputs"); +static const arg_def_t rc_end_usage_arg = + ARG_DEF(NULL, "rc-end-usage", 1, "0 - 3: VBR, CBR, CQ, Q"); +static const arg_def_t speed_arg = + ARG_DEF("sp", "speed", 1, "speed configuration"); +static const arg_def_t aqmode_arg = + ARG_DEF("aq", "aqmode", 1, "aq-mode off/on"); + +#if CONFIG_VP9_HIGHBITDEPTH +static const struct arg_enum_list bitdepth_enum[] = { + {"8", VPX_BITS_8}, + {"10", VPX_BITS_10}, + {"12", VPX_BITS_12}, + {NULL, 0} +}; + +static const arg_def_t bitdepth_arg = + ARG_DEF_ENUM("d", "bit-depth", 1, "Bit depth for codec 8, 10 or 12. ", + bitdepth_enum); +#endif // CONFIG_VP9_HIGHBITDEPTH + + +static const arg_def_t *svc_args[] = { + &frames_arg, &width_arg, &height_arg, + &timebase_arg, &bitrate_arg, &skip_frames_arg, &spatial_layers_arg, + &kf_dist_arg, &scale_factors_arg, &passes_arg, &pass_arg, + &fpf_name_arg, &min_q_arg, &max_q_arg, &min_bitrate_arg, + &max_bitrate_arg, &temporal_layers_arg, &temporal_layering_mode_arg, + &lag_in_frame_arg, &threads_arg, &aqmode_arg, +#if OUTPUT_RC_STATS + &output_rc_stats_arg, +#endif + +#if CONFIG_VP9_HIGHBITDEPTH + &bitdepth_arg, +#endif + &speed_arg, + &rc_end_usage_arg, NULL +}; + +static const uint32_t default_frames_to_skip = 0; +static const uint32_t default_frames_to_code = 60 * 60; +static const uint32_t default_width = 1920; +static const uint32_t default_height = 1080; +static const uint32_t default_timebase_num = 1; +static const uint32_t default_timebase_den = 60; +static const uint32_t default_bitrate = 1000; +static const uint32_t default_spatial_layers = 5; +static const uint32_t default_temporal_layers = 1; +static const uint32_t default_kf_dist = 100; +static const uint32_t default_temporal_layering_mode = 0; +static const uint32_t default_output_rc_stats = 0; +static const int32_t default_speed = -1; // -1 means use library default. +static const uint32_t default_threads = 0; // zero means use library default. + +typedef struct { + const char *input_filename; + const char *output_filename; + uint32_t frames_to_code; + uint32_t frames_to_skip; + struct VpxInputContext input_ctx; + stats_io_t rc_stats; + int passes; + int pass; +} AppInput; + +static const char *exec_name; + +void usage_exit(void) { + fprintf(stderr, "Usage: %s <options> input_filename output_filename\n", + exec_name); + fprintf(stderr, "Options:\n"); + arg_show_usage(stderr, svc_args); + exit(EXIT_FAILURE); +} + +static void parse_command_line(int argc, const char **argv_, + AppInput *app_input, SvcContext *svc_ctx, + vpx_codec_enc_cfg_t *enc_cfg) { + struct arg arg = {0}; + char **argv = NULL; + char **argi = NULL; + char **argj = NULL; + vpx_codec_err_t res; + int passes = 0; + int pass = 0; + const char *fpf_file_name = NULL; + unsigned int min_bitrate = 0; + unsigned int max_bitrate = 0; + char string_options[1024] = {0}; + + // initialize SvcContext with parameters that will be passed to vpx_svc_init + svc_ctx->log_level = SVC_LOG_DEBUG; + svc_ctx->spatial_layers = default_spatial_layers; + svc_ctx->temporal_layers = default_temporal_layers; + svc_ctx->temporal_layering_mode = default_temporal_layering_mode; +#if OUTPUT_RC_STATS + svc_ctx->output_rc_stat = default_output_rc_stats; +#endif + svc_ctx->speed = default_speed; + svc_ctx->threads = default_threads; + + // start with default encoder configuration + res = vpx_codec_enc_config_default(vpx_codec_vp9_cx(), enc_cfg, 0); + if (res) { + die("Failed to get config: %s\n", vpx_codec_err_to_string(res)); + } + // update enc_cfg with app default values + enc_cfg->g_w = default_width; + enc_cfg->g_h = default_height; + enc_cfg->g_timebase.num = default_timebase_num; + enc_cfg->g_timebase.den = default_timebase_den; + enc_cfg->rc_target_bitrate = default_bitrate; + enc_cfg->kf_min_dist = default_kf_dist; + enc_cfg->kf_max_dist = default_kf_dist; + enc_cfg->rc_end_usage = VPX_CQ; + + // initialize AppInput with default values + app_input->frames_to_code = default_frames_to_code; + app_input->frames_to_skip = default_frames_to_skip; + + // process command line options + argv = argv_dup(argc - 1, argv_ + 1); + for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) { + arg.argv_step = 1; + + if (arg_match(&arg, &frames_arg, argi)) { + app_input->frames_to_code = arg_parse_uint(&arg); + } else if (arg_match(&arg, &width_arg, argi)) { + enc_cfg->g_w = arg_parse_uint(&arg); + } else if (arg_match(&arg, &height_arg, argi)) { + enc_cfg->g_h = arg_parse_uint(&arg); + } else if (arg_match(&arg, &timebase_arg, argi)) { + enc_cfg->g_timebase = arg_parse_rational(&arg); + } else if (arg_match(&arg, &bitrate_arg, argi)) { + enc_cfg->rc_target_bitrate = arg_parse_uint(&arg); + } else if (arg_match(&arg, &skip_frames_arg, argi)) { + app_input->frames_to_skip = arg_parse_uint(&arg); + } else if (arg_match(&arg, &spatial_layers_arg, argi)) { + svc_ctx->spatial_layers = arg_parse_uint(&arg); + } else if (arg_match(&arg, &temporal_layers_arg, argi)) { + svc_ctx->temporal_layers = arg_parse_uint(&arg); +#if OUTPUT_RC_STATS + } else if (arg_match(&arg, &output_rc_stats_arg, argi)) { + svc_ctx->output_rc_stat = arg_parse_uint(&arg); +#endif + } else if (arg_match(&arg, &speed_arg, argi)) { + svc_ctx->speed = arg_parse_uint(&arg); + } else if (arg_match(&arg, &aqmode_arg, argi)) { + svc_ctx->aqmode = arg_parse_uint(&arg); + } else if (arg_match(&arg, &threads_arg, argi)) { + svc_ctx->threads = arg_parse_uint(&arg); + } else if (arg_match(&arg, &temporal_layering_mode_arg, argi)) { + svc_ctx->temporal_layering_mode = + enc_cfg->temporal_layering_mode = arg_parse_int(&arg); + if (svc_ctx->temporal_layering_mode) { + enc_cfg->g_error_resilient = 1; + } + } else if (arg_match(&arg, &kf_dist_arg, argi)) { + enc_cfg->kf_min_dist = arg_parse_uint(&arg); + enc_cfg->kf_max_dist = enc_cfg->kf_min_dist; + } else if (arg_match(&arg, &scale_factors_arg, argi)) { + snprintf(string_options, sizeof(string_options), "%s scale-factors=%s", + string_options, arg.val); + } else if (arg_match(&arg, &passes_arg, argi)) { + passes = arg_parse_uint(&arg); + if (passes < 1 || passes > 2) { + die("Error: Invalid number of passes (%d)\n", passes); + } + } else if (arg_match(&arg, &pass_arg, argi)) { + pass = arg_parse_uint(&arg); + if (pass < 1 || pass > 2) { + die("Error: Invalid pass selected (%d)\n", pass); + } + } else if (arg_match(&arg, &fpf_name_arg, argi)) { + fpf_file_name = arg.val; + } else if (arg_match(&arg, &min_q_arg, argi)) { + snprintf(string_options, sizeof(string_options), "%s min-quantizers=%s", + string_options, arg.val); + } else if (arg_match(&arg, &max_q_arg, argi)) { + snprintf(string_options, sizeof(string_options), "%s max-quantizers=%s", + string_options, arg.val); + } else if (arg_match(&arg, &min_bitrate_arg, argi)) { + min_bitrate = arg_parse_uint(&arg); + } else if (arg_match(&arg, &max_bitrate_arg, argi)) { + max_bitrate = arg_parse_uint(&arg); + } else if (arg_match(&arg, &lag_in_frame_arg, argi)) { + enc_cfg->g_lag_in_frames = arg_parse_uint(&arg); + } else if (arg_match(&arg, &rc_end_usage_arg, argi)) { + enc_cfg->rc_end_usage = arg_parse_uint(&arg); +#if CONFIG_VP9_HIGHBITDEPTH + } else if (arg_match(&arg, &bitdepth_arg, argi)) { + enc_cfg->g_bit_depth = arg_parse_enum_or_int(&arg); + switch (enc_cfg->g_bit_depth) { + case VPX_BITS_8: + enc_cfg->g_input_bit_depth = 8; + enc_cfg->g_profile = 0; + break; + case VPX_BITS_10: + enc_cfg->g_input_bit_depth = 10; + enc_cfg->g_profile = 2; + break; + case VPX_BITS_12: + enc_cfg->g_input_bit_depth = 12; + enc_cfg->g_profile = 2; + break; + default: + die("Error: Invalid bit depth selected (%d)\n", enc_cfg->g_bit_depth); + break; + } +#endif // CONFIG_VP9_HIGHBITDEPTH + } else { + ++argj; + } + } + + // There will be a space in front of the string options + if (strlen(string_options) > 0) + vpx_svc_set_options(svc_ctx, string_options + 1); + + if (passes == 0 || passes == 1) { + if (pass) { + fprintf(stderr, "pass is ignored since there's only one pass\n"); + } + enc_cfg->g_pass = VPX_RC_ONE_PASS; + } else { + if (pass == 0) { + die("pass must be specified when passes is 2\n"); + } + + if (fpf_file_name == NULL) { + die("fpf must be specified when passes is 2\n"); + } + + if (pass == 1) { + enc_cfg->g_pass = VPX_RC_FIRST_PASS; + if (!stats_open_file(&app_input->rc_stats, fpf_file_name, 0)) { + fatal("Failed to open statistics store"); + } + } else { + enc_cfg->g_pass = VPX_RC_LAST_PASS; + if (!stats_open_file(&app_input->rc_stats, fpf_file_name, 1)) { + fatal("Failed to open statistics store"); + } + enc_cfg->rc_twopass_stats_in = stats_get(&app_input->rc_stats); + } + app_input->passes = passes; + app_input->pass = pass; + } + + if (enc_cfg->rc_target_bitrate > 0) { + if (min_bitrate > 0) { + enc_cfg->rc_2pass_vbr_minsection_pct = + min_bitrate * 100 / enc_cfg->rc_target_bitrate; + } + if (max_bitrate > 0) { + enc_cfg->rc_2pass_vbr_maxsection_pct = + max_bitrate * 100 / enc_cfg->rc_target_bitrate; + } + } + + // Check for unrecognized options + for (argi = argv; *argi; ++argi) + if (argi[0][0] == '-' && strlen(argi[0]) > 1) + die("Error: Unrecognized option %s\n", *argi); + + if (argv[0] == NULL || argv[1] == 0) { + usage_exit(); + } + app_input->input_filename = argv[0]; + app_input->output_filename = argv[1]; + free(argv); + + if (enc_cfg->g_w < 16 || enc_cfg->g_w % 2 || enc_cfg->g_h < 16 || + enc_cfg->g_h % 2) + die("Invalid resolution: %d x %d\n", enc_cfg->g_w, enc_cfg->g_h); + + printf( + "Codec %s\nframes: %d, skip: %d\n" + "layers: %d\n" + "width %d, height: %d,\n" + "num: %d, den: %d, bitrate: %d,\n" + "gop size: %d\n", + vpx_codec_iface_name(vpx_codec_vp9_cx()), app_input->frames_to_code, + app_input->frames_to_skip, + svc_ctx->spatial_layers, enc_cfg->g_w, enc_cfg->g_h, + enc_cfg->g_timebase.num, enc_cfg->g_timebase.den, + enc_cfg->rc_target_bitrate, enc_cfg->kf_max_dist); +} + +#if OUTPUT_RC_STATS +// For rate control encoding stats. +struct RateControlStats { + // Number of input frames per layer. + int layer_input_frames[VPX_MAX_LAYERS]; + // Total (cumulative) number of encoded frames per layer. + int layer_tot_enc_frames[VPX_MAX_LAYERS]; + // Number of encoded non-key frames per layer. + int layer_enc_frames[VPX_MAX_LAYERS]; + // Framerate per layer (cumulative). + double layer_framerate[VPX_MAX_LAYERS]; + // Target average frame size per layer (per-frame-bandwidth per layer). + double layer_pfb[VPX_MAX_LAYERS]; + // Actual average frame size per layer. + double layer_avg_frame_size[VPX_MAX_LAYERS]; + // Average rate mismatch per layer (|target - actual| / target). + double layer_avg_rate_mismatch[VPX_MAX_LAYERS]; + // Actual encoding bitrate per layer (cumulative). + double layer_encoding_bitrate[VPX_MAX_LAYERS]; + // Average of the short-time encoder actual bitrate. + // TODO(marpan): Should we add these short-time stats for each layer? + double avg_st_encoding_bitrate; + // Variance of the short-time encoder actual bitrate. + double variance_st_encoding_bitrate; + // Window (number of frames) for computing short-time encoding bitrate. + int window_size; + // Number of window measurements. + int window_count; +}; + +// Note: these rate control stats assume only 1 key frame in the +// sequence (i.e., first frame only). +static void set_rate_control_stats(struct RateControlStats *rc, + vpx_codec_enc_cfg_t *cfg) { + unsigned int sl, tl; + // Set the layer (cumulative) framerate and the target layer (non-cumulative) + // per-frame-bandwidth, for the rate control encoding stats below. + const double framerate = cfg->g_timebase.den / cfg->g_timebase.num; + + for (sl = 0; sl < cfg->ss_number_layers; ++sl) { + for (tl = 0; tl < cfg->ts_number_layers; ++tl) { + const int layer = sl * cfg->ts_number_layers + tl; + const int tlayer0 = sl * cfg->ts_number_layers; + if (cfg->ts_number_layers == 1) + rc->layer_framerate[layer] = framerate; + else + rc->layer_framerate[layer] = + framerate / cfg->ts_rate_decimator[tl]; + if (tl > 0) { + rc->layer_pfb[layer] = 1000.0 * + (cfg->layer_target_bitrate[layer] - + cfg->layer_target_bitrate[layer - 1]) / + (rc->layer_framerate[layer] - + rc->layer_framerate[layer - 1]); + } else { + rc->layer_pfb[tlayer0] = 1000.0 * + cfg->layer_target_bitrate[tlayer0] / + rc->layer_framerate[tlayer0]; + } + rc->layer_input_frames[layer] = 0; + rc->layer_enc_frames[layer] = 0; + rc->layer_tot_enc_frames[layer] = 0; + rc->layer_encoding_bitrate[layer] = 0.0; + rc->layer_avg_frame_size[layer] = 0.0; + rc->layer_avg_rate_mismatch[layer] = 0.0; + } + } + rc->window_count = 0; + rc->window_size = 15; + rc->avg_st_encoding_bitrate = 0.0; + rc->variance_st_encoding_bitrate = 0.0; +} + +static void printout_rate_control_summary(struct RateControlStats *rc, + vpx_codec_enc_cfg_t *cfg, + int frame_cnt) { + unsigned int sl, tl; + int tot_num_frames = 0; + double perc_fluctuation = 0.0; + printf("Total number of processed frames: %d\n\n", frame_cnt - 1); + printf("Rate control layer stats for sl%d tl%d layer(s):\n\n", + cfg->ss_number_layers, cfg->ts_number_layers); + for (sl = 0; sl < cfg->ss_number_layers; ++sl) { + for (tl = 0; tl < cfg->ts_number_layers; ++tl) { + const int layer = sl * cfg->ts_number_layers + tl; + const int num_dropped = (tl > 0) ? + (rc->layer_input_frames[layer] - rc->layer_enc_frames[layer]) : + (rc->layer_input_frames[layer] - rc->layer_enc_frames[layer] - 1); + if (!sl) + tot_num_frames += rc->layer_input_frames[layer]; + rc->layer_encoding_bitrate[layer] = 0.001 * rc->layer_framerate[layer] * + rc->layer_encoding_bitrate[layer] / tot_num_frames; + rc->layer_avg_frame_size[layer] = rc->layer_avg_frame_size[layer] / + rc->layer_enc_frames[layer]; + rc->layer_avg_rate_mismatch[layer] = + 100.0 * rc->layer_avg_rate_mismatch[layer] / + rc->layer_enc_frames[layer]; + printf("For layer#: sl%d tl%d \n", sl, tl); + printf("Bitrate (target vs actual): %d %f.0 kbps\n", + cfg->layer_target_bitrate[layer], + rc->layer_encoding_bitrate[layer]); + printf("Average frame size (target vs actual): %f %f bits\n", + rc->layer_pfb[layer], rc->layer_avg_frame_size[layer]); + printf("Average rate_mismatch: %f\n", + rc->layer_avg_rate_mismatch[layer]); + printf("Number of input frames, encoded (non-key) frames, " + "and percent dropped frames: %d %d %f.0 \n", + rc->layer_input_frames[layer], rc->layer_enc_frames[layer], + 100.0 * num_dropped / rc->layer_input_frames[layer]); + printf("\n"); + } + } + rc->avg_st_encoding_bitrate = rc->avg_st_encoding_bitrate / rc->window_count; + rc->variance_st_encoding_bitrate = + rc->variance_st_encoding_bitrate / rc->window_count - + (rc->avg_st_encoding_bitrate * rc->avg_st_encoding_bitrate); + perc_fluctuation = 100.0 * sqrt(rc->variance_st_encoding_bitrate) / + rc->avg_st_encoding_bitrate; + printf("Short-time stats, for window of %d frames: \n", rc->window_size); + printf("Average, rms-variance, and percent-fluct: %f %f %f \n", + rc->avg_st_encoding_bitrate, + sqrt(rc->variance_st_encoding_bitrate), + perc_fluctuation); + if (frame_cnt != tot_num_frames) + die("Error: Number of input frames not equal to output encoded frames != " + "%d tot_num_frames = %d\n", frame_cnt, tot_num_frames); +} + +vpx_codec_err_t parse_superframe_index(const uint8_t *data, + size_t data_sz, + uint32_t sizes[8], int *count) { + // A chunk ending with a byte matching 0xc0 is an invalid chunk unless + // it is a super frame index. If the last byte of real video compression + // data is 0xc0 the encoder must add a 0 byte. If we have the marker but + // not the associated matching marker byte at the front of the index we have + // an invalid bitstream and need to return an error. + + uint8_t marker; + + marker = *(data + data_sz - 1); + *count = 0; + + + if ((marker & 0xe0) == 0xc0) { + const uint32_t frames = (marker & 0x7) + 1; + const uint32_t mag = ((marker >> 3) & 0x3) + 1; + const size_t index_sz = 2 + mag * frames; + + // This chunk is marked as having a superframe index but doesn't have + // enough data for it, thus it's an invalid superframe index. + if (data_sz < index_sz) + return VPX_CODEC_CORRUPT_FRAME; + + { + const uint8_t marker2 = *(data + data_sz - index_sz); + + // This chunk is marked as having a superframe index but doesn't have + // the matching marker byte at the front of the index therefore it's an + // invalid chunk. + if (marker != marker2) + return VPX_CODEC_CORRUPT_FRAME; + } + + { + // Found a valid superframe index. + uint32_t i, j; + const uint8_t *x = &data[data_sz - index_sz + 1]; + + for (i = 0; i < frames; ++i) { + uint32_t this_sz = 0; + + for (j = 0; j < mag; ++j) + this_sz |= (*x++) << (j * 8); + sizes[i] = this_sz; + } + *count = frames; + } + } + return VPX_CODEC_OK; +} +#endif + +// Example pattern for spatial layers and 2 temporal layers used in the +// bypass/flexible mode. The pattern corresponds to the pattern +// VP9E_TEMPORAL_LAYERING_MODE_0101 (temporal_layering_mode == 2) used in +// non-flexible mode. +void set_frame_flags_bypass_mode(int sl, int tl, int num_spatial_layers, + int is_key_frame, + vpx_svc_ref_frame_config_t *ref_frame_config) { + for (sl = 0; sl < num_spatial_layers; ++sl) { + if (!tl) { + if (!sl) { + ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_GF | + VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF; + } else { + if (is_key_frame) { + ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_LAST | + VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF; + } else { + ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF; + } + } + } else if (tl == 1) { + if (!sl) { + ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_GF | + VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_UPD_GF; + } else { + ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_UPD_GF; + } + } + if (tl == 0) { + ref_frame_config->lst_fb_idx[sl] = sl; + if (sl) + ref_frame_config->gld_fb_idx[sl] = sl - 1; + else + ref_frame_config->gld_fb_idx[sl] = 0; + ref_frame_config->alt_fb_idx[sl] = 0; + } else if (tl == 1) { + ref_frame_config->lst_fb_idx[sl] = sl; + ref_frame_config->gld_fb_idx[sl] = num_spatial_layers + sl - 1; + ref_frame_config->alt_fb_idx[sl] = num_spatial_layers + sl; + } + } +} + +int main(int argc, const char **argv) { + AppInput app_input = {0}; + VpxVideoWriter *writer = NULL; + VpxVideoInfo info = {0}; + vpx_codec_ctx_t codec; + vpx_codec_enc_cfg_t enc_cfg; + SvcContext svc_ctx; + uint32_t i; + uint32_t frame_cnt = 0; + vpx_image_t raw; + vpx_codec_err_t res; + int pts = 0; /* PTS starts at 0 */ + int frame_duration = 1; /* 1 timebase tick per frame */ + FILE *infile = NULL; + int end_of_stream = 0; + int frames_received = 0; +#if OUTPUT_RC_STATS + VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS] = {NULL}; + struct RateControlStats rc; + vpx_svc_layer_id_t layer_id; + vpx_svc_ref_frame_config_t ref_frame_config; + int sl, tl; + double sum_bitrate = 0.0; + double sum_bitrate2 = 0.0; + double framerate = 30.0; +#endif + struct vpx_usec_timer timer; + int64_t cx_time = 0; + memset(&svc_ctx, 0, sizeof(svc_ctx)); + svc_ctx.log_print = 1; + exec_name = argv[0]; + parse_command_line(argc, argv, &app_input, &svc_ctx, &enc_cfg); + + // Allocate image buffer +#if CONFIG_VP9_HIGHBITDEPTH + if (!vpx_img_alloc(&raw, enc_cfg.g_input_bit_depth == 8 ? + VPX_IMG_FMT_I420 : VPX_IMG_FMT_I42016, + enc_cfg.g_w, enc_cfg.g_h, 32)) { + die("Failed to allocate image %dx%d\n", enc_cfg.g_w, enc_cfg.g_h); + } +#else + if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, enc_cfg.g_w, enc_cfg.g_h, 32)) { + die("Failed to allocate image %dx%d\n", enc_cfg.g_w, enc_cfg.g_h); + } +#endif // CONFIG_VP9_HIGHBITDEPTH + + if (!(infile = fopen(app_input.input_filename, "rb"))) + die("Failed to open %s for reading\n", app_input.input_filename); + + // Initialize codec + if (vpx_svc_init(&svc_ctx, &codec, vpx_codec_vp9_cx(), &enc_cfg) != + VPX_CODEC_OK) + die("Failed to initialize encoder\n"); + +#if OUTPUT_RC_STATS + if (svc_ctx.output_rc_stat) { + set_rate_control_stats(&rc, &enc_cfg); + framerate = enc_cfg.g_timebase.den / enc_cfg.g_timebase.num; + } +#endif + + info.codec_fourcc = VP9_FOURCC; + info.time_base.numerator = enc_cfg.g_timebase.num; + info.time_base.denominator = enc_cfg.g_timebase.den; + + if (!(app_input.passes == 2 && app_input.pass == 1)) { + // We don't save the bitstream for the 1st pass on two pass rate control + writer = vpx_video_writer_open(app_input.output_filename, kContainerIVF, + &info); + if (!writer) + die("Failed to open %s for writing\n", app_input.output_filename); + } +#if OUTPUT_RC_STATS + // For now, just write temporal layer streams. + // TODO(wonkap): do spatial by re-writing superframe. + if (svc_ctx.output_rc_stat) { + for (tl = 0; tl < enc_cfg.ts_number_layers; ++tl) { + char file_name[PATH_MAX]; + + snprintf(file_name, sizeof(file_name), "%s_t%d.ivf", + app_input.output_filename, tl); + outfile[tl] = vpx_video_writer_open(file_name, kContainerIVF, &info); + if (!outfile[tl]) + die("Failed to open %s for writing", file_name); + } + } +#endif + + // skip initial frames + for (i = 0; i < app_input.frames_to_skip; ++i) + vpx_img_read(&raw, infile); + + if (svc_ctx.speed != -1) + vpx_codec_control(&codec, VP8E_SET_CPUUSED, svc_ctx.speed); + if (svc_ctx.threads) + vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, (svc_ctx.threads >> 1)); + if (svc_ctx.speed >= 5 && svc_ctx.aqmode == 1) + vpx_codec_control(&codec, VP9E_SET_AQ_MODE, 3); + + + // Encode frames + while (!end_of_stream) { + vpx_codec_iter_t iter = NULL; + const vpx_codec_cx_pkt_t *cx_pkt; + if (frame_cnt >= app_input.frames_to_code || !vpx_img_read(&raw, infile)) { + // We need one extra vpx_svc_encode call at end of stream to flush + // encoder and get remaining data + end_of_stream = 1; + } + + // For BYPASS/FLEXIBLE mode, set the frame flags (reference and updates) + // and the buffer indices for each spatial layer of the current + // (super)frame to be encoded. The temporal layer_id for the current frame + // also needs to be set. + // TODO(marpan): Should rename the "VP9E_TEMPORAL_LAYERING_MODE_BYPASS" + // mode to "VP9E_LAYERING_MODE_BYPASS". + if (svc_ctx.temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) { + layer_id.spatial_layer_id = 0; + // Example for 2 temporal layers. + if (frame_cnt % 2 == 0) + layer_id.temporal_layer_id = 0; + else + layer_id.temporal_layer_id = 1; + // Note that we only set the temporal layer_id, since we are calling + // the encode for the whole superframe. The encoder will internally loop + // over all the spatial layers for the current superframe. + vpx_codec_control(&codec, VP9E_SET_SVC_LAYER_ID, &layer_id); + set_frame_flags_bypass_mode(sl, layer_id.temporal_layer_id, + svc_ctx.spatial_layers, + frame_cnt == 0, + &ref_frame_config); + vpx_codec_control(&codec, VP9E_SET_SVC_REF_FRAME_CONFIG, + &ref_frame_config); + // Keep track of input frames, to account for frame drops in rate control + // stats/metrics. + for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) { + ++rc.layer_input_frames[sl * enc_cfg.ts_number_layers + + layer_id.temporal_layer_id]; + } + } + + vpx_usec_timer_start(&timer); + res = vpx_svc_encode(&svc_ctx, &codec, (end_of_stream ? NULL : &raw), + pts, frame_duration, svc_ctx.speed >= 5 ? + VPX_DL_REALTIME : VPX_DL_GOOD_QUALITY); + vpx_usec_timer_mark(&timer); + cx_time += vpx_usec_timer_elapsed(&timer); + + printf("%s", vpx_svc_get_message(&svc_ctx)); + fflush(stdout); + if (res != VPX_CODEC_OK) { + die_codec(&codec, "Failed to encode frame"); + } + + while ((cx_pkt = vpx_codec_get_cx_data(&codec, &iter)) != NULL) { + switch (cx_pkt->kind) { + case VPX_CODEC_CX_FRAME_PKT: { + SvcInternal_t *const si = (SvcInternal_t *)svc_ctx.internal; + if (cx_pkt->data.frame.sz > 0) { +#if OUTPUT_RC_STATS + uint32_t sizes[8]; + int count = 0; +#endif + vpx_video_writer_write_frame(writer, + cx_pkt->data.frame.buf, + cx_pkt->data.frame.sz, + cx_pkt->data.frame.pts); +#if OUTPUT_RC_STATS + // TODO(marpan/wonkap): Put this (to line728) in separate function. + if (svc_ctx.output_rc_stat) { + vpx_codec_control(&codec, VP9E_GET_SVC_LAYER_ID, &layer_id); + parse_superframe_index(cx_pkt->data.frame.buf, + cx_pkt->data.frame.sz, sizes, &count); + // Note computing input_layer_frames here won't account for frame + // drops in rate control stats. + // TODO(marpan): Fix this for non-bypass mode so we can get stats + // for dropped frames. + if (svc_ctx.temporal_layering_mode != + VP9E_TEMPORAL_LAYERING_MODE_BYPASS) { + for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) { + ++rc.layer_input_frames[sl * enc_cfg.ts_number_layers + + layer_id.temporal_layer_id]; + } + } + for (tl = layer_id.temporal_layer_id; + tl < enc_cfg.ts_number_layers; ++tl) { + vpx_video_writer_write_frame(outfile[tl], + cx_pkt->data.frame.buf, + cx_pkt->data.frame.sz, + cx_pkt->data.frame.pts); + } + + for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) { + for (tl = layer_id.temporal_layer_id; + tl < enc_cfg.ts_number_layers; ++tl) { + const int layer = sl * enc_cfg.ts_number_layers + tl; + ++rc.layer_tot_enc_frames[layer]; + rc.layer_encoding_bitrate[layer] += 8.0 * sizes[sl]; + // Keep count of rate control stats per layer, for non-key + // frames. + if (tl == layer_id.temporal_layer_id && + !(cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY)) { + rc.layer_avg_frame_size[layer] += 8.0 * sizes[sl]; + rc.layer_avg_rate_mismatch[layer] += + fabs(8.0 * sizes[sl] - rc.layer_pfb[layer]) / + rc.layer_pfb[layer]; + ++rc.layer_enc_frames[layer]; + } + } + } + + // Update for short-time encoding bitrate states, for moving + // window of size rc->window, shifted by rc->window / 2. + // Ignore first window segment, due to key frame. + if (frame_cnt > rc.window_size) { + tl = layer_id.temporal_layer_id; + for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) { + sum_bitrate += 0.001 * 8.0 * sizes[sl] * framerate; + } + if (frame_cnt % rc.window_size == 0) { + rc.window_count += 1; + rc.avg_st_encoding_bitrate += sum_bitrate / rc.window_size; + rc.variance_st_encoding_bitrate += + (sum_bitrate / rc.window_size) * + (sum_bitrate / rc.window_size); + sum_bitrate = 0.0; + } + } + + // Second shifted window. + if (frame_cnt > rc.window_size + rc.window_size / 2) { + tl = layer_id.temporal_layer_id; + for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) { + sum_bitrate2 += 0.001 * 8.0 * sizes[sl] * framerate; + } + + if (frame_cnt > 2 * rc.window_size && + frame_cnt % rc.window_size == 0) { + rc.window_count += 1; + rc.avg_st_encoding_bitrate += sum_bitrate2 / rc.window_size; + rc.variance_st_encoding_bitrate += + (sum_bitrate2 / rc.window_size) * + (sum_bitrate2 / rc.window_size); + sum_bitrate2 = 0.0; + } + } + } +#endif + } + + printf("SVC frame: %d, kf: %d, size: %d, pts: %d\n", frames_received, + !!(cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY), + (int)cx_pkt->data.frame.sz, (int)cx_pkt->data.frame.pts); + if (enc_cfg.ss_number_layers == 1 && enc_cfg.ts_number_layers == 1) + si->bytes_sum[0] += (int)cx_pkt->data.frame.sz; + ++frames_received; + break; + } + case VPX_CODEC_STATS_PKT: { + stats_write(&app_input.rc_stats, + cx_pkt->data.twopass_stats.buf, + cx_pkt->data.twopass_stats.sz); + break; + } + default: { + break; + } + } + } + + if (!end_of_stream) { + ++frame_cnt; + pts += frame_duration; + } + } + + // Compensate for the extra frame count for the bypass mode. + if (svc_ctx.temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) { + for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) { + const int layer = sl * enc_cfg.ts_number_layers + + layer_id.temporal_layer_id; + --rc.layer_input_frames[layer]; + } + } + + printf("Processed %d frames\n", frame_cnt); + fclose(infile); +#if OUTPUT_RC_STATS + if (svc_ctx.output_rc_stat) { + printout_rate_control_summary(&rc, &enc_cfg, frame_cnt); + printf("\n"); + } +#endif + if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec"); + if (app_input.passes == 2) + stats_close(&app_input.rc_stats, 1); + if (writer) { + vpx_video_writer_close(writer); + } +#if OUTPUT_RC_STATS + if (svc_ctx.output_rc_stat) { + for (tl = 0; tl < enc_cfg.ts_number_layers; ++tl) { + vpx_video_writer_close(outfile[tl]); + } + } +#endif + printf("Frame cnt and encoding time/FPS stats for encoding: %d %f %f \n", + frame_cnt, + 1000 * (float)cx_time / (double)(frame_cnt * 1000000), + 1000000 * (double)frame_cnt / (double)cx_time); + vpx_img_free(&raw); + // display average size, psnr + printf("%s", vpx_svc_dump_statistics(&svc_ctx)); + vpx_svc_release(&svc_ctx); + return EXIT_SUCCESS; +}
diff --git a/src/third_party/libvpx/examples/vpx_temporal_svc_encoder.c b/src/third_party/libvpx/examples/vpx_temporal_svc_encoder.c new file mode 100644 index 0000000..e6c09fb --- /dev/null +++ b/src/third_party/libvpx/examples/vpx_temporal_svc_encoder.c
@@ -0,0 +1,852 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// This is an example demonstrating how to implement a multi-layer VPx +// encoding scheme based on temporal scalability for video applications +// that benefit from a scalable bitstream. + +#include <assert.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "./vpx_config.h" +#include "../vpx_ports/vpx_timer.h" +#include "vpx/vp8cx.h" +#include "vpx/vpx_encoder.h" + +#include "../tools_common.h" +#include "../video_writer.h" + +static const char *exec_name; + +void usage_exit(void) { + exit(EXIT_FAILURE); +} + +// Denoiser states, for temporal denoising. +enum denoiserState { + kDenoiserOff, + kDenoiserOnYOnly, + kDenoiserOnYUV, + kDenoiserOnYUVAggressive, + kDenoiserOnAdaptive +}; + +static int mode_to_num_layers[13] = {1, 2, 2, 3, 3, 3, 3, 5, 2, 3, 3, 3, 3}; + +// For rate control encoding stats. +struct RateControlMetrics { + // Number of input frames per layer. + int layer_input_frames[VPX_TS_MAX_LAYERS]; + // Total (cumulative) number of encoded frames per layer. + int layer_tot_enc_frames[VPX_TS_MAX_LAYERS]; + // Number of encoded non-key frames per layer. + int layer_enc_frames[VPX_TS_MAX_LAYERS]; + // Framerate per layer layer (cumulative). + double layer_framerate[VPX_TS_MAX_LAYERS]; + // Target average frame size per layer (per-frame-bandwidth per layer). + double layer_pfb[VPX_TS_MAX_LAYERS]; + // Actual average frame size per layer. + double layer_avg_frame_size[VPX_TS_MAX_LAYERS]; + // Average rate mismatch per layer (|target - actual| / target). + double layer_avg_rate_mismatch[VPX_TS_MAX_LAYERS]; + // Actual encoding bitrate per layer (cumulative). + double layer_encoding_bitrate[VPX_TS_MAX_LAYERS]; + // Average of the short-time encoder actual bitrate. + // TODO(marpan): Should we add these short-time stats for each layer? + double avg_st_encoding_bitrate; + // Variance of the short-time encoder actual bitrate. + double variance_st_encoding_bitrate; + // Window (number of frames) for computing short-timee encoding bitrate. + int window_size; + // Number of window measurements. + int window_count; + int layer_target_bitrate[VPX_MAX_LAYERS]; +}; + +// Note: these rate control metrics assume only 1 key frame in the +// sequence (i.e., first frame only). So for temporal pattern# 7 +// (which has key frame for every frame on base layer), the metrics +// computation will be off/wrong. +// TODO(marpan): Update these metrics to account for multiple key frames +// in the stream. +static void set_rate_control_metrics(struct RateControlMetrics *rc, + vpx_codec_enc_cfg_t *cfg) { + unsigned int i = 0; + // Set the layer (cumulative) framerate and the target layer (non-cumulative) + // per-frame-bandwidth, for the rate control encoding stats below. + const double framerate = cfg->g_timebase.den / cfg->g_timebase.num; + rc->layer_framerate[0] = framerate / cfg->ts_rate_decimator[0]; + rc->layer_pfb[0] = 1000.0 * rc->layer_target_bitrate[0] / + rc->layer_framerate[0]; + for (i = 0; i < cfg->ts_number_layers; ++i) { + if (i > 0) { + rc->layer_framerate[i] = framerate / cfg->ts_rate_decimator[i]; + rc->layer_pfb[i] = 1000.0 * + (rc->layer_target_bitrate[i] - rc->layer_target_bitrate[i - 1]) / + (rc->layer_framerate[i] - rc->layer_framerate[i - 1]); + } + rc->layer_input_frames[i] = 0; + rc->layer_enc_frames[i] = 0; + rc->layer_tot_enc_frames[i] = 0; + rc->layer_encoding_bitrate[i] = 0.0; + rc->layer_avg_frame_size[i] = 0.0; + rc->layer_avg_rate_mismatch[i] = 0.0; + } + rc->window_count = 0; + rc->window_size = 15; + rc->avg_st_encoding_bitrate = 0.0; + rc->variance_st_encoding_bitrate = 0.0; +} + +static void printout_rate_control_summary(struct RateControlMetrics *rc, + vpx_codec_enc_cfg_t *cfg, + int frame_cnt) { + unsigned int i = 0; + int tot_num_frames = 0; + double perc_fluctuation = 0.0; + printf("Total number of processed frames: %d\n\n", frame_cnt -1); + printf("Rate control layer stats for %d layer(s):\n\n", + cfg->ts_number_layers); + for (i = 0; i < cfg->ts_number_layers; ++i) { + const int num_dropped = (i > 0) ? + (rc->layer_input_frames[i] - rc->layer_enc_frames[i]) : + (rc->layer_input_frames[i] - rc->layer_enc_frames[i] - 1); + tot_num_frames += rc->layer_input_frames[i]; + rc->layer_encoding_bitrate[i] = 0.001 * rc->layer_framerate[i] * + rc->layer_encoding_bitrate[i] / tot_num_frames; + rc->layer_avg_frame_size[i] = rc->layer_avg_frame_size[i] / + rc->layer_enc_frames[i]; + rc->layer_avg_rate_mismatch[i] = 100.0 * rc->layer_avg_rate_mismatch[i] / + rc->layer_enc_frames[i]; + printf("For layer#: %d \n", i); + printf("Bitrate (target vs actual): %d %f \n", rc->layer_target_bitrate[i], + rc->layer_encoding_bitrate[i]); + printf("Average frame size (target vs actual): %f %f \n", rc->layer_pfb[i], + rc->layer_avg_frame_size[i]); + printf("Average rate_mismatch: %f \n", rc->layer_avg_rate_mismatch[i]); + printf("Number of input frames, encoded (non-key) frames, " + "and perc dropped frames: %d %d %f \n", rc->layer_input_frames[i], + rc->layer_enc_frames[i], + 100.0 * num_dropped / rc->layer_input_frames[i]); + printf("\n"); + } + rc->avg_st_encoding_bitrate = rc->avg_st_encoding_bitrate / rc->window_count; + rc->variance_st_encoding_bitrate = + rc->variance_st_encoding_bitrate / rc->window_count - + (rc->avg_st_encoding_bitrate * rc->avg_st_encoding_bitrate); + perc_fluctuation = 100.0 * sqrt(rc->variance_st_encoding_bitrate) / + rc->avg_st_encoding_bitrate; + printf("Short-time stats, for window of %d frames: \n",rc->window_size); + printf("Average, rms-variance, and percent-fluct: %f %f %f \n", + rc->avg_st_encoding_bitrate, + sqrt(rc->variance_st_encoding_bitrate), + perc_fluctuation); + if ((frame_cnt - 1) != tot_num_frames) + die("Error: Number of input frames not equal to output! \n"); +} + +// Temporal scaling parameters: +// NOTE: The 3 prediction frames cannot be used interchangeably due to +// differences in the way they are handled throughout the code. The +// frames should be allocated to layers in the order LAST, GF, ARF. +// Other combinations work, but may produce slightly inferior results. +static void set_temporal_layer_pattern(int layering_mode, + vpx_codec_enc_cfg_t *cfg, + int *layer_flags, + int *flag_periodicity) { + switch (layering_mode) { + case 0: { + // 1-layer. + int ids[1] = {0}; + cfg->ts_periodicity = 1; + *flag_periodicity = 1; + cfg->ts_number_layers = 1; + cfg->ts_rate_decimator[0] = 1; + memcpy(cfg->ts_layer_id, ids, sizeof(ids)); + // Update L only. + layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF; + break; + } + case 1: { + // 2-layers, 2-frame period. + int ids[2] = {0, 1}; + cfg->ts_periodicity = 2; + *flag_periodicity = 2; + cfg->ts_number_layers = 2; + cfg->ts_rate_decimator[0] = 2; + cfg->ts_rate_decimator[1] = 1; + memcpy(cfg->ts_layer_id, ids, sizeof(ids)); +#if 1 + // 0=L, 1=GF, Intra-layer prediction enabled. + layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF; + layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_REF_ARF; +#else + // 0=L, 1=GF, Intra-layer prediction disabled. + layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF; + layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_LAST; +#endif + break; + } + case 2: { + // 2-layers, 3-frame period. + int ids[3] = {0, 1, 1}; + cfg->ts_periodicity = 3; + *flag_periodicity = 3; + cfg->ts_number_layers = 2; + cfg->ts_rate_decimator[0] = 3; + cfg->ts_rate_decimator[1] = 1; + memcpy(cfg->ts_layer_id, ids, sizeof(ids)); + // 0=L, 1=GF, Intra-layer prediction enabled. + layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF | + VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; + layer_flags[1] = + layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST; + break; + } + case 3: { + // 3-layers, 6-frame period. + int ids[6] = {0, 2, 2, 1, 2, 2}; + cfg->ts_periodicity = 6; + *flag_periodicity = 6; + cfg->ts_number_layers = 3; + cfg->ts_rate_decimator[0] = 6; + cfg->ts_rate_decimator[1] = 3; + cfg->ts_rate_decimator[2] = 1; + memcpy(cfg->ts_layer_id, ids, sizeof(ids)); + // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled. + layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF | + VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; + layer_flags[3] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | + VP8_EFLAG_NO_UPD_LAST; + layer_flags[1] = + layer_flags[2] = + layer_flags[4] = + layer_flags[5] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST; + break; + } + case 4: { + // 3-layers, 4-frame period. + int ids[4] = {0, 2, 1, 2}; + cfg->ts_periodicity = 4; + *flag_periodicity = 4; + cfg->ts_number_layers = 3; + cfg->ts_rate_decimator[0] = 4; + cfg->ts_rate_decimator[1] = 2; + cfg->ts_rate_decimator[2] = 1; + memcpy(cfg->ts_layer_id, ids, sizeof(ids)); + // 0=L, 1=GF, 2=ARF, Intra-layer prediction disabled. + layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF | + VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; + layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST; + layer_flags[1] = + layer_flags[3] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; + break; + } + case 5: { + // 3-layers, 4-frame period. + int ids[4] = {0, 2, 1, 2}; + cfg->ts_periodicity = 4; + *flag_periodicity = 4; + cfg->ts_number_layers = 3; + cfg->ts_rate_decimator[0] = 4; + cfg->ts_rate_decimator[1] = 2; + cfg->ts_rate_decimator[2] = 1; + memcpy(cfg->ts_layer_id, ids, sizeof(ids)); + // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled in layer 1, disabled + // in layer 2. + layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF | + VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; + layer_flags[2] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_UPD_ARF; + layer_flags[1] = + layer_flags[3] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; + break; + } + case 6: { + // 3-layers, 4-frame period. + int ids[4] = {0, 2, 1, 2}; + cfg->ts_periodicity = 4; + *flag_periodicity = 4; + cfg->ts_number_layers = 3; + cfg->ts_rate_decimator[0] = 4; + cfg->ts_rate_decimator[1] = 2; + cfg->ts_rate_decimator[2] = 1; + memcpy(cfg->ts_layer_id, ids, sizeof(ids)); + // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled. + layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF | + VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; + layer_flags[2] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_UPD_ARF; + layer_flags[1] = + layer_flags[3] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF; + break; + } + case 7: { + // NOTE: Probably of academic interest only. + // 5-layers, 16-frame period. + int ids[16] = {0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4}; + cfg->ts_periodicity = 16; + *flag_periodicity = 16; + cfg->ts_number_layers = 5; + cfg->ts_rate_decimator[0] = 16; + cfg->ts_rate_decimator[1] = 8; + cfg->ts_rate_decimator[2] = 4; + cfg->ts_rate_decimator[3] = 2; + cfg->ts_rate_decimator[4] = 1; + memcpy(cfg->ts_layer_id, ids, sizeof(ids)); + layer_flags[0] = VPX_EFLAG_FORCE_KF; + layer_flags[1] = + layer_flags[3] = + layer_flags[5] = + layer_flags[7] = + layer_flags[9] = + layer_flags[11] = + layer_flags[13] = + layer_flags[15] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF; + layer_flags[2] = + layer_flags[6] = + layer_flags[10] = + layer_flags[14] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_GF; + layer_flags[4] = + layer_flags[12] = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_UPD_ARF; + layer_flags[8] = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF; + break; + } + case 8: { + // 2-layers, with sync point at first frame of layer 1. + int ids[2] = {0, 1}; + cfg->ts_periodicity = 2; + *flag_periodicity = 8; + cfg->ts_number_layers = 2; + cfg->ts_rate_decimator[0] = 2; + cfg->ts_rate_decimator[1] = 1; + memcpy(cfg->ts_layer_id, ids, sizeof(ids)); + // 0=L, 1=GF. + // ARF is used as predictor for all frames, and is only updated on + // key frame. Sync point every 8 frames. + + // Layer 0: predict from L and ARF, update L and G. + layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF | + VP8_EFLAG_NO_UPD_ARF; + // Layer 1: sync point: predict from L and ARF, and update G. + layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_UPD_ARF; + // Layer 0, predict from L and ARF, update L. + layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF; + // Layer 1: predict from L, G and ARF, and update G. + layer_flags[3] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_UPD_ENTROPY; + // Layer 0. + layer_flags[4] = layer_flags[2]; + // Layer 1. + layer_flags[5] = layer_flags[3]; + // Layer 0. + layer_flags[6] = layer_flags[4]; + // Layer 1. + layer_flags[7] = layer_flags[5]; + break; + } + case 9: { + // 3-layers: Sync points for layer 1 and 2 every 8 frames. + int ids[4] = {0, 2, 1, 2}; + cfg->ts_periodicity = 4; + *flag_periodicity = 8; + cfg->ts_number_layers = 3; + cfg->ts_rate_decimator[0] = 4; + cfg->ts_rate_decimator[1] = 2; + cfg->ts_rate_decimator[2] = 1; + memcpy(cfg->ts_layer_id, ids, sizeof(ids)); + // 0=L, 1=GF, 2=ARF. + layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF | + VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; + layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF; + layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF; + layer_flags[3] = + layer_flags[5] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF; + layer_flags[4] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; + layer_flags[6] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_UPD_ARF; + layer_flags[7] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_ENTROPY; + break; + } + case 10: { + // 3-layers structure where ARF is used as predictor for all frames, + // and is only updated on key frame. + // Sync points for layer 1 and 2 every 8 frames. + + int ids[4] = {0, 2, 1, 2}; + cfg->ts_periodicity = 4; + *flag_periodicity = 8; + cfg->ts_number_layers = 3; + cfg->ts_rate_decimator[0] = 4; + cfg->ts_rate_decimator[1] = 2; + cfg->ts_rate_decimator[2] = 1; + memcpy(cfg->ts_layer_id, ids, sizeof(ids)); + // 0=L, 1=GF, 2=ARF. + // Layer 0: predict from L and ARF; update L and G. + layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_UPD_ARF | + VP8_EFLAG_NO_REF_GF; + // Layer 2: sync point: predict from L and ARF; update none. + layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_UPD_ENTROPY; + // Layer 1: sync point: predict from L and ARF; update G. + layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_ARF | + VP8_EFLAG_NO_UPD_LAST; + // Layer 2: predict from L, G, ARF; update none. + layer_flags[3] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | + VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY; + // Layer 0: predict from L and ARF; update L. + layer_flags[4] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | + VP8_EFLAG_NO_REF_GF; + // Layer 2: predict from L, G, ARF; update none. + layer_flags[5] = layer_flags[3]; + // Layer 1: predict from L, G, ARF; update G. + layer_flags[6] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST; + // Layer 2: predict from L, G, ARF; update none. + layer_flags[7] = layer_flags[3]; + break; + } + case 11: { + // 3-layers structure with one reference frame. + // This works same as temporal_layering_mode 3. + // This was added to compare with vp9_spatial_svc_encoder. + + // 3-layers, 4-frame period. + int ids[4] = {0, 2, 1, 2}; + cfg->ts_periodicity = 4; + *flag_periodicity = 4; + cfg->ts_number_layers = 3; + cfg->ts_rate_decimator[0] = 4; + cfg->ts_rate_decimator[1] = 2; + cfg->ts_rate_decimator[2] = 1; + memcpy(cfg->ts_layer_id, ids, sizeof(ids)); + // 0=L, 1=GF, 2=ARF, Intra-layer prediction disabled. + layer_flags[0] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; + layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST; + layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF; + layer_flags[3] = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF; + break; + } + case 12: + default: { + // 3-layers structure as in case 10, but no sync/refresh points for + // layer 1 and 2. + int ids[4] = {0, 2, 1, 2}; + cfg->ts_periodicity = 4; + *flag_periodicity = 8; + cfg->ts_number_layers = 3; + cfg->ts_rate_decimator[0] = 4; + cfg->ts_rate_decimator[1] = 2; + cfg->ts_rate_decimator[2] = 1; + memcpy(cfg->ts_layer_id, ids, sizeof(ids)); + // 0=L, 1=GF, 2=ARF. + // Layer 0: predict from L and ARF; update L. + layer_flags[0] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | + VP8_EFLAG_NO_REF_GF; + layer_flags[4] = layer_flags[0]; + // Layer 1: predict from L, G, ARF; update G. + layer_flags[2] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST; + layer_flags[6] = layer_flags[2]; + // Layer 2: predict from L, G, ARF; update none. + layer_flags[1] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | + VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY; + layer_flags[3] = layer_flags[1]; + layer_flags[5] = layer_flags[1]; + layer_flags[7] = layer_flags[1]; + break; + } + } +} + +int main(int argc, char **argv) { + VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS] = {NULL}; + vpx_codec_ctx_t codec; + vpx_codec_enc_cfg_t cfg; + int frame_cnt = 0; + vpx_image_t raw; + vpx_codec_err_t res; + unsigned int width; + unsigned int height; + int speed; + int frame_avail; + int got_data; + int flags = 0; + unsigned int i; + int pts = 0; // PTS starts at 0. + int frame_duration = 1; // 1 timebase tick per frame. + int layering_mode = 0; + int layer_flags[VPX_TS_MAX_PERIODICITY] = {0}; + int flag_periodicity = 1; +#if VPX_ENCODER_ABI_VERSION > (4 + VPX_CODEC_ABI_VERSION) + vpx_svc_layer_id_t layer_id = {0, 0}; +#else + vpx_svc_layer_id_t layer_id = {0}; +#endif + const VpxInterface *encoder = NULL; + FILE *infile = NULL; + struct RateControlMetrics rc; + int64_t cx_time = 0; + const int min_args_base = 11; +#if CONFIG_VP9_HIGHBITDEPTH + vpx_bit_depth_t bit_depth = VPX_BITS_8; + int input_bit_depth = 8; + const int min_args = min_args_base + 1; +#else + const int min_args = min_args_base; +#endif // CONFIG_VP9_HIGHBITDEPTH + double sum_bitrate = 0.0; + double sum_bitrate2 = 0.0; + double framerate = 30.0; + + exec_name = argv[0]; + // Check usage and arguments. + if (argc < min_args) { +#if CONFIG_VP9_HIGHBITDEPTH + die("Usage: %s <infile> <outfile> <codec_type(vp8/vp9)> <width> <height> " + "<rate_num> <rate_den> <speed> <frame_drop_threshold> <mode> " + "<Rate_0> ... <Rate_nlayers-1> <bit-depth> \n", argv[0]); +#else + die("Usage: %s <infile> <outfile> <codec_type(vp8/vp9)> <width> <height> " + "<rate_num> <rate_den> <speed> <frame_drop_threshold> <mode> " + "<Rate_0> ... <Rate_nlayers-1> \n", argv[0]); +#endif // CONFIG_VP9_HIGHBITDEPTH + } + + encoder = get_vpx_encoder_by_name(argv[3]); + if (!encoder) + die("Unsupported codec."); + + printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface())); + + width = strtol(argv[4], NULL, 0); + height = strtol(argv[5], NULL, 0); + if (width < 16 || width % 2 || height < 16 || height % 2) { + die("Invalid resolution: %d x %d", width, height); + } + + layering_mode = strtol(argv[10], NULL, 0); + if (layering_mode < 0 || layering_mode > 13) { + die("Invalid layering mode (0..12) %s", argv[10]); + } + + if (argc != min_args + mode_to_num_layers[layering_mode]) { + die("Invalid number of arguments"); + } + +#if CONFIG_VP9_HIGHBITDEPTH + switch (strtol(argv[argc-1], NULL, 0)) { + case 8: + bit_depth = VPX_BITS_8; + input_bit_depth = 8; + break; + case 10: + bit_depth = VPX_BITS_10; + input_bit_depth = 10; + break; + case 12: + bit_depth = VPX_BITS_12; + input_bit_depth = 12; + break; + default: + die("Invalid bit depth (8, 10, 12) %s", argv[argc-1]); + } + if (!vpx_img_alloc(&raw, + bit_depth == VPX_BITS_8 ? VPX_IMG_FMT_I420 : + VPX_IMG_FMT_I42016, + width, height, 32)) { + die("Failed to allocate image", width, height); + } +#else + if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 32)) { + die("Failed to allocate image", width, height); + } +#endif // CONFIG_VP9_HIGHBITDEPTH + + // Populate encoder configuration. + res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0); + if (res) { + printf("Failed to get config: %s\n", vpx_codec_err_to_string(res)); + return EXIT_FAILURE; + } + + // Update the default configuration with our settings. + cfg.g_w = width; + cfg.g_h = height; + +#if CONFIG_VP9_HIGHBITDEPTH + if (bit_depth != VPX_BITS_8) { + cfg.g_bit_depth = bit_depth; + cfg.g_input_bit_depth = input_bit_depth; + cfg.g_profile = 2; + } +#endif // CONFIG_VP9_HIGHBITDEPTH + + // Timebase format e.g. 30fps: numerator=1, demoninator = 30. + cfg.g_timebase.num = strtol(argv[6], NULL, 0); + cfg.g_timebase.den = strtol(argv[7], NULL, 0); + + speed = strtol(argv[8], NULL, 0); + if (speed < 0) { + die("Invalid speed setting: must be positive"); + } + + for (i = min_args_base; + (int)i < min_args_base + mode_to_num_layers[layering_mode]; + ++i) { + rc.layer_target_bitrate[i - 11] = strtol(argv[i], NULL, 0); + if (strncmp(encoder->name, "vp8", 3) == 0) + cfg.ts_target_bitrate[i - 11] = rc.layer_target_bitrate[i - 11]; + else if (strncmp(encoder->name, "vp9", 3) == 0) + cfg.layer_target_bitrate[i - 11] = rc.layer_target_bitrate[i - 11]; + } + + // Real time parameters. + cfg.rc_dropframe_thresh = strtol(argv[9], NULL, 0); + cfg.rc_end_usage = VPX_CBR; + cfg.rc_min_quantizer = 2; + cfg.rc_max_quantizer = 56; + if (strncmp(encoder->name, "vp9", 3) == 0) + cfg.rc_max_quantizer = 52; + cfg.rc_undershoot_pct = 50; + cfg.rc_overshoot_pct = 50; + cfg.rc_buf_initial_sz = 500; + cfg.rc_buf_optimal_sz = 600; + cfg.rc_buf_sz = 1000; + + // Disable dynamic resizing by default. + cfg.rc_resize_allowed = 0; + + // Use 1 thread as default. + cfg.g_threads = 1; + + // Enable error resilient mode. + cfg.g_error_resilient = 1; + cfg.g_lag_in_frames = 0; + cfg.kf_mode = VPX_KF_AUTO; + + // Disable automatic keyframe placement. + cfg.kf_min_dist = cfg.kf_max_dist = 3000; + + cfg.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS; + + set_temporal_layer_pattern(layering_mode, + &cfg, + layer_flags, + &flag_periodicity); + + set_rate_control_metrics(&rc, &cfg); + + // Target bandwidth for the whole stream. + // Set to layer_target_bitrate for highest layer (total bitrate). + cfg.rc_target_bitrate = rc.layer_target_bitrate[cfg.ts_number_layers - 1]; + + // Open input file. + if (!(infile = fopen(argv[1], "rb"))) { + die("Failed to open %s for reading", argv[1]); + } + + framerate = cfg.g_timebase.den / cfg.g_timebase.num; + // Open an output file for each stream. + for (i = 0; i < cfg.ts_number_layers; ++i) { + char file_name[PATH_MAX]; + VpxVideoInfo info; + info.codec_fourcc = encoder->fourcc; + info.frame_width = cfg.g_w; + info.frame_height = cfg.g_h; + info.time_base.numerator = cfg.g_timebase.num; + info.time_base.denominator = cfg.g_timebase.den; + + snprintf(file_name, sizeof(file_name), "%s_%d.ivf", argv[2], i); + outfile[i] = vpx_video_writer_open(file_name, kContainerIVF, &info); + if (!outfile[i]) + die("Failed to open %s for writing", file_name); + + assert(outfile[i] != NULL); + } + // No spatial layers in this encoder. + cfg.ss_number_layers = 1; + + // Initialize codec. +#if CONFIG_VP9_HIGHBITDEPTH + if (vpx_codec_enc_init( + &codec, encoder->codec_interface(), &cfg, + bit_depth == VPX_BITS_8 ? 0 : VPX_CODEC_USE_HIGHBITDEPTH)) +#else + if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0)) +#endif // CONFIG_VP9_HIGHBITDEPTH + die_codec(&codec, "Failed to initialize encoder"); + + if (strncmp(encoder->name, "vp8", 3) == 0) { + vpx_codec_control(&codec, VP8E_SET_CPUUSED, -speed); + vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, kDenoiserOff); + vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 1); + } else if (strncmp(encoder->name, "vp9", 3) == 0) { + vpx_svc_extra_cfg_t svc_params; + vpx_codec_control(&codec, VP8E_SET_CPUUSED, speed); + vpx_codec_control(&codec, VP9E_SET_AQ_MODE, 3); + vpx_codec_control(&codec, VP9E_SET_FRAME_PERIODIC_BOOST, 0); + vpx_codec_control(&codec, VP9E_SET_NOISE_SENSITIVITY, kDenoiserOff); + vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 1); + vpx_codec_control(&codec, VP9E_SET_TUNE_CONTENT, 0); + vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, (cfg.g_threads >> 1)); + if (vpx_codec_control(&codec, VP9E_SET_SVC, layering_mode > 0 ? 1: 0)) + die_codec(&codec, "Failed to set SVC"); + for (i = 0; i < cfg.ts_number_layers; ++i) { + svc_params.max_quantizers[i] = cfg.rc_max_quantizer; + svc_params.min_quantizers[i] = cfg.rc_min_quantizer; + } + svc_params.scaling_factor_num[0] = cfg.g_h; + svc_params.scaling_factor_den[0] = cfg.g_h; + vpx_codec_control(&codec, VP9E_SET_SVC_PARAMETERS, &svc_params); + } + if (strncmp(encoder->name, "vp8", 3) == 0) { + vpx_codec_control(&codec, VP8E_SET_SCREEN_CONTENT_MODE, 0); + } + vpx_codec_control(&codec, VP8E_SET_TOKEN_PARTITIONS, 1); + // This controls the maximum target size of the key frame. + // For generating smaller key frames, use a smaller max_intra_size_pct + // value, like 100 or 200. + { + const int max_intra_size_pct = 900; + vpx_codec_control(&codec, VP8E_SET_MAX_INTRA_BITRATE_PCT, + max_intra_size_pct); + } + + frame_avail = 1; + while (frame_avail || got_data) { + struct vpx_usec_timer timer; + vpx_codec_iter_t iter = NULL; + const vpx_codec_cx_pkt_t *pkt; +#if VPX_ENCODER_ABI_VERSION > (4 + VPX_CODEC_ABI_VERSION) + // Update the temporal layer_id. No spatial layers in this test. + layer_id.spatial_layer_id = 0; +#endif + layer_id.temporal_layer_id = + cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity]; + if (strncmp(encoder->name, "vp9", 3) == 0) { + vpx_codec_control(&codec, VP9E_SET_SVC_LAYER_ID, &layer_id); + } else if (strncmp(encoder->name, "vp8", 3) == 0) { + vpx_codec_control(&codec, VP8E_SET_TEMPORAL_LAYER_ID, + layer_id.temporal_layer_id); + } + flags = layer_flags[frame_cnt % flag_periodicity]; + if (layering_mode == 0) + flags = 0; + frame_avail = vpx_img_read(&raw, infile); + if (frame_avail) + ++rc.layer_input_frames[layer_id.temporal_layer_id]; + vpx_usec_timer_start(&timer); + if (vpx_codec_encode(&codec, frame_avail? &raw : NULL, pts, 1, flags, + VPX_DL_REALTIME)) { + die_codec(&codec, "Failed to encode frame"); + } + vpx_usec_timer_mark(&timer); + cx_time += vpx_usec_timer_elapsed(&timer); + // Reset KF flag. + if (layering_mode != 7) { + layer_flags[0] &= ~VPX_EFLAG_FORCE_KF; + } + got_data = 0; + while ( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) { + got_data = 1; + switch (pkt->kind) { + case VPX_CODEC_CX_FRAME_PKT: + for (i = cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity]; + i < cfg.ts_number_layers; ++i) { + vpx_video_writer_write_frame(outfile[i], pkt->data.frame.buf, + pkt->data.frame.sz, pts); + ++rc.layer_tot_enc_frames[i]; + rc.layer_encoding_bitrate[i] += 8.0 * pkt->data.frame.sz; + // Keep count of rate control stats per layer (for non-key frames). + if (i == cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity] && + !(pkt->data.frame.flags & VPX_FRAME_IS_KEY)) { + rc.layer_avg_frame_size[i] += 8.0 * pkt->data.frame.sz; + rc.layer_avg_rate_mismatch[i] += + fabs(8.0 * pkt->data.frame.sz - rc.layer_pfb[i]) / + rc.layer_pfb[i]; + ++rc.layer_enc_frames[i]; + } + } + // Update for short-time encoding bitrate states, for moving window + // of size rc->window, shifted by rc->window / 2. + // Ignore first window segment, due to key frame. + if (frame_cnt > rc.window_size) { + sum_bitrate += 0.001 * 8.0 * pkt->data.frame.sz * framerate; + if (frame_cnt % rc.window_size == 0) { + rc.window_count += 1; + rc.avg_st_encoding_bitrate += sum_bitrate / rc.window_size; + rc.variance_st_encoding_bitrate += + (sum_bitrate / rc.window_size) * + (sum_bitrate / rc.window_size); + sum_bitrate = 0.0; + } + } + // Second shifted window. + if (frame_cnt > rc.window_size + rc.window_size / 2) { + sum_bitrate2 += 0.001 * 8.0 * pkt->data.frame.sz * framerate; + if (frame_cnt > 2 * rc.window_size && + frame_cnt % rc.window_size == 0) { + rc.window_count += 1; + rc.avg_st_encoding_bitrate += sum_bitrate2 / rc.window_size; + rc.variance_st_encoding_bitrate += + (sum_bitrate2 / rc.window_size) * + (sum_bitrate2 / rc.window_size); + sum_bitrate2 = 0.0; + } + } + break; + default: + break; + } + } + ++frame_cnt; + pts += frame_duration; + } + fclose(infile); + printout_rate_control_summary(&rc, &cfg, frame_cnt); + printf("\n"); + printf("Frame cnt and encoding time/FPS stats for encoding: %d %f %f \n", + frame_cnt, + 1000 * (float)cx_time / (double)(frame_cnt * 1000000), + 1000000 * (double)frame_cnt / (double)cx_time); + + if (vpx_codec_destroy(&codec)) + die_codec(&codec, "Failed to destroy codec"); + + // Try to rewrite the output file headers with the actual frame count. + for (i = 0; i < cfg.ts_number_layers; ++i) + vpx_video_writer_close(outfile[i]); + + vpx_img_free(&raw); + return EXIT_SUCCESS; +}
diff --git a/src/third_party/libvpx/fix_orbis_deps.py b/src/third_party/libvpx/fix_orbis_deps.py new file mode 100644 index 0000000..64abfda --- /dev/null +++ b/src/third_party/libvpx/fix_orbis_deps.py
@@ -0,0 +1,27 @@ +import re +import sys + +abs_path_re = re.compile('[A-Za-z]:\\.*') + +contents = sys.stdin.readlines() +if contents: + contents = [line.rstrip() for line in contents] + contents = [line.replace('"', '') for line in contents] + _, first_dep_line = contents[0].split(':', 1) + deps = [] + remaining_deps = [first_dep_line] + contents[1:] + # Go through each line and split on whitespace. + # There may be multiple deps on each line. + for line in remaining_deps: + line = line.strip(' \t\\') + line = line.replace('\\', '/') + line_deps = line.split() + deps.extend(line_deps) + + # Strip out all absolute paths. Assume these are system includes + # we don't care about. colons in the path confuse make. + deps = filter(lambda d: not abs_path_re.match(d), deps) + + sys.stdout.write('%s %s: \\\n' % (deps[0] + '.d', deps[0] + '.o')) + sys.stdout.write(' \\\n'.join([' %s' % d for d in deps])) + sys.stdout.write('\n')
diff --git a/src/third_party/libvpx/ivfdec.c b/src/third_party/libvpx/ivfdec.c new file mode 100644 index 0000000..7fc25a0 --- /dev/null +++ b/src/third_party/libvpx/ivfdec.c
@@ -0,0 +1,112 @@ +/* + * Copyright (c) 2013 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "vpx_ports/mem_ops.h" + +#include "./ivfdec.h" + +static const char *IVF_SIGNATURE = "DKIF"; + +static void fix_framerate(int *num, int *den) { + // Some versions of vpxenc used 1/(2*fps) for the timebase, so + // we can guess the framerate using only the timebase in this + // case. Other files would require reading ahead to guess the + // timebase, like we do for webm. + if (*den > 0 && *den < 1000000000 && *num > 0 && *num < 1000) { + // Correct for the factor of 2 applied to the timebase in the encoder. + if (*num & 1) + *den *= 2; + else + *num /= 2; + } else { + // Don't know FPS for sure, and don't have readahead code + // (yet?), so just default to 30fps. + *num = 30; + *den = 1; + } +} + +int file_is_ivf(struct VpxInputContext *input_ctx) { + char raw_hdr[32]; + int is_ivf = 0; + + if (fread(raw_hdr, 1, 32, input_ctx->file) == 32) { + if (memcmp(IVF_SIGNATURE, raw_hdr, 4) == 0) { + is_ivf = 1; + + if (mem_get_le16(raw_hdr + 4) != 0) { + fprintf(stderr, "Error: Unrecognized IVF version! This file may not" + " decode properly."); + } + + input_ctx->fourcc = mem_get_le32(raw_hdr + 8); + input_ctx->width = mem_get_le16(raw_hdr + 12); + input_ctx->height = mem_get_le16(raw_hdr + 14); + input_ctx->framerate.numerator = mem_get_le32(raw_hdr + 16); + input_ctx->framerate.denominator = mem_get_le32(raw_hdr + 20); + fix_framerate(&input_ctx->framerate.numerator, + &input_ctx->framerate.denominator); + } + } + + if (!is_ivf) { + rewind(input_ctx->file); + input_ctx->detect.buf_read = 0; + } else { + input_ctx->detect.position = 4; + } + return is_ivf; +} + +int ivf_read_frame(FILE *infile, uint8_t **buffer, + size_t *bytes_read, size_t *buffer_size) { + char raw_header[IVF_FRAME_HDR_SZ] = {0}; + size_t frame_size = 0; + + if (fread(raw_header, IVF_FRAME_HDR_SZ, 1, infile) != 1) { + if (!feof(infile)) + warn("Failed to read frame size\n"); + } else { + frame_size = mem_get_le32(raw_header); + + if (frame_size > 256 * 1024 * 1024) { + warn("Read invalid frame size (%u)\n", (unsigned int)frame_size); + frame_size = 0; + } + + if (frame_size > *buffer_size) { + uint8_t *new_buffer = realloc(*buffer, 2 * frame_size); + + if (new_buffer) { + *buffer = new_buffer; + *buffer_size = 2 * frame_size; + } else { + warn("Failed to allocate compressed data buffer\n"); + frame_size = 0; + } + } + } + + if (!feof(infile)) { + if (fread(*buffer, 1, frame_size, infile) != frame_size) { + warn("Failed to read full frame\n"); + return 1; + } + + *bytes_read = frame_size; + return 0; + } + + return 1; +}
diff --git a/src/third_party/libvpx/ivfdec.h b/src/third_party/libvpx/ivfdec.h new file mode 100644 index 0000000..dd29cc6 --- /dev/null +++ b/src/third_party/libvpx/ivfdec.h
@@ -0,0 +1,28 @@ +/* + * Copyright (c) 2013 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#ifndef IVFDEC_H_ +#define IVFDEC_H_ + +#include "./tools_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int file_is_ivf(struct VpxInputContext *input); + +int ivf_read_frame(FILE *infile, uint8_t **buffer, + size_t *bytes_read, size_t *buffer_size); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // IVFDEC_H_
diff --git a/src/third_party/libvpx/ivfenc.c b/src/third_party/libvpx/ivfenc.c new file mode 100644 index 0000000..4a97c42 --- /dev/null +++ b/src/third_party/libvpx/ivfenc.c
@@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "./ivfenc.h" + +#include "vpx/vpx_encoder.h" +#include "vpx_ports/mem_ops.h" + +void ivf_write_file_header(FILE *outfile, + const struct vpx_codec_enc_cfg *cfg, + unsigned int fourcc, + int frame_cnt) { + char header[32]; + + header[0] = 'D'; + header[1] = 'K'; + header[2] = 'I'; + header[3] = 'F'; + mem_put_le16(header + 4, 0); // version + mem_put_le16(header + 6, 32); // header size + mem_put_le32(header + 8, fourcc); // fourcc + mem_put_le16(header + 12, cfg->g_w); // width + mem_put_le16(header + 14, cfg->g_h); // height + mem_put_le32(header + 16, cfg->g_timebase.den); // rate + mem_put_le32(header + 20, cfg->g_timebase.num); // scale + mem_put_le32(header + 24, frame_cnt); // length + mem_put_le32(header + 28, 0); // unused + + fwrite(header, 1, 32, outfile); +} + +void ivf_write_frame_header(FILE *outfile, int64_t pts, size_t frame_size) { + char header[12]; + + mem_put_le32(header, (int)frame_size); + mem_put_le32(header + 4, (int)(pts & 0xFFFFFFFF)); + mem_put_le32(header + 8, (int)(pts >> 32)); + fwrite(header, 1, 12, outfile); +} + +void ivf_write_frame_size(FILE *outfile, size_t frame_size) { + char header[4]; + + mem_put_le32(header, (int)frame_size); + fwrite(header, 1, 4, outfile); +}
diff --git a/src/third_party/libvpx/ivfenc.h b/src/third_party/libvpx/ivfenc.h new file mode 100644 index 0000000..6623687 --- /dev/null +++ b/src/third_party/libvpx/ivfenc.h
@@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#ifndef IVFENC_H_ +#define IVFENC_H_ + +#include "./tools_common.h" + +struct vpx_codec_enc_cfg; +struct vpx_codec_cx_pkt; + +#ifdef __cplusplus +extern "C" { +#endif + +void ivf_write_file_header(FILE *outfile, + const struct vpx_codec_enc_cfg *cfg, + uint32_t fourcc, + int frame_cnt); + +void ivf_write_frame_header(FILE *outfile, int64_t pts, size_t frame_size); + +void ivf_write_frame_size(FILE *outfile, size_t frame_size); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // IVFENC_H_
diff --git a/src/third_party/libvpx/keywords.dox b/src/third_party/libvpx/keywords.dox new file mode 100644 index 0000000..56f5368 --- /dev/null +++ b/src/third_party/libvpx/keywords.dox
@@ -0,0 +1,51 @@ +/*!\page rfc2119 RFC2119 Keywords + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL + NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and + "OPTIONAL" in this document are to be interpreted as described in + <a href="http://www.ietf.org/rfc/rfc2119.txt">RFC 2119.</a> + +Specifically, the following definitions are used: + +\section MUST +\anchor REQUIRED +\anchor SHALL + This word, or the terms "REQUIRED" or "SHALL", mean that the + definition is an absolute requirement of the specification. + +\section MUSTNOT MUST NOT +\anchor SHALLNOT + This phrase, or the phrase "SHALL NOT", mean that the + definition is an absolute prohibition of the specification. + +\section SHOULD +\anchor RECOMMENDED + This word, or the adjective "RECOMMENDED", mean that there + may exist valid reasons in particular circumstances to ignore a + particular item, but the full implications must be understood and + carefully weighed before choosing a different course. + +\section SHOULDNOT SHOULD NOT +\anchor NOTRECOMMENDED + This phrase, or the phrase "NOT RECOMMENDED" mean that + there may exist valid reasons in particular circumstances when the + particular behavior is acceptable or even useful, but the full + implications should be understood and the case carefully weighed + before implementing any behavior described with this label. + +\section MAY +\anchor OPTIONAL + This word, or the adjective "OPTIONAL", mean that an item is + truly optional. One vendor may choose to include the item because a + particular marketplace requires it or because the vendor feels that + it enhances the product while another vendor may omit the same item. + An implementation which does not include a particular option \ref MUST be + prepared to interoperate with another implementation which does + include the option, though perhaps with reduced functionality. In the + same vein an implementation which does include a particular option + \ref MUST be prepared to interoperate with another implementation which + does not include the option (except, of course, for the feature the + option provides.) + + +*/
diff --git a/src/third_party/libvpx/libs.doxy_template b/src/third_party/libvpx/libs.doxy_template new file mode 100644 index 0000000..5a8f847 --- /dev/null +++ b/src/third_party/libvpx/libs.doxy_template
@@ -0,0 +1,1296 @@ +## +## Copyright (c) 2010 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## + + +# Doxyfile 1.5.4 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file that +# follow. The default is UTF-8 which is also the encoding used for all text before +# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into +# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of +# possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = "WebM Codec SDK" + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = docs + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, +# Italian, Japanese, Japanese-en (Japanese with English messages), Korean, +# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, +# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to java_doc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a java_doc-style +# comment as the brief description. If set to NO, the java_doc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to +# include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the defqault) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct (or union) is +# documented as struct with the name of the typedef. So +# typedef struct type_s {} type_t, will appear in the documentation as a struct +# with name type_t. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named type_s. This can typically +# be useful for C code where the coding convention is that all structs are +# typedef'ed and only the typedef is referenced never the struct's name. + +TYPEDEF_HIDES_STRUCT = NO + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be extracted +# and appear in the documentation as a namespace called 'anonymous_namespace{file}', +# where file will be replaced with the base name of the file that contains the anonymous +# namespace. By default anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = NO + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from the +# version control system). Doxygen will invoke the program by executing (via +# popen()) the command <command> <input-file>, where <command> is the value of +# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = + +# This tag can be used to specify the character encoding of the source files that +# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default +# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. +# See http://www.gnu.org/software/libiconv for the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the output. +# The symbol name can be a fully qualified name, a word, or if the wildcard * is used, +# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command <filter> <input-file>, where <filter> +# is the value of the INPUT_FILTER tag, and <input-file> is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH +# then you must also enable this option. If you don't then doxygen will produce +# a warning and turn it on anyway + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentstion. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# java_script and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# java_script, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the la_te_x output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the la_te_x docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the la_te_x command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for la_te_x. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# la_te_x documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = YES + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = letter + +# The EXTRA_PACKAGES tag can be to specify one or more names of la_te_x +# packages that should be included in the la_te_x output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal la_te_x header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the la_te_x that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated la_te_x files. This will instruct la_te_x to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the auto_gen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an auto_gen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and la_te_x code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = *.h + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and la_te_x) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to +# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to +# specify the directory where the mscgen tool resides. If left empty the tool is assumed to +# be found in the default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a caller dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable caller graphs for selected +# functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the number +# of direct children of the root node in a graph is already larger than +# MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, which results in a white background. +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). + +DOT_TRANSPARENT = YES + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO
diff --git a/src/third_party/libvpx/libs.mk b/src/third_party/libvpx/libs.mk new file mode 100644 index 0000000..f563bd3 --- /dev/null +++ b/src/third_party/libvpx/libs.mk
@@ -0,0 +1,649 @@ +## +## Copyright (c) 2010 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## + + +# ARM assembly files are written in RVCT-style. We use some make magic to +# filter those files to allow GCC compilation +ifeq ($(ARCH_ARM),yes) + ASM:=$(if $(filter yes,$(CONFIG_GCC)$(CONFIG_MSVS)),.asm.s,.asm) +else + ASM:=.asm +endif + +# +# Rule to generate runtime cpu detection files +# +define rtcd_h_template +$$(BUILD_PFX)$(1).h: $$(SRC_PATH_BARE)/$(2) + @echo " [CREATE] $$@" + $$(qexec)$$(SRC_PATH_BARE)/build/make/rtcd.pl --arch=$$(TGT_ISA) \ + --sym=$(1) \ + --config=$$(CONFIG_DIR)$$(target)-$$(TOOLCHAIN).mk \ + $$(RTCD_OPTIONS) $$^ > $$@ +CLEAN-OBJS += $$(BUILD_PFX)$(1).h +RTCD += $$(BUILD_PFX)$(1).h +endef + +CODEC_SRCS-yes += CHANGELOG +CODEC_SRCS-yes += libs.mk + +include $(SRC_PATH_BARE)/vpx/vpx_codec.mk +CODEC_SRCS-yes += $(addprefix vpx/,$(call enabled,API_SRCS)) +CODEC_DOC_SRCS += $(addprefix vpx/,$(call enabled,API_DOC_SRCS)) + +include $(SRC_PATH_BARE)/vpx_mem/vpx_mem.mk +CODEC_SRCS-yes += $(addprefix vpx_mem/,$(call enabled,MEM_SRCS)) + +include $(SRC_PATH_BARE)/vpx_scale/vpx_scale.mk +CODEC_SRCS-yes += $(addprefix vpx_scale/,$(call enabled,SCALE_SRCS)) + +include $(SRC_PATH_BARE)/vpx_ports/vpx_ports.mk +CODEC_SRCS-yes += $(addprefix vpx_ports/,$(call enabled,PORTS_SRCS)) + +include $(SRC_PATH_BARE)/vpx_dsp/vpx_dsp.mk +CODEC_SRCS-yes += $(addprefix vpx_dsp/,$(call enabled,DSP_SRCS)) + +include $(SRC_PATH_BARE)/vpx_util/vpx_util.mk +CODEC_SRCS-yes += $(addprefix vpx_util/,$(call enabled,UTIL_SRCS)) + +ifeq ($(CONFIG_VP8),yes) + VP8_PREFIX=vp8/ + include $(SRC_PATH_BARE)/$(VP8_PREFIX)vp8_common.mk +endif + +ifeq ($(CONFIG_VP8_ENCODER),yes) + include $(SRC_PATH_BARE)/$(VP8_PREFIX)vp8cx.mk + CODEC_SRCS-yes += $(addprefix $(VP8_PREFIX),$(call enabled,VP8_CX_SRCS)) + CODEC_EXPORTS-yes += $(addprefix $(VP8_PREFIX),$(VP8_CX_EXPORTS)) + INSTALL-LIBS-yes += include/vpx/vp8.h include/vpx/vp8cx.h + INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/$(VP8_PREFIX)/% + CODEC_DOC_SECTIONS += vp8 vp8_encoder +endif + +ifeq ($(CONFIG_VP8_DECODER),yes) + include $(SRC_PATH_BARE)/$(VP8_PREFIX)vp8dx.mk + CODEC_SRCS-yes += $(addprefix $(VP8_PREFIX),$(call enabled,VP8_DX_SRCS)) + CODEC_EXPORTS-yes += $(addprefix $(VP8_PREFIX),$(VP8_DX_EXPORTS)) + INSTALL-LIBS-yes += include/vpx/vp8.h include/vpx/vp8dx.h + INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/$(VP8_PREFIX)/% + CODEC_DOC_SECTIONS += vp8 vp8_decoder +endif + +ifeq ($(CONFIG_VP9),yes) + VP9_PREFIX=vp9/ + include $(SRC_PATH_BARE)/$(VP9_PREFIX)vp9_common.mk +endif + +ifeq ($(CONFIG_VP9_ENCODER),yes) + VP9_PREFIX=vp9/ + include $(SRC_PATH_BARE)/$(VP9_PREFIX)vp9cx.mk + CODEC_SRCS-yes += $(addprefix $(VP9_PREFIX),$(call enabled,VP9_CX_SRCS)) + CODEC_EXPORTS-yes += $(addprefix $(VP9_PREFIX),$(VP9_CX_EXPORTS)) + CODEC_SRCS-yes += $(VP9_PREFIX)vp9cx.mk vpx/vp8.h vpx/vp8cx.h + INSTALL-LIBS-yes += include/vpx/vp8.h include/vpx/vp8cx.h + INSTALL-LIBS-$(CONFIG_SPATIAL_SVC) += include/vpx/svc_context.h + INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/$(VP9_PREFIX)/% + CODEC_DOC_SRCS += vpx/vp8.h vpx/vp8cx.h + CODEC_DOC_SECTIONS += vp9 vp9_encoder +endif + +ifeq ($(CONFIG_VP9_DECODER),yes) + VP9_PREFIX=vp9/ + include $(SRC_PATH_BARE)/$(VP9_PREFIX)vp9dx.mk + CODEC_SRCS-yes += $(addprefix $(VP9_PREFIX),$(call enabled,VP9_DX_SRCS)) + CODEC_EXPORTS-yes += $(addprefix $(VP9_PREFIX),$(VP9_DX_EXPORTS)) + CODEC_SRCS-yes += $(VP9_PREFIX)vp9dx.mk vpx/vp8.h vpx/vp8dx.h + INSTALL-LIBS-yes += include/vpx/vp8.h include/vpx/vp8dx.h + INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/$(VP9_PREFIX)/% + CODEC_DOC_SRCS += vpx/vp8.h vpx/vp8dx.h + CODEC_DOC_SECTIONS += vp9 vp9_decoder +endif + +VP9_PREFIX=vp9/ +$(BUILD_PFX)$(VP9_PREFIX)%.c.o: CFLAGS += -Wextra + +# VP10 make file +ifeq ($(CONFIG_VP10),yes) + VP10_PREFIX=vp10/ + include $(SRC_PATH_BARE)/$(VP10_PREFIX)vp10_common.mk +endif + +ifeq ($(CONFIG_VP10_ENCODER),yes) + VP10_PREFIX=vp10/ + include $(SRC_PATH_BARE)/$(VP10_PREFIX)vp10cx.mk + CODEC_SRCS-yes += $(addprefix $(VP10_PREFIX),$(call enabled,VP10_CX_SRCS)) + CODEC_EXPORTS-yes += $(addprefix $(VP10_PREFIX),$(VP10_CX_EXPORTS)) + CODEC_SRCS-yes += $(VP10_PREFIX)vp10cx.mk vpx/vp8.h vpx/vp8cx.h + INSTALL-LIBS-yes += include/vpx/vp8.h include/vpx/vp8cx.h + INSTALL-LIBS-$(CONFIG_SPATIAL_SVC) += include/vpx/svc_context.h + INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/$(VP10_PREFIX)/% + CODEC_DOC_SRCS += vpx/vp8.h vpx/vp8cx.h + CODEC_DOC_SECTIONS += vp9 vp9_encoder +endif + +ifeq ($(CONFIG_VP10_DECODER),yes) + VP10_PREFIX=vp10/ + include $(SRC_PATH_BARE)/$(VP10_PREFIX)vp10dx.mk + CODEC_SRCS-yes += $(addprefix $(VP10_PREFIX),$(call enabled,VP10_DX_SRCS)) + CODEC_EXPORTS-yes += $(addprefix $(VP10_PREFIX),$(VP10_DX_EXPORTS)) + CODEC_SRCS-yes += $(VP10_PREFIX)vp10dx.mk vpx/vp8.h vpx/vp8dx.h + INSTALL-LIBS-yes += include/vpx/vp8.h include/vpx/vp8dx.h + INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/$(VP10_PREFIX)/% + CODEC_DOC_SRCS += vpx/vp8.h vpx/vp8dx.h + CODEC_DOC_SECTIONS += vp9 vp9_decoder +endif + +VP10_PREFIX=vp10/ +$(BUILD_PFX)$(VP10_PREFIX)%.c.o: CFLAGS += -Wextra + +ifeq ($(CONFIG_ENCODERS),yes) + CODEC_DOC_SECTIONS += encoder +endif +ifeq ($(CONFIG_DECODERS),yes) + CODEC_DOC_SECTIONS += decoder +endif + + +ifeq ($(CONFIG_MSVS),yes) +CODEC_LIB=$(if $(CONFIG_STATIC_MSVCRT),vpxmt,vpxmd) +GTEST_LIB=$(if $(CONFIG_STATIC_MSVCRT),gtestmt,gtestmd) +# This variable uses deferred expansion intentionally, since the results of +# $(wildcard) may change during the course of the Make. +VS_PLATFORMS = $(foreach d,$(wildcard */Release/$(CODEC_LIB).lib),$(word 1,$(subst /, ,$(d)))) +endif + +# The following pairs define a mapping of locations in the distribution +# tree to locations in the source/build trees. +INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/vpx/% +INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/vpx_ports/% +INSTALL_MAPS += $(LIBSUBDIR)/% % +INSTALL_MAPS += src/% $(SRC_PATH_BARE)/% +ifeq ($(CONFIG_MSVS),yes) +INSTALL_MAPS += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/% $(p)/Release/%) +INSTALL_MAPS += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/% $(p)/Debug/%) +endif + +CODEC_SRCS-yes += build/make/version.sh +CODEC_SRCS-yes += build/make/rtcd.pl +CODEC_SRCS-yes += vpx_ports/emmintrin_compat.h +CODEC_SRCS-yes += vpx_ports/mem_ops.h +CODEC_SRCS-yes += vpx_ports/mem_ops_aligned.h +CODEC_SRCS-yes += vpx_ports/vpx_once.h +CODEC_SRCS-yes += $(BUILD_PFX)vpx_config.c +INSTALL-SRCS-no += $(BUILD_PFX)vpx_config.c +ifeq ($(ARCH_X86)$(ARCH_X86_64),yes) +INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += third_party/x86inc/x86inc.asm +endif +CODEC_EXPORTS-yes += vpx/exports_com +CODEC_EXPORTS-$(CONFIG_ENCODERS) += vpx/exports_enc +ifeq ($(CONFIG_SPATIAL_SVC),yes) +CODEC_EXPORTS-$(CONFIG_ENCODERS) += vpx/exports_spatial_svc +endif +CODEC_EXPORTS-$(CONFIG_DECODERS) += vpx/exports_dec + +INSTALL-LIBS-yes += include/vpx/vpx_codec.h +INSTALL-LIBS-yes += include/vpx/vpx_frame_buffer.h +INSTALL-LIBS-yes += include/vpx/vpx_image.h +INSTALL-LIBS-yes += include/vpx/vpx_integer.h +INSTALL-LIBS-$(CONFIG_DECODERS) += include/vpx/vpx_decoder.h +INSTALL-LIBS-$(CONFIG_ENCODERS) += include/vpx/vpx_encoder.h +ifeq ($(CONFIG_EXTERNAL_BUILD),yes) +ifeq ($(CONFIG_MSVS),yes) +INSTALL-LIBS-yes += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/$(CODEC_LIB).lib) +INSTALL-LIBS-$(CONFIG_DEBUG_LIBS) += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/$(CODEC_LIB)d.lib) +INSTALL-LIBS-$(CONFIG_SHARED) += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/vpx.dll) +INSTALL-LIBS-$(CONFIG_SHARED) += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/vpx.exp) +endif +else +INSTALL-LIBS-$(CONFIG_STATIC) += $(LIBSUBDIR)/libvpx.a +INSTALL-LIBS-$(CONFIG_DEBUG_LIBS) += $(LIBSUBDIR)/libvpx_g.a +endif + +CODEC_SRCS=$(call enabled,CODEC_SRCS) +INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += $(CODEC_SRCS) +INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += $(call enabled,CODEC_EXPORTS) + + +# Generate a list of all enabled sources, in particular for exporting to gyp +# based build systems. +libvpx_srcs.txt: + @echo " [CREATE] $@" + @echo $(CODEC_SRCS) | xargs -n1 echo | LC_ALL=C sort -u > $@ +CLEAN-OBJS += libvpx_srcs.txt + + +ifeq ($(CONFIG_EXTERNAL_BUILD),yes) +ifeq ($(CONFIG_MSVS),yes) + +vpx.def: $(call enabled,CODEC_EXPORTS) + @echo " [CREATE] $@" + $(qexec)$(SRC_PATH_BARE)/build/make/gen_msvs_def.sh\ + --name=vpx\ + --out=$@ $^ +CLEAN-OBJS += vpx.def + +# Assembly files that are included, but don't define symbols themselves. +# Filtered out to avoid Visual Studio build warnings. +ASM_INCLUDES := \ + third_party/x86inc/x86inc.asm \ + vpx_config.asm \ + vpx_ports/x86_abi_support.asm \ + +vpx.$(VCPROJ_SFX): $(CODEC_SRCS) vpx.def + @echo " [CREATE] $@" + $(qexec)$(GEN_VCPROJ) \ + $(if $(CONFIG_SHARED),--dll,--lib) \ + --target=$(TOOLCHAIN) \ + $(if $(CONFIG_STATIC_MSVCRT),--static-crt) \ + --name=vpx \ + --proj-guid=DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74 \ + --module-def=vpx.def \ + --ver=$(CONFIG_VS_VERSION) \ + --src-path-bare="$(SRC_PATH_BARE)" \ + --out=$@ $(CFLAGS) \ + $(filter-out $(addprefix %, $(ASM_INCLUDES)), $^) \ + --src-path-bare="$(SRC_PATH_BARE)" \ + +PROJECTS-yes += vpx.$(VCPROJ_SFX) + +vpx.$(VCPROJ_SFX): vpx_config.asm +vpx.$(VCPROJ_SFX): $(RTCD) + +endif +else +LIBVPX_OBJS=$(call objs,$(CODEC_SRCS)) +OBJS-yes += $(LIBVPX_OBJS) +LIBS-$(if yes,$(CONFIG_STATIC)) += $(BUILD_PFX)libvpx.a $(BUILD_PFX)libvpx_g.a +$(BUILD_PFX)libvpx_g.a: $(LIBVPX_OBJS) + +SO_VERSION_MAJOR := 3 +SO_VERSION_MINOR := 0 +SO_VERSION_PATCH := 0 +ifeq ($(filter darwin%,$(TGT_OS)),$(TGT_OS)) +LIBVPX_SO := libvpx.$(SO_VERSION_MAJOR).dylib +SHARED_LIB_SUF := .dylib +EXPORT_FILE := libvpx.syms +LIBVPX_SO_SYMLINKS := $(addprefix $(LIBSUBDIR)/, \ + libvpx.dylib ) +else +ifeq ($(filter iphonesimulator%,$(TGT_OS)),$(TGT_OS)) +LIBVPX_SO := libvpx.$(SO_VERSION_MAJOR).dylib +SHARED_LIB_SUF := .dylib +EXPORT_FILE := libvpx.syms +LIBVPX_SO_SYMLINKS := $(addprefix $(LIBSUBDIR)/, libvpx.dylib) +else +ifeq ($(filter os2%,$(TGT_OS)),$(TGT_OS)) +LIBVPX_SO := libvpx$(SO_VERSION_MAJOR).dll +SHARED_LIB_SUF := _dll.a +EXPORT_FILE := libvpx.def +LIBVPX_SO_SYMLINKS := +LIBVPX_SO_IMPLIB := libvpx_dll.a +else +LIBVPX_SO := libvpx.so.$(SO_VERSION_MAJOR).$(SO_VERSION_MINOR).$(SO_VERSION_PATCH) +SHARED_LIB_SUF := .so +EXPORT_FILE := libvpx.ver +LIBVPX_SO_SYMLINKS := $(addprefix $(LIBSUBDIR)/, \ + libvpx.so libvpx.so.$(SO_VERSION_MAJOR) \ + libvpx.so.$(SO_VERSION_MAJOR).$(SO_VERSION_MINOR)) +endif +endif +endif + +LIBS-$(CONFIG_SHARED) += $(BUILD_PFX)$(LIBVPX_SO)\ + $(notdir $(LIBVPX_SO_SYMLINKS)) \ + $(if $(LIBVPX_SO_IMPLIB), $(BUILD_PFX)$(LIBVPX_SO_IMPLIB)) +$(BUILD_PFX)$(LIBVPX_SO): $(LIBVPX_OBJS) $(EXPORT_FILE) +$(BUILD_PFX)$(LIBVPX_SO): extralibs += -lm +$(BUILD_PFX)$(LIBVPX_SO): SONAME = libvpx.so.$(SO_VERSION_MAJOR) +$(BUILD_PFX)$(LIBVPX_SO): EXPORTS_FILE = $(EXPORT_FILE) + +libvpx.ver: $(call enabled,CODEC_EXPORTS) + @echo " [CREATE] $@" + $(qexec)echo "{ global:" > $@ + $(qexec)for f in $?; do awk '{print $$2";"}' < $$f >>$@; done + $(qexec)echo "local: *; };" >> $@ +CLEAN-OBJS += libvpx.ver + +libvpx.syms: $(call enabled,CODEC_EXPORTS) + @echo " [CREATE] $@" + $(qexec)awk '{print "_"$$2}' $^ >$@ +CLEAN-OBJS += libvpx.syms + +libvpx.def: $(call enabled,CODEC_EXPORTS) + @echo " [CREATE] $@" + $(qexec)echo LIBRARY $(LIBVPX_SO:.dll=) INITINSTANCE TERMINSTANCE > $@ + $(qexec)echo "DATA MULTIPLE NONSHARED" >> $@ + $(qexec)echo "EXPORTS" >> $@ + $(qexec)awk '!/vpx_svc_*/ {print "_"$$2}' $^ >>$@ +CLEAN-OBJS += libvpx.def + +libvpx_dll.a: $(LIBVPX_SO) + @echo " [IMPLIB] $@" + $(qexec)emximp -o $@ $< +CLEAN-OBJS += libvpx_dll.a + +define libvpx_symlink_template +$(1): $(2) + @echo " [LN] $(2) $$@" + $(qexec)mkdir -p $$(dir $$@) + $(qexec)ln -sf $(2) $$@ +endef + +$(eval $(call libvpx_symlink_template,\ + $(addprefix $(BUILD_PFX),$(notdir $(LIBVPX_SO_SYMLINKS))),\ + $(BUILD_PFX)$(LIBVPX_SO))) +$(eval $(call libvpx_symlink_template,\ + $(addprefix $(DIST_DIR)/,$(LIBVPX_SO_SYMLINKS)),\ + $(LIBVPX_SO))) + + +INSTALL-LIBS-$(CONFIG_SHARED) += $(LIBVPX_SO_SYMLINKS) +INSTALL-LIBS-$(CONFIG_SHARED) += $(LIBSUBDIR)/$(LIBVPX_SO) +INSTALL-LIBS-$(CONFIG_SHARED) += $(if $(LIBVPX_SO_IMPLIB),$(LIBSUBDIR)/$(LIBVPX_SO_IMPLIB)) + + +LIBS-yes += vpx.pc +vpx.pc: config.mk libs.mk + @echo " [CREATE] $@" + $(qexec)echo '# pkg-config file from libvpx $(VERSION_STRING)' > $@ + $(qexec)echo 'prefix=$(PREFIX)' >> $@ + $(qexec)echo 'exec_prefix=$${prefix}' >> $@ + $(qexec)echo 'libdir=$${prefix}/$(LIBSUBDIR)' >> $@ + $(qexec)echo 'includedir=$${prefix}/include' >> $@ + $(qexec)echo '' >> $@ + $(qexec)echo 'Name: vpx' >> $@ + $(qexec)echo 'Description: WebM Project VPx codec implementation' >> $@ + $(qexec)echo 'Version: $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)' >> $@ + $(qexec)echo 'Requires:' >> $@ + $(qexec)echo 'Conflicts:' >> $@ + $(qexec)echo 'Libs: -L$${libdir} -lvpx -lm' >> $@ +ifeq ($(HAVE_PTHREAD_H),yes) + $(qexec)echo 'Libs.private: -lm -lpthread' >> $@ +else + $(qexec)echo 'Libs.private: -lm' >> $@ +endif + $(qexec)echo 'Cflags: -I$${includedir}' >> $@ +INSTALL-LIBS-yes += $(LIBSUBDIR)/pkgconfig/vpx.pc +INSTALL_MAPS += $(LIBSUBDIR)/pkgconfig/%.pc %.pc +CLEAN-OBJS += vpx.pc +endif + +# +# Rule to make assembler configuration file from C configuration file +# +ifeq ($(ARCH_X86)$(ARCH_X86_64),yes) +# YASM +$(BUILD_PFX)vpx_config.asm: $(BUILD_PFX)vpx_config.h + @echo " [CREATE] $@" + @egrep "#define [A-Z0-9_]+ [01]" $< \ + | awk '{print $$2 " equ " $$3}' > $@ +else +ADS2GAS=$(if $(filter yes,$(CONFIG_GCC)),| $(ASM_CONVERSION)) +$(BUILD_PFX)vpx_config.asm: $(BUILD_PFX)vpx_config.h + @echo " [CREATE] $@" + @egrep "#define [A-Z0-9_]+ [01]" $< \ + | awk '{print $$2 " EQU " $$3}' $(ADS2GAS) > $@ + @echo " END" $(ADS2GAS) >> $@ +CLEAN-OBJS += $(BUILD_PFX)vpx_config.asm +endif + +# +# Add assembler dependencies for configuration. +# +$(filter %.s.o,$(OBJS-yes)): $(BUILD_PFX)vpx_config.asm +$(filter %$(ASM).o,$(OBJS-yes)): $(BUILD_PFX)vpx_config.asm + + +$(shell $(SRC_PATH_BARE)/build/make/version.sh "$(SRC_PATH_BARE)" $(BUILD_PFX)vpx_version.h) +CLEAN-OBJS += $(BUILD_PFX)vpx_version.h + +# +# Add include path for libwebm sources. +# +ifeq ($(CONFIG_WEBM_IO),yes) + CXXFLAGS += -I$(SRC_PATH_BARE)/third_party/libwebm +endif + +## +## libvpx test directives +## +ifeq ($(CONFIG_UNIT_TESTS),yes) +LIBVPX_TEST_DATA_PATH ?= . + +include $(SRC_PATH_BARE)/test/test.mk +LIBVPX_TEST_SRCS=$(addprefix test/,$(call enabled,LIBVPX_TEST_SRCS)) +LIBVPX_TEST_BIN=./test_libvpx$(EXE_SFX) +LIBVPX_TEST_DATA=$(addprefix $(LIBVPX_TEST_DATA_PATH)/,\ + $(call enabled,LIBVPX_TEST_DATA)) +libvpx_test_data_url=http://downloads.webmproject.org/test_data/libvpx/$(1) + +TEST_INTRA_PRED_SPEED_BIN=./test_intra_pred_speed$(EXE_SFX) +TEST_INTRA_PRED_SPEED_SRCS=$(addprefix test/,$(call enabled,TEST_INTRA_PRED_SPEED_SRCS)) +TEST_INTRA_PRED_SPEED_OBJS := $(sort $(call objs,$(TEST_INTRA_PRED_SPEED_SRCS))) + +libvpx_test_srcs.txt: + @echo " [CREATE] $@" + @echo $(LIBVPX_TEST_SRCS) | xargs -n1 echo | LC_ALL=C sort -u > $@ +CLEAN-OBJS += libvpx_test_srcs.txt + +$(LIBVPX_TEST_DATA): $(SRC_PATH_BARE)/test/test-data.sha1 + @echo " [DOWNLOAD] $@" + $(qexec)trap 'rm -f $@' INT TERM &&\ + curl -L -o $@ $(call libvpx_test_data_url,$(@F)) + +testdata:: $(LIBVPX_TEST_DATA) + $(qexec)[ -x "$$(which sha1sum)" ] && sha1sum=sha1sum;\ + [ -x "$$(which shasum)" ] && sha1sum=shasum;\ + [ -x "$$(which sha1)" ] && sha1sum=sha1;\ + if [ -n "$${sha1sum}" ]; then\ + set -e;\ + echo "Checking test data:";\ + for f in $(call enabled,LIBVPX_TEST_DATA); do\ + grep $$f $(SRC_PATH_BARE)/test/test-data.sha1 |\ + (cd $(LIBVPX_TEST_DATA_PATH); $${sha1sum} -c);\ + done; \ + else\ + echo "Skipping test data integrity check, sha1sum not found.";\ + fi + +ifeq ($(CONFIG_EXTERNAL_BUILD),yes) +ifeq ($(CONFIG_MSVS),yes) + +gtest.$(VCPROJ_SFX): $(SRC_PATH_BARE)/third_party/googletest/src/src/gtest-all.cc + @echo " [CREATE] $@" + $(qexec)$(GEN_VCPROJ) \ + --lib \ + --target=$(TOOLCHAIN) \ + $(if $(CONFIG_STATIC_MSVCRT),--static-crt) \ + --name=gtest \ + --proj-guid=EC00E1EC-AF68-4D92-A255-181690D1C9B1 \ + --ver=$(CONFIG_VS_VERSION) \ + --src-path-bare="$(SRC_PATH_BARE)" \ + -D_VARIADIC_MAX=10 \ + --out=gtest.$(VCPROJ_SFX) $(SRC_PATH_BARE)/third_party/googletest/src/src/gtest-all.cc \ + -I. -I"$(SRC_PATH_BARE)/third_party/googletest/src/include" -I"$(SRC_PATH_BARE)/third_party/googletest/src" + +PROJECTS-$(CONFIG_MSVS) += gtest.$(VCPROJ_SFX) + +test_libvpx.$(VCPROJ_SFX): $(LIBVPX_TEST_SRCS) vpx.$(VCPROJ_SFX) gtest.$(VCPROJ_SFX) + @echo " [CREATE] $@" + $(qexec)$(GEN_VCPROJ) \ + --exe \ + --target=$(TOOLCHAIN) \ + --name=test_libvpx \ + -D_VARIADIC_MAX=10 \ + --proj-guid=CD837F5F-52D8-4314-A370-895D614166A7 \ + --ver=$(CONFIG_VS_VERSION) \ + --src-path-bare="$(SRC_PATH_BARE)" \ + $(if $(CONFIG_STATIC_MSVCRT),--static-crt) \ + --out=$@ $(INTERNAL_CFLAGS) $(CFLAGS) \ + -I. -I"$(SRC_PATH_BARE)/third_party/googletest/src/include" \ + $(if $(CONFIG_WEBM_IO),-I"$(SRC_PATH_BARE)/third_party/libwebm") \ + -L. -l$(CODEC_LIB) -l$(GTEST_LIB) $^ + +PROJECTS-$(CONFIG_MSVS) += test_libvpx.$(VCPROJ_SFX) + +LIBVPX_TEST_BIN := $(addprefix $(TGT_OS:win64=x64)/Release/,$(notdir $(LIBVPX_TEST_BIN))) + +ifneq ($(strip $(TEST_INTRA_PRED_SPEED_OBJS)),) +PROJECTS-$(CONFIG_MSVS) += test_intra_pred_speed.$(VCPROJ_SFX) +test_intra_pred_speed.$(VCPROJ_SFX): $(TEST_INTRA_PRED_SPEED_SRCS) vpx.$(VCPROJ_SFX) gtest.$(VCPROJ_SFX) + @echo " [CREATE] $@" + $(qexec)$(GEN_VCPROJ) \ + --exe \ + --target=$(TOOLCHAIN) \ + --name=test_intra_pred_speed \ + -D_VARIADIC_MAX=10 \ + --proj-guid=CD837F5F-52D8-4314-A370-895D614166A7 \ + --ver=$(CONFIG_VS_VERSION) \ + --src-path-bare="$(SRC_PATH_BARE)" \ + $(if $(CONFIG_STATIC_MSVCRT),--static-crt) \ + --out=$@ $(INTERNAL_CFLAGS) $(CFLAGS) \ + -I. -I"$(SRC_PATH_BARE)/third_party/googletest/src/include" \ + -L. -l$(CODEC_LIB) -l$(GTEST_LIB) $^ +endif # TEST_INTRA_PRED_SPEED +endif +else + +include $(SRC_PATH_BARE)/third_party/googletest/gtest.mk +GTEST_SRCS := $(addprefix third_party/googletest/src/,$(call enabled,GTEST_SRCS)) +GTEST_OBJS=$(call objs,$(GTEST_SRCS)) +ifeq ($(filter win%,$(TGT_OS)),$(TGT_OS)) +# Disabling pthreads globally will cause issues on darwin and possibly elsewhere +$(GTEST_OBJS) $(GTEST_OBJS:.o=.d): CXXFLAGS += -DGTEST_HAS_PTHREAD=0 +endif +GTEST_INCLUDES := -I$(SRC_PATH_BARE)/third_party/googletest/src +GTEST_INCLUDES += -I$(SRC_PATH_BARE)/third_party/googletest/src/include +$(GTEST_OBJS) $(GTEST_OBJS:.o=.d): CXXFLAGS += $(GTEST_INCLUDES) +OBJS-yes += $(GTEST_OBJS) +LIBS-yes += $(BUILD_PFX)libgtest.a $(BUILD_PFX)libgtest_g.a +$(BUILD_PFX)libgtest_g.a: $(GTEST_OBJS) + +LIBVPX_TEST_OBJS=$(sort $(call objs,$(LIBVPX_TEST_SRCS))) +$(LIBVPX_TEST_OBJS) $(LIBVPX_TEST_OBJS:.o=.d): CXXFLAGS += $(GTEST_INCLUDES) +OBJS-yes += $(LIBVPX_TEST_OBJS) +BINS-yes += $(LIBVPX_TEST_BIN) + +CODEC_LIB=$(if $(CONFIG_DEBUG_LIBS),vpx_g,vpx) +CODEC_LIB_SUF=$(if $(CONFIG_SHARED),$(SHARED_LIB_SUF),.a) +TEST_LIBS := lib$(CODEC_LIB)$(CODEC_LIB_SUF) libgtest.a +$(LIBVPX_TEST_BIN): $(TEST_LIBS) +$(eval $(call linkerxx_template,$(LIBVPX_TEST_BIN), \ + $(LIBVPX_TEST_OBJS) \ + -L. -lvpx -lgtest $(extralibs) -lm)) + +ifneq ($(strip $(TEST_INTRA_PRED_SPEED_OBJS)),) +$(TEST_INTRA_PRED_SPEED_OBJS) $(TEST_INTRA_PRED_SPEED_OBJS:.o=.d): CXXFLAGS += $(GTEST_INCLUDES) +OBJS-yes += $(TEST_INTRA_PRED_SPEED_OBJS) +BINS-yes += $(TEST_INTRA_PRED_SPEED_BIN) + +$(TEST_INTRA_PRED_SPEED_BIN): $(TEST_LIBS) +$(eval $(call linkerxx_template,$(TEST_INTRA_PRED_SPEED_BIN), \ + $(TEST_INTRA_PRED_SPEED_OBJS) \ + -L. -lvpx -lgtest $(extralibs) -lm)) +endif # TEST_INTRA_PRED_SPEED + +endif # CONFIG_UNIT_TESTS + +# Install test sources only if codec source is included +INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += $(patsubst $(SRC_PATH_BARE)/%,%,\ + $(shell find $(SRC_PATH_BARE)/third_party/googletest -type f)) +INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += $(LIBVPX_TEST_SRCS) +INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += $(TEST_INTRA_PRED_SPEED_SRCS) + +define test_shard_template +test:: test_shard.$(1) +test-no-data-check:: test_shard_ndc.$(1) +test_shard.$(1) test_shard_ndc.$(1): $(LIBVPX_TEST_BIN) + @set -e; \ + export GTEST_SHARD_INDEX=$(1); \ + export GTEST_TOTAL_SHARDS=$(2); \ + $(LIBVPX_TEST_BIN) +test_shard.$(1): testdata +.PHONY: test_shard.$(1) +endef + +NUM_SHARDS := 10 +SHARDS := 0 1 2 3 4 5 6 7 8 9 +$(foreach s,$(SHARDS),$(eval $(call test_shard_template,$(s),$(NUM_SHARDS)))) + +endif + +## +## documentation directives +## +CLEAN-OBJS += libs.doxy +DOCS-yes += libs.doxy +libs.doxy: $(CODEC_DOC_SRCS) + @echo " [CREATE] $@" + @rm -f $@ + @echo "INPUT += $^" >> $@ + @echo "INCLUDE_PATH += ." >> $@; + @echo "ENABLED_SECTIONS += $(sort $(CODEC_DOC_SECTIONS))" >> $@ + +## Generate rtcd.h for all objects +ifeq ($(CONFIG_DEPENDENCY_TRACKING),yes) +$(OBJS-yes:.o=.d): $(RTCD) +else +$(OBJS-yes): $(RTCD) +endif + +## Update the global src list +SRCS += $(CODEC_SRCS) $(LIBVPX_TEST_SRCS) $(GTEST_SRCS) + +## +## vpxdec/vpxenc tests. +## +ifeq ($(CONFIG_UNIT_TESTS),yes) +TEST_BIN_PATH = . +ifeq ($(CONFIG_MSVS),yes) +# MSVC will build both Debug and Release configurations of tools in a +# sub directory named for the current target. Assume the user wants to +# run the Release tools, and assign TEST_BIN_PATH accordingly. +# TODO(tomfinegan): Is this adequate for ARM? +# TODO(tomfinegan): Support running the debug versions of tools? +TEST_BIN_PATH := $(addsuffix /$(TGT_OS:win64=x64)/Release, $(TEST_BIN_PATH)) +endif +utiltest utiltest-no-data-check: + $(qexec)$(SRC_PATH_BARE)/test/vpxdec.sh \ + --test-data-path $(LIBVPX_TEST_DATA_PATH) \ + --bin-path $(TEST_BIN_PATH) + $(qexec)$(SRC_PATH_BARE)/test/vpxenc.sh \ + --test-data-path $(LIBVPX_TEST_DATA_PATH) \ + --bin-path $(TEST_BIN_PATH) +utiltest: testdata +else +utiltest utiltest-no-data-check: + @echo Unit tests must be enabled to make the utiltest target. +endif + +## +## Example tests. +## +ifeq ($(CONFIG_UNIT_TESTS),yes) +# All non-MSVC targets output example targets in a sub dir named examples. +EXAMPLES_BIN_PATH = examples +ifeq ($(CONFIG_MSVS),yes) +# MSVC will build both Debug and Release configurations of the examples in a +# sub directory named for the current target. Assume the user wants to +# run the Release tools, and assign EXAMPLES_BIN_PATH accordingly. +# TODO(tomfinegan): Is this adequate for ARM? +# TODO(tomfinegan): Support running the debug versions of tools? +EXAMPLES_BIN_PATH := $(TGT_OS:win64=x64)/Release +endif +exampletest exampletest-no-data-check: examples + $(qexec)$(SRC_PATH_BARE)/test/examples.sh \ + --test-data-path $(LIBVPX_TEST_DATA_PATH) \ + --bin-path $(EXAMPLES_BIN_PATH) +exampletest: testdata +else +exampletest exampletest-no-data-check: + @echo Unit tests must be enabled to make the exampletest target. +endif
diff --git a/src/third_party/libvpx/libvpx.gyp b/src/third_party/libvpx/libvpx.gyp new file mode 100644 index 0000000..d99bd16 --- /dev/null +++ b/src/third_party/libvpx/libvpx.gyp
@@ -0,0 +1,192 @@ +{ + 'variables': { + 'libvpx_source': '<(DEPTH)/third_party/libvpx', + }, + 'targets': [ + { + 'target_name': 'libvpx', + 'type': 'static_library', + 'conditions': [ + ['target_arch == "ps4"', { + 'variables': { + 'use_system_yasm': '1', + 'yasm_output_path': '<(SHARED_INTERMEDIATE_DIR)/third_party/libvpx', + 'yasm_flags': [ + '-f', 'elf64', + '-I', '<(libvpx_source)', + '-I', '<(libvpx_source)/platforms/<(target_arch)', + ], + }, + 'includes': [ + '../yasm/yasm_compile.gypi' + ], + 'include_dirs': [ + '<(libvpx_source)', + '<(libvpx_source)/platforms/<(target_arch)', + '<(libvpx_source)/vpx_mem/memory_manager/include/', + '<(libvpx_source)/third_party/libyuv/include', + ], + # Always optimize libvpx at O3. + # Debug performance is too slow. + 'cflags': ['-O3'], + 'cflags!': ['-O0', '-O2'], + }], + ], + # This list was generated by running configure and then + # make libvpx_srcs.txt + 'sources': [ + 'platforms/ps4/vp9_rtcd.h', + 'platforms/ps4/vpx_config.c', + 'platforms/ps4/vpx_config.h', + 'platforms/ps4/vpx_dsp_rtcd.h', + 'platforms/ps4/vpx_scale_rtcd.h', + 'platforms/ps4/vpx_version.h', + 'vp9/common/vp9_alloccommon.c', + 'vp9/common/vp9_alloccommon.h', + 'vp9/common/vp9_blockd.c', + 'vp9/common/vp9_blockd.h', + 'vp9/common/vp9_common.h', + 'vp9/common/vp9_common_data.c', + 'vp9/common/vp9_common_data.h', + 'vp9/common/vp9_debugmodes.c', + 'vp9/common/vp9_entropy.c', + 'vp9/common/vp9_entropy.h', + 'vp9/common/vp9_entropymode.c', + 'vp9/common/vp9_entropymode.h', + 'vp9/common/vp9_entropymv.c', + 'vp9/common/vp9_entropymv.h', + 'vp9/common/vp9_enums.h', + 'vp9/common/vp9_filter.c', + 'vp9/common/vp9_filter.h', + 'vp9/common/vp9_frame_buffers.c', + 'vp9/common/vp9_frame_buffers.h', + 'vp9/common/vp9_idct.c', + 'vp9/common/vp9_idct.h', + 'vp9/common/vp9_loopfilter.c', + 'vp9/common/vp9_loopfilter.h', + 'vp9/common/vp9_mv.h', + 'vp9/common/vp9_mvref_common.c', + 'vp9/common/vp9_mvref_common.h', + 'vp9/common/vp9_onyxc_int.h', + 'vp9/common/vp9_ppflags.h', + 'vp9/common/vp9_pred_common.c', + 'vp9/common/vp9_pred_common.h', + 'vp9/common/vp9_quant_common.c', + 'vp9/common/vp9_quant_common.h', + 'vp9/common/vp9_reconinter.c', + 'vp9/common/vp9_reconinter.h', + 'vp9/common/vp9_reconintra.c', + 'vp9/common/vp9_reconintra.h', + 'vp9/common/vp9_rtcd.c', + 'vp9/common/vp9_scale.c', + 'vp9/common/vp9_scale.h', + 'vp9/common/vp9_scan.c', + 'vp9/common/vp9_scan.h', + 'vp9/common/vp9_seg_common.c', + 'vp9/common/vp9_seg_common.h', + 'vp9/common/vp9_textblit.h', + 'vp9/common/vp9_thread_common.c', + 'vp9/common/vp9_thread_common.h', + 'vp9/common/vp9_tile_common.c', + 'vp9/common/vp9_tile_common.h', + 'vp9/common/x86/vp9_idct_intrin_sse2.c', + 'vp9/decoder/vp9_decodeframe.c', + 'vp9/decoder/vp9_decodeframe.h', + 'vp9/decoder/vp9_decodemv.c', + 'vp9/decoder/vp9_decodemv.h', + 'vp9/decoder/vp9_decoder.c', + 'vp9/decoder/vp9_decoder.h', + 'vp9/decoder/vp9_detokenize.c', + 'vp9/decoder/vp9_detokenize.h', + 'vp9/decoder/vp9_dsubexp.c', + 'vp9/decoder/vp9_dsubexp.h', + 'vp9/decoder/vp9_dthread.c', + 'vp9/decoder/vp9_dthread.h', + 'vp9/vp9_dx_iface.c', + 'vp9/vp9_dx_iface.h', + 'vp9/vp9_iface_common.h', + 'vpx/internal/vpx_codec_internal.h', + 'vpx/internal/vpx_psnr.h', + 'vpx/src/vpx_codec.c', + 'vpx/src/vpx_decoder.c', + 'vpx/src/vpx_encoder.c', + 'vpx/src/vpx_image.c', + 'vpx/src/vpx_psnr.c', + 'vpx/vp8.h', + 'vpx/vp8dx.h', + 'vpx/vpx_codec.h', + 'vpx/vpx_decoder.h', + 'vpx/vpx_encoder.h', + 'vpx/vpx_frame_buffer.h', + 'vpx/vpx_image.h', + 'vpx/vpx_integer.h', + 'vpx_dsp/add_noise.c', + 'vpx_dsp/bitreader.c', + 'vpx_dsp/bitreader.h', + 'vpx_dsp/bitreader_buffer.c', + 'vpx_dsp/bitreader_buffer.h', + 'vpx_dsp/intrapred.c', + 'vpx_dsp/inv_txfm.c', + 'vpx_dsp/inv_txfm.h', + 'vpx_dsp/loopfilter.c', + 'vpx_dsp/prob.c', + 'vpx_dsp/prob.h', + 'vpx_dsp/txfm_common.h', + 'vpx_dsp/variance.c', + 'vpx_dsp/variance.h', + 'vpx_dsp/vpx_convolve.c', + 'vpx_dsp/vpx_convolve.h', + 'vpx_dsp/vpx_dsp_common.h', + 'vpx_dsp/vpx_dsp_rtcd.c', + 'vpx_dsp/vpx_filter.h', + 'vpx_dsp/x86/add_noise_sse2.asm', + 'vpx_dsp/x86/convolve.h', + 'vpx_dsp/x86/halfpix_variance_impl_sse2.asm', + 'vpx_dsp/x86/halfpix_variance_sse2.c', + 'vpx_dsp/x86/intrapred_sse2.asm', + 'vpx_dsp/x86/intrapred_ssse3.asm', + 'vpx_dsp/x86/inv_txfm_sse2.c', + 'vpx_dsp/x86/inv_txfm_sse2.h', + 'vpx_dsp/x86/inv_txfm_ssse3_x86_64.asm', + 'vpx_dsp/x86/inv_wht_sse2.asm', + 'vpx_dsp/x86/loopfilter_sse2.c', + 'vpx_dsp/x86/ssim_opt_x86_64.asm', + 'vpx_dsp/x86/subpel_variance_sse2.asm', + 'vpx_dsp/x86/txfm_common_sse2.h', + 'vpx_dsp/x86/variance_sse2.c', + 'vpx_dsp/x86/vpx_asm_stubs.c', + 'vpx_dsp/x86/vpx_convolve_copy_sse2.asm', + 'vpx_dsp/x86/vpx_subpixel_8t_intrin_ssse3.c', + 'vpx_dsp/x86/vpx_subpixel_8t_sse2.asm', + 'vpx_dsp/x86/vpx_subpixel_8t_ssse3.asm', + 'vpx_dsp/x86/vpx_subpixel_bilinear_sse2.asm', + 'vpx_dsp/x86/vpx_subpixel_bilinear_ssse3.asm', + 'vpx_mem/include/vpx_mem_intrnl.h', + 'vpx_mem/vpx_mem.c', + 'vpx_mem/vpx_mem.h', + 'vpx_ports/bitops.h', + 'vpx_ports/emmintrin_compat.h', + 'vpx_ports/emms.asm', + 'vpx_ports/mem.h', + 'vpx_ports/mem_ops.h', + 'vpx_ports/mem_ops_aligned.h', + 'vpx_ports/msvc.h', + 'vpx_ports/system_state.h', + 'vpx_ports/vpx_once.h', + 'vpx_ports/vpx_timer.h', + 'vpx_ports/x86.h', + 'vpx_ports/x86_abi_support.asm', + 'vpx_scale/generic/gen_scalers.c', + 'vpx_scale/generic/vpx_scale.c', + 'vpx_scale/generic/yv12config.c', + 'vpx_scale/generic/yv12extend.c', + 'vpx_scale/vpx_scale.h', + 'vpx_scale/vpx_scale_rtcd.c', + 'vpx_scale/yv12config.h', + 'vpx_util/endian_inl.h', + 'vpx_util/vpx_thread.c', + 'vpx_util/vpx_thread.h', + ], + }, + ], +}
diff --git a/src/third_party/libvpx/mainpage.dox b/src/third_party/libvpx/mainpage.dox new file mode 100644 index 0000000..ec202fa --- /dev/null +++ b/src/third_party/libvpx/mainpage.dox
@@ -0,0 +1,53 @@ +/*!\mainpage WebM Codec SDK + + \section main_contents Page Contents + - \ref main_intro + - \ref main_startpoints + - \ref main_support + + \section main_intro Introduction + Welcome to the WebM Codec SDK. This SDK allows you to integrate your + applications with the VP8 and VP9 video codecs, high quality, royalty free, + open source codecs deployed on billions of computers and devices worldwide. + + This distribution of the WebM Codec SDK includes the following support: + + \if vp8_encoder + - \ref vp8_encoder + \endif + \if vp8_decoder + - \ref vp8_decoder + \endif + + + \section main_startpoints Starting Points + - Consult the \ref changelog for a complete list of improvements in this + release. + - The \ref readme contains instructions on recompiling the sample applications. + - Read the \ref usage "usage" for a narrative on codec usage. + - Read the \ref samples "sample code" for examples of how to interact with the + codec. + - \ref codec reference + \if encoder + - \ref encoder reference + \endif + \if decoder + - \ref decoder reference + \endif + + \section main_support Support Options & FAQ + The WebM project is an open source project supported by its community. For + questions about this SDK, please mail the apps-devel@webmproject.org list. + To contribute, see http://www.webmproject.org/code/contribute and mail + codec-devel@webmproject.org. +*/ + +/*!\page changelog CHANGELOG + \verbinclude CHANGELOG +*/ + +/*!\page readme README + \verbinclude README +*/ + +/*!\defgroup codecs Supported Codecs */
diff --git a/src/third_party/libvpx/md5_utils.c b/src/third_party/libvpx/md5_utils.c new file mode 100644 index 0000000..a9b979a --- /dev/null +++ b/src/third_party/libvpx/md5_utils.c
@@ -0,0 +1,254 @@ +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + * + * Changed so as no longer to depend on Colin Plumb's `usual.h' header + * definitions + * - Ian Jackson <ian@chiark.greenend.org.uk>. + * Still in the public domain. + */ + +#include <string.h> /* for memcpy() */ + +#include "md5_utils.h" + +static void +byteSwap(UWORD32 *buf, unsigned words) { + md5byte *p; + + /* Only swap bytes for big endian machines */ + int i = 1; + + if (*(char *)&i == 1) + return; + + p = (md5byte *)buf; + + do { + *buf++ = (UWORD32)((unsigned)p[3] << 8 | p[2]) << 16 | + ((unsigned)p[1] << 8 | p[0]); + p += 4; + } while (--words); +} + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void +MD5Init(struct MD5Context *ctx) { + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bytes[0] = 0; + ctx->bytes[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void +MD5Update(struct MD5Context *ctx, md5byte const *buf, unsigned len) { + UWORD32 t; + + /* Update byte count */ + + t = ctx->bytes[0]; + + if ((ctx->bytes[0] = t + len) < t) + ctx->bytes[1]++; /* Carry from low to high */ + + t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */ + + if (t > len) { + memcpy((md5byte *)ctx->in + 64 - t, buf, len); + return; + } + + /* First chunk is an odd size */ + memcpy((md5byte *)ctx->in + 64 - t, buf, t); + byteSwap(ctx->in, 16); + MD5Transform(ctx->buf, ctx->in); + buf += t; + len -= t; + + /* Process data in 64-byte chunks */ + while (len >= 64) { + memcpy(ctx->in, buf, 64); + byteSwap(ctx->in, 16); + MD5Transform(ctx->buf, ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + memcpy(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void +MD5Final(md5byte digest[16], struct MD5Context *ctx) { + int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */ + md5byte *p = (md5byte *)ctx->in + count; + + /* Set the first char of padding to 0x80. There is always room. */ + *p++ = 0x80; + + /* Bytes of padding needed to make 56 bytes (-8..55) */ + count = 56 - 1 - count; + + if (count < 0) { /* Padding forces an extra block */ + memset(p, 0, count + 8); + byteSwap(ctx->in, 16); + MD5Transform(ctx->buf, ctx->in); + p = (md5byte *)ctx->in; + count = 56; + } + + memset(p, 0, count); + byteSwap(ctx->in, 14); + + /* Append length in bits and transform */ + ctx->in[14] = ctx->bytes[0] << 3; + ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29; + MD5Transform(ctx->buf, ctx->in); + + byteSwap(ctx->buf, 4); + memcpy(digest, ctx->buf, 16); + memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ +} + +#ifndef ASM_MD5 + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f,w,x,y,z,in,s) \ + (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x) + +#if defined(__clang__) && defined(__has_attribute) +#if __has_attribute(no_sanitize) +#define VPX_NO_UNSIGNED_OVERFLOW_CHECK \ + __attribute__((no_sanitize("unsigned-integer-overflow"))) +#endif +#endif + +#ifndef VPX_NO_UNSIGNED_OVERFLOW_CHECK +#define VPX_NO_UNSIGNED_OVERFLOW_CHECK +#endif + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +VPX_NO_UNSIGNED_OVERFLOW_CHECK void +MD5Transform(UWORD32 buf[4], UWORD32 const in[16]) { + register UWORD32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +#undef VPX_NO_UNSIGNED_OVERFLOW_CHECK + +#endif
diff --git a/src/third_party/libvpx/md5_utils.h b/src/third_party/libvpx/md5_utils.h new file mode 100644 index 0000000..bd4991b --- /dev/null +++ b/src/third_party/libvpx/md5_utils.h
@@ -0,0 +1,49 @@ +/* + * This is the header file for the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + * + * Changed so as no longer to depend on Colin Plumb's `usual.h' + * header definitions + * - Ian Jackson <ian@chiark.greenend.org.uk>. + * Still in the public domain. + */ + +#ifndef MD5_UTILS_H_ +#define MD5_UTILS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define md5byte unsigned char +#define UWORD32 unsigned int + +typedef struct MD5Context MD5Context; +struct MD5Context { + UWORD32 buf[4]; + UWORD32 bytes[2]; + UWORD32 in[16]; +}; + +void MD5Init(struct MD5Context *context); +void MD5Update(struct MD5Context *context, md5byte const *buf, unsigned len); +void MD5Final(unsigned char digest[16], struct MD5Context *context); +void MD5Transform(UWORD32 buf[4], UWORD32 const in[16]); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // MD5_UTILS_H_
diff --git a/src/third_party/libvpx/rate_hist.c b/src/third_party/libvpx/rate_hist.c new file mode 100644 index 0000000..a77222b --- /dev/null +++ b/src/third_party/libvpx/rate_hist.c
@@ -0,0 +1,285 @@ +/* + * Copyright (c) 2014 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <assert.h> +#include <stdlib.h> +#include <limits.h> +#include <stdio.h> +#include <math.h> + +#include "./rate_hist.h" + +#define RATE_BINS 100 +#define HIST_BAR_MAX 40 + +struct hist_bucket { + int low; + int high; + int count; +}; + +struct rate_hist { + int64_t *pts; + int *sz; + int samples; + int frames; + struct hist_bucket bucket[RATE_BINS]; + int total; +}; + +struct rate_hist *init_rate_histogram(const vpx_codec_enc_cfg_t *cfg, + const vpx_rational_t *fps) { + int i; + struct rate_hist *hist = malloc(sizeof(*hist)); + + // Determine the number of samples in the buffer. Use the file's framerate + // to determine the number of frames in rc_buf_sz milliseconds, with an + // adjustment (5/4) to account for alt-refs + hist->samples = cfg->rc_buf_sz * 5 / 4 * fps->num / fps->den / 1000; + + // prevent division by zero + if (hist->samples == 0) + hist->samples = 1; + + hist->frames = 0; + hist->total = 0; + + hist->pts = calloc(hist->samples, sizeof(*hist->pts)); + hist->sz = calloc(hist->samples, sizeof(*hist->sz)); + for (i = 0; i < RATE_BINS; i++) { + hist->bucket[i].low = INT_MAX; + hist->bucket[i].high = 0; + hist->bucket[i].count = 0; + } + + return hist; +} + +void destroy_rate_histogram(struct rate_hist *hist) { + if (hist) { + free(hist->pts); + free(hist->sz); + free(hist); + } +} + +void update_rate_histogram(struct rate_hist *hist, + const vpx_codec_enc_cfg_t *cfg, + const vpx_codec_cx_pkt_t *pkt) { + int i; + int64_t then = 0; + int64_t avg_bitrate = 0; + int64_t sum_sz = 0; + const int64_t now = pkt->data.frame.pts * 1000 * + (uint64_t)cfg->g_timebase.num / + (uint64_t)cfg->g_timebase.den; + + int idx = hist->frames++ % hist->samples; + hist->pts[idx] = now; + hist->sz[idx] = (int)pkt->data.frame.sz; + + if (now < cfg->rc_buf_initial_sz) + return; + + if (!cfg->rc_target_bitrate) + return; + + then = now; + + /* Sum the size over the past rc_buf_sz ms */ + for (i = hist->frames; i > 0 && hist->frames - i < hist->samples; i--) { + const int i_idx = (i - 1) % hist->samples; + + then = hist->pts[i_idx]; + if (now - then > cfg->rc_buf_sz) + break; + sum_sz += hist->sz[i_idx]; + } + + if (now == then) + return; + + avg_bitrate = sum_sz * 8 * 1000 / (now - then); + idx = (int)(avg_bitrate * (RATE_BINS / 2) / (cfg->rc_target_bitrate * 1000)); + if (idx < 0) + idx = 0; + if (idx > RATE_BINS - 1) + idx = RATE_BINS - 1; + if (hist->bucket[idx].low > avg_bitrate) + hist->bucket[idx].low = (int)avg_bitrate; + if (hist->bucket[idx].high < avg_bitrate) + hist->bucket[idx].high = (int)avg_bitrate; + hist->bucket[idx].count++; + hist->total++; +} + +static int merge_hist_buckets(struct hist_bucket *bucket, + int max_buckets, int *num_buckets) { + int small_bucket = 0, merge_bucket = INT_MAX, big_bucket = 0; + int buckets = *num_buckets; + int i; + + /* Find the extrema for this list of buckets */ + big_bucket = small_bucket = 0; + for (i = 0; i < buckets; i++) { + if (bucket[i].count < bucket[small_bucket].count) + small_bucket = i; + if (bucket[i].count > bucket[big_bucket].count) + big_bucket = i; + } + + /* If we have too many buckets, merge the smallest with an adjacent + * bucket. + */ + while (buckets > max_buckets) { + int last_bucket = buckets - 1; + + /* merge the small bucket with an adjacent one. */ + if (small_bucket == 0) + merge_bucket = 1; + else if (small_bucket == last_bucket) + merge_bucket = last_bucket - 1; + else if (bucket[small_bucket - 1].count < bucket[small_bucket + 1].count) + merge_bucket = small_bucket - 1; + else + merge_bucket = small_bucket + 1; + + assert(abs(merge_bucket - small_bucket) <= 1); + assert(small_bucket < buckets); + assert(big_bucket < buckets); + assert(merge_bucket < buckets); + + if (merge_bucket < small_bucket) { + bucket[merge_bucket].high = bucket[small_bucket].high; + bucket[merge_bucket].count += bucket[small_bucket].count; + } else { + bucket[small_bucket].high = bucket[merge_bucket].high; + bucket[small_bucket].count += bucket[merge_bucket].count; + merge_bucket = small_bucket; + } + + assert(bucket[merge_bucket].low != bucket[merge_bucket].high); + + buckets--; + + /* Remove the merge_bucket from the list, and find the new small + * and big buckets while we're at it + */ + big_bucket = small_bucket = 0; + for (i = 0; i < buckets; i++) { + if (i > merge_bucket) + bucket[i] = bucket[i + 1]; + + if (bucket[i].count < bucket[small_bucket].count) + small_bucket = i; + if (bucket[i].count > bucket[big_bucket].count) + big_bucket = i; + } + } + + *num_buckets = buckets; + return bucket[big_bucket].count; +} + +static void show_histogram(const struct hist_bucket *bucket, + int buckets, int total, int scale) { + const char *pat1, *pat2; + int i; + + switch ((int)(log(bucket[buckets - 1].high) / log(10)) + 1) { + case 1: + case 2: + pat1 = "%4d %2s: "; + pat2 = "%4d-%2d: "; + break; + case 3: + pat1 = "%5d %3s: "; + pat2 = "%5d-%3d: "; + break; + case 4: + pat1 = "%6d %4s: "; + pat2 = "%6d-%4d: "; + break; + case 5: + pat1 = "%7d %5s: "; + pat2 = "%7d-%5d: "; + break; + case 6: + pat1 = "%8d %6s: "; + pat2 = "%8d-%6d: "; + break; + case 7: + pat1 = "%9d %7s: "; + pat2 = "%9d-%7d: "; + break; + default: + pat1 = "%12d %10s: "; + pat2 = "%12d-%10d: "; + break; + } + + for (i = 0; i < buckets; i++) { + int len; + int j; + float pct; + + pct = (float)(100.0 * bucket[i].count / total); + len = HIST_BAR_MAX * bucket[i].count / scale; + if (len < 1) + len = 1; + assert(len <= HIST_BAR_MAX); + + if (bucket[i].low == bucket[i].high) + fprintf(stderr, pat1, bucket[i].low, ""); + else + fprintf(stderr, pat2, bucket[i].low, bucket[i].high); + + for (j = 0; j < HIST_BAR_MAX; j++) + fprintf(stderr, j < len ? "=" : " "); + fprintf(stderr, "\t%5d (%6.2f%%)\n", bucket[i].count, pct); + } +} + +void show_q_histogram(const int counts[64], int max_buckets) { + struct hist_bucket bucket[64]; + int buckets = 0; + int total = 0; + int scale; + int i; + + for (i = 0; i < 64; i++) { + if (counts[i]) { + bucket[buckets].low = bucket[buckets].high = i; + bucket[buckets].count = counts[i]; + buckets++; + total += counts[i]; + } + } + + fprintf(stderr, "\nQuantizer Selection:\n"); + scale = merge_hist_buckets(bucket, max_buckets, &buckets); + show_histogram(bucket, buckets, total, scale); +} + +void show_rate_histogram(struct rate_hist *hist, + const vpx_codec_enc_cfg_t *cfg, int max_buckets) { + int i, scale; + int buckets = 0; + + for (i = 0; i < RATE_BINS; i++) { + if (hist->bucket[i].low == INT_MAX) + continue; + hist->bucket[buckets++] = hist->bucket[i]; + } + + fprintf(stderr, "\nRate (over %dms window):\n", cfg->rc_buf_sz); + scale = merge_hist_buckets(hist->bucket, max_buckets, &buckets); + show_histogram(hist->bucket, buckets, hist->total, scale); +}
diff --git a/src/third_party/libvpx/rate_hist.h b/src/third_party/libvpx/rate_hist.h new file mode 100644 index 0000000..00a1676 --- /dev/null +++ b/src/third_party/libvpx/rate_hist.h
@@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef RATE_HIST_H_ +#define RATE_HIST_H_ + +#include "vpx/vpx_encoder.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct rate_hist; + +struct rate_hist *init_rate_histogram(const vpx_codec_enc_cfg_t *cfg, + const vpx_rational_t *fps); + +void destroy_rate_histogram(struct rate_hist *hist); + +void update_rate_histogram(struct rate_hist *hist, + const vpx_codec_enc_cfg_t *cfg, + const vpx_codec_cx_pkt_t *pkt); + +void show_q_histogram(const int counts[64], int max_buckets); + +void show_rate_histogram(struct rate_hist *hist, const vpx_codec_enc_cfg_t *cfg, + int max_buckets); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // RATE_HIST_H_
diff --git a/src/third_party/libvpx/solution.mk b/src/third_party/libvpx/solution.mk new file mode 100644 index 0000000..145adc0 --- /dev/null +++ b/src/third_party/libvpx/solution.mk
@@ -0,0 +1,31 @@ +## +## Copyright (c) 2010 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## + +# libvpx reverse dependencies (targets that depend on libvpx) +VPX_NONDEPS=$(addsuffix .$(VCPROJ_SFX),vpx gtest) +VPX_RDEPS=$(foreach vcp,\ + $(filter-out $(VPX_NONDEPS),$^), --dep=$(vcp:.$(VCPROJ_SFX)=):vpx) + +vpx.sln: $(wildcard *.$(VCPROJ_SFX)) + @echo " [CREATE] $@" + $(SRC_PATH_BARE)/build/make/gen_msvs_sln.sh \ + $(if $(filter vpx.$(VCPROJ_SFX),$^),$(VPX_RDEPS)) \ + --dep=test_libvpx:gtest \ + --ver=$(CONFIG_VS_VERSION)\ + --out=$@ $^ +vpx.sln.mk: vpx.sln + @true + +PROJECTS-yes += vpx.sln vpx.sln.mk +-include vpx.sln.mk + +# Always install this file, as it is an unconditional post-build rule. +INSTALL_MAPS += src/% $(SRC_PATH_BARE)/% +INSTALL-SRCS-yes += $(target).mk
diff --git a/src/third_party/libvpx/test/acm_random.h b/src/third_party/libvpx/test/acm_random.h new file mode 100644 index 0000000..b94b6e1 --- /dev/null +++ b/src/third_party/libvpx/test/acm_random.h
@@ -0,0 +1,73 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef TEST_ACM_RANDOM_H_ +#define TEST_ACM_RANDOM_H_ + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "vpx/vpx_integer.h" + +namespace libvpx_test { + +class ACMRandom { + public: + ACMRandom() : random_(DeterministicSeed()) {} + + explicit ACMRandom(int seed) : random_(seed) {} + + void Reset(int seed) { + random_.Reseed(seed); + } + uint16_t Rand16(void) { + const uint32_t value = + random_.Generate(testing::internal::Random::kMaxRange); + return (value >> 15) & 0xffff; + } + + int16_t Rand9Signed(void) { + // Use 9 bits: values between 255 (0x0FF) and -256 (0x100). + const uint32_t value = random_.Generate(512); + return static_cast<int16_t>(value) - 256; + } + + uint8_t Rand8(void) { + const uint32_t value = + random_.Generate(testing::internal::Random::kMaxRange); + // There's a bit more entropy in the upper bits of this implementation. + return (value >> 23) & 0xff; + } + + uint8_t Rand8Extremes(void) { + // Returns a random value near 0 or near 255, to better exercise + // saturation behavior. + const uint8_t r = Rand8(); + return r < 128 ? r << 4 : r >> 4; + } + + int PseudoUniform(int range) { + return random_.Generate(range); + } + + int operator()(int n) { + return PseudoUniform(n); + } + + static int DeterministicSeed(void) { + return 0xbaba; + } + + private: + testing::internal::Random random_; +}; + +} // namespace libvpx_test + +#endif // TEST_ACM_RANDOM_H_
diff --git a/src/third_party/libvpx/test/active_map_refresh_test.cc b/src/third_party/libvpx/test/active_map_refresh_test.cc new file mode 100644 index 0000000..c945661 --- /dev/null +++ b/src/third_party/libvpx/test/active_map_refresh_test.cc
@@ -0,0 +1,127 @@ +/* + * Copyright (c) 2015 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include <algorithm> +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "test/codec_factory.h" +#include "test/encode_test_driver.h" +#include "test/util.h" +#include "test/y4m_video_source.h" + +namespace { + +// Check if any pixel in a 16x16 macroblock varies between frames. +int CheckMb(const vpx_image_t ¤t, const vpx_image_t &previous, + int mb_r, int mb_c) { + for (int plane = 0; plane < 3; plane++) { + int r = 16 * mb_r; + int c0 = 16 * mb_c; + int r_top = std::min(r + 16, static_cast<int>(current.d_h)); + int c_top = std::min(c0 + 16, static_cast<int>(current.d_w)); + r = std::max(r, 0); + c0 = std::max(c0, 0); + if (plane > 0 && current.x_chroma_shift) { + c_top = (c_top + 1) >> 1; + c0 >>= 1; + } + if (plane > 0 && current.y_chroma_shift) { + r_top = (r_top + 1) >> 1; + r >>= 1; + } + for (; r < r_top; ++r) { + for (int c = c0; c < c_top; ++c) { + if (current.planes[plane][current.stride[plane] * r + c] != + previous.planes[plane][previous.stride[plane] * r + c]) + return 1; + } + } + } + return 0; +} + +void GenerateMap(int mb_rows, int mb_cols, const vpx_image_t ¤t, + const vpx_image_t &previous, uint8_t *map) { + for (int mb_r = 0; mb_r < mb_rows; ++mb_r) { + for (int mb_c = 0; mb_c < mb_cols; ++mb_c) { + map[mb_r * mb_cols + mb_c] = CheckMb(current, previous, mb_r, mb_c); + } + } +} + +const int kAqModeCyclicRefresh = 3; + +class ActiveMapRefreshTest + : public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> { + protected: + ActiveMapRefreshTest() : EncoderTest(GET_PARAM(0)) {} + virtual ~ActiveMapRefreshTest() {} + + virtual void SetUp() { + InitializeConfig(); + SetMode(GET_PARAM(1)); + cpu_used_ = GET_PARAM(2); + } + + virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, + ::libvpx_test::Encoder *encoder) { + ::libvpx_test::Y4mVideoSource *y4m_video = + static_cast<libvpx_test::Y4mVideoSource *>(video); + if (video->frame() == 1) { + encoder->Control(VP8E_SET_CPUUSED, cpu_used_); + encoder->Control(VP9E_SET_AQ_MODE, kAqModeCyclicRefresh); + } else if (video->frame() >= 2 && video->img()) { + vpx_image_t *current = video->img(); + vpx_image_t *previous = y4m_holder_->img(); + ASSERT_TRUE(previous != NULL); + vpx_active_map_t map = vpx_active_map_t(); + const int width = static_cast<int>(current->d_w); + const int height = static_cast<int>(current->d_h); + const int mb_width = (width + 15) / 16; + const int mb_height = (height + 15) / 16; + uint8_t *active_map = new uint8_t[mb_width * mb_height]; + GenerateMap(mb_height, mb_width, *current, *previous, active_map); + map.cols = mb_width; + map.rows = mb_height; + map.active_map = active_map; + encoder->Control(VP8E_SET_ACTIVEMAP, &map); + delete[] active_map; + } + if (video->img()) { + y4m_video->SwapBuffers(y4m_holder_); + } + } + + int cpu_used_; + ::libvpx_test::Y4mVideoSource *y4m_holder_; +}; + +TEST_P(ActiveMapRefreshTest, Test) { + cfg_.g_lag_in_frames = 0; + cfg_.g_profile = 1; + cfg_.rc_target_bitrate = 600; + cfg_.rc_resize_allowed = 0; + cfg_.rc_min_quantizer = 8; + cfg_.rc_max_quantizer = 30; + cfg_.g_pass = VPX_RC_ONE_PASS; + cfg_.rc_end_usage = VPX_CBR; + cfg_.kf_max_dist = 90000; + + ::libvpx_test::Y4mVideoSource video("desktop_credits.y4m", 0, 30); + ::libvpx_test::Y4mVideoSource video_holder("desktop_credits.y4m", 0, 30); + video_holder.Begin(); + y4m_holder_ = &video_holder; + + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); +} + +VP9_INSTANTIATE_TEST_CASE(ActiveMapRefreshTest, + ::testing::Values(::libvpx_test::kRealTime), + ::testing::Range(5, 6)); +} // namespace
diff --git a/src/third_party/libvpx/test/active_map_test.cc b/src/third_party/libvpx/test/active_map_test.cc new file mode 100644 index 0000000..dc3de72 --- /dev/null +++ b/src/third_party/libvpx/test/active_map_test.cc
@@ -0,0 +1,89 @@ +/* + * Copyright (c) 2014 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include <climits> +#include <vector> +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "test/codec_factory.h" +#include "test/encode_test_driver.h" +#include "test/i420_video_source.h" +#include "test/util.h" + +namespace { + +class ActiveMapTest + : public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> { + protected: + static const int kWidth = 208; + static const int kHeight = 144; + + ActiveMapTest() : EncoderTest(GET_PARAM(0)) {} + virtual ~ActiveMapTest() {} + + virtual void SetUp() { + InitializeConfig(); + SetMode(GET_PARAM(1)); + cpu_used_ = GET_PARAM(2); + } + + virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, + ::libvpx_test::Encoder *encoder) { + if (video->frame() == 1) { + encoder->Control(VP8E_SET_CPUUSED, cpu_used_); + } else if (video->frame() == 3) { + vpx_active_map_t map = vpx_active_map_t(); + uint8_t active_map[9 * 13] = { + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, + 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, + 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, + }; + map.cols = (kWidth + 15) / 16; + map.rows = (kHeight + 15) / 16; + ASSERT_EQ(map.cols, 13u); + ASSERT_EQ(map.rows, 9u); + map.active_map = active_map; + encoder->Control(VP8E_SET_ACTIVEMAP, &map); + } else if (video->frame() == 15) { + vpx_active_map_t map = vpx_active_map_t(); + map.cols = (kWidth + 15) / 16; + map.rows = (kHeight + 15) / 16; + map.active_map = NULL; + encoder->Control(VP8E_SET_ACTIVEMAP, &map); + } + } + + int cpu_used_; +}; + +TEST_P(ActiveMapTest, Test) { + // Validate that this non multiple of 64 wide clip encodes + cfg_.g_lag_in_frames = 0; + cfg_.rc_target_bitrate = 400; + cfg_.rc_resize_allowed = 0; + cfg_.g_pass = VPX_RC_ONE_PASS; + cfg_.rc_end_usage = VPX_CBR; + cfg_.kf_max_dist = 90000; + + ::libvpx_test::I420VideoSource video("hantro_odd.yuv", kWidth, kHeight, 30, + 1, 0, 20); + + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); +} + +VP9_INSTANTIATE_TEST_CASE(ActiveMapTest, + ::testing::Values(::libvpx_test::kRealTime), + ::testing::Range(0, 9)); +} // namespace
diff --git a/src/third_party/libvpx/test/add_noise_test.cc b/src/third_party/libvpx/test/add_noise_test.cc new file mode 100644 index 0000000..e9945c4 --- /dev/null +++ b/src/third_party/libvpx/test/add_noise_test.cc
@@ -0,0 +1,197 @@ +/* + * Copyright (c) 2016 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include <math.h> +#include "test/clear_system_state.h" +#include "test/register_state_check.h" +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "./vpx_dsp_rtcd.h" +#include "vpx/vpx_integer.h" +#include "vpx_mem/vpx_mem.h" + +namespace { + +// TODO(jimbankoski): make width and height integers not unsigned. +typedef void (*AddNoiseFunc)(unsigned char *start, char *noise, + char blackclamp[16], char whiteclamp[16], + char bothclamp[16], unsigned int width, + unsigned int height, int pitch); + +class AddNoiseTest + : public ::testing::TestWithParam<AddNoiseFunc> { + public: + virtual void TearDown() { + libvpx_test::ClearSystemState(); + } + virtual ~AddNoiseTest() {} +}; + +double stddev6(char a, char b, char c, char d, char e, char f) { + const double n = (a + b + c + d + e + f) / 6.0; + const double v = ((a - n) * (a - n) + (b - n) * (b - n) + (c - n) * (c - n) + + (d - n) * (d - n) + (e - n) * (e - n) + (f - n) * (f - n)) / + 6.0; + return sqrt(v); +} + +// TODO(jimbankoski): The following 2 functions are duplicated in each codec. +// For now the vp9 one has been copied into the test as is. We should normalize +// these in vpx_dsp and not have 3 copies of these unless there is different +// noise we add for each codec. + +double gaussian(double sigma, double mu, double x) { + return 1 / (sigma * sqrt(2.0 * 3.14159265)) * + (exp(-(x - mu) * (x - mu) / (2 * sigma * sigma))); +} + +int setup_noise(int size_noise, char *noise) { + char char_dist[300]; + const int ai = 4; + const int qi = 24; + const double sigma = ai + .5 + .6 * (63 - qi) / 63.0; + + /* set up a lookup table of 256 entries that matches + * a gaussian distribution with sigma determined by q. + */ + int next = 0; + + for (int i = -32; i < 32; i++) { + int a_i = (int) (0.5 + 256 * gaussian(sigma, 0, i)); + + if (a_i) { + for (int j = 0; j < a_i; j++) { + char_dist[next + j] = (char)(i); + } + + next = next + a_i; + } + } + + for (; next < 256; next++) + char_dist[next] = 0; + + for (int i = 0; i < size_noise; i++) { + noise[i] = char_dist[rand() & 0xff]; // NOLINT + } + + // Returns the most negative value in distribution. + return char_dist[0]; +} + +TEST_P(AddNoiseTest, CheckNoiseAdded) { + DECLARE_ALIGNED(16, char, blackclamp[16]); + DECLARE_ALIGNED(16, char, whiteclamp[16]); + DECLARE_ALIGNED(16, char, bothclamp[16]); + const int width = 64; + const int height = 64; + const int image_size = width * height; + char noise[3072]; + + const int clamp = setup_noise(3072, noise); + for (int i = 0; i < 16; i++) { + blackclamp[i] = -clamp; + whiteclamp[i] = -clamp; + bothclamp[i] = -2 * clamp; + } + + uint8_t *const s = reinterpret_cast<uint8_t *>(vpx_calloc(image_size, 1)); + memset(s, 99, image_size); + + ASM_REGISTER_STATE_CHECK(GetParam()(s, noise, blackclamp, whiteclamp, + bothclamp, width, height, width)); + + // Check to make sure we don't end up having either the same or no added + // noise either vertically or horizontally. + for (int i = 0; i < image_size - 6 * width - 6; ++i) { + const double hd = stddev6(s[i] - 99, s[i + 1] - 99, s[i + 2] - 99, + s[i + 3] - 99, s[i + 4] - 99, s[i + 5] - 99); + const double vd = stddev6(s[i] - 99, s[i + width] - 99, + s[i + 2 * width] - 99, s[i + 3 * width] - 99, + s[i + 4 * width] - 99, s[i + 5 * width] - 99); + + EXPECT_NE(hd, 0); + EXPECT_NE(vd, 0); + } + + // Initialize pixels in the image to 255 and check for roll over. + memset(s, 255, image_size); + + ASM_REGISTER_STATE_CHECK(GetParam()(s, noise, blackclamp, whiteclamp, + bothclamp, width, height, width)); + + // Check to make sure don't roll over. + for (int i = 0; i < image_size; ++i) { + EXPECT_GT((int)s[i], 10) << "i = " << i; + } + + // Initialize pixels in the image to 0 and check for roll under. + memset(s, 0, image_size); + + ASM_REGISTER_STATE_CHECK(GetParam()(s, noise, blackclamp, whiteclamp, + bothclamp, width, height, width)); + + // Check to make sure don't roll under. + for (int i = 0; i < image_size; ++i) { + EXPECT_LT((int)s[i], 245) << "i = " << i; + } + + vpx_free(s); +} + +TEST_P(AddNoiseTest, CheckCvsAssembly) { + DECLARE_ALIGNED(16, char, blackclamp[16]); + DECLARE_ALIGNED(16, char, whiteclamp[16]); + DECLARE_ALIGNED(16, char, bothclamp[16]); + const int width = 64; + const int height = 64; + const int image_size = width * height; + char noise[3072]; + + const int clamp = setup_noise(3072, noise); + for (int i = 0; i < 16; i++) { + blackclamp[i] = -clamp; + whiteclamp[i] = -clamp; + bothclamp[i] = -2 * clamp; + } + + uint8_t *const s = reinterpret_cast<uint8_t *>(vpx_calloc(image_size, 1)); + uint8_t *const d = reinterpret_cast<uint8_t *>(vpx_calloc(image_size, 1)); + + memset(s, 99, image_size); + memset(d, 99, image_size); + + srand(0); + ASM_REGISTER_STATE_CHECK(GetParam()(s, noise, blackclamp, whiteclamp, + bothclamp, width, height, width)); + srand(0); + ASM_REGISTER_STATE_CHECK(vpx_plane_add_noise_c(d, noise, blackclamp, + whiteclamp, bothclamp, + width, height, width)); + + for (int i = 0; i < image_size; ++i) { + EXPECT_EQ((int)s[i], (int)d[i]) << "i = " << i; + } + + vpx_free(d); + vpx_free(s); +} + +INSTANTIATE_TEST_CASE_P(C, AddNoiseTest, + ::testing::Values(vpx_plane_add_noise_c)); + +#if HAVE_SSE2 +INSTANTIATE_TEST_CASE_P(SSE2, AddNoiseTest, + ::testing::Values(vpx_plane_add_noise_sse2)); +#endif + +#if HAVE_MSA +INSTANTIATE_TEST_CASE_P(MSA, AddNoiseTest, + ::testing::Values(vpx_plane_add_noise_msa)); +#endif +} // namespace
diff --git a/src/third_party/libvpx/test/altref_test.cc b/src/third_party/libvpx/test/altref_test.cc new file mode 100644 index 0000000..0799f42 --- /dev/null +++ b/src/third_party/libvpx/test/altref_test.cc
@@ -0,0 +1,170 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "test/codec_factory.h" +#include "test/encode_test_driver.h" +#include "test/i420_video_source.h" +#include "test/util.h" +namespace { + +#if CONFIG_VP8_ENCODER + +// lookahead range: [kLookAheadMin, kLookAheadMax). +const int kLookAheadMin = 5; +const int kLookAheadMax = 26; + +class AltRefTest : public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWithParam<int> { + protected: + AltRefTest() : EncoderTest(GET_PARAM(0)), altref_count_(0) {} + virtual ~AltRefTest() {} + + virtual void SetUp() { + InitializeConfig(); + SetMode(libvpx_test::kTwoPassGood); + } + + virtual void BeginPassHook(unsigned int pass) { + altref_count_ = 0; + } + + virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video, + libvpx_test::Encoder *encoder) { + if (video->frame() == 1) { + encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1); + encoder->Control(VP8E_SET_CPUUSED, 3); + } + } + + virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) { + if (pkt->data.frame.flags & VPX_FRAME_IS_INVISIBLE) ++altref_count_; + } + + int altref_count() const { return altref_count_; } + + private: + int altref_count_; +}; + +TEST_P(AltRefTest, MonotonicTimestamps) { + const vpx_rational timebase = { 33333333, 1000000000 }; + cfg_.g_timebase = timebase; + cfg_.rc_target_bitrate = 1000; + cfg_.g_lag_in_frames = GET_PARAM(1); + + libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + timebase.den, timebase.num, 0, 30); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + EXPECT_GE(altref_count(), 1); +} + +VP8_INSTANTIATE_TEST_CASE(AltRefTest, + ::testing::Range(kLookAheadMin, kLookAheadMax)); + +#endif // CONFIG_VP8_ENCODER + +class AltRefForcedKeyTestLarge + : public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> { + protected: + AltRefForcedKeyTestLarge() + : EncoderTest(GET_PARAM(0)), + encoding_mode_(GET_PARAM(1)), + cpu_used_(GET_PARAM(2)), + forced_kf_frame_num_(1), + frame_num_(0) {} + virtual ~AltRefForcedKeyTestLarge() {} + + virtual void SetUp() { + InitializeConfig(); + SetMode(encoding_mode_); + cfg_.rc_end_usage = VPX_VBR; + cfg_.g_threads = 0; + } + + virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, + ::libvpx_test::Encoder *encoder) { + if (video->frame() == 0) { + encoder->Control(VP8E_SET_CPUUSED, cpu_used_); + encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1); + // override test default for tile columns if necessary. +#if CONFIG_VP9_ENCODER + if (GET_PARAM(0) == &libvpx_test::kVP9) { + encoder->Control(VP9E_SET_TILE_COLUMNS, 6); + } +#endif +#if CONFIG_VP10_ENCODER + if (GET_PARAM(0) == &libvpx_test::kVP10) { + encoder->Control(VP9E_SET_TILE_COLUMNS, 6); + } +#endif + } + frame_flags_ = + (video->frame() == forced_kf_frame_num_) ? VPX_EFLAG_FORCE_KF : 0; + } + + virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) { + if (frame_num_ == forced_kf_frame_num_) { + ASSERT_TRUE(!!(pkt->data.frame.flags & VPX_FRAME_IS_KEY)) + << "Frame #" << frame_num_ << " isn't a keyframe!"; + } + ++frame_num_; + } + + ::libvpx_test::TestMode encoding_mode_; + int cpu_used_; + unsigned int forced_kf_frame_num_; + unsigned int frame_num_; +}; + +TEST_P(AltRefForcedKeyTestLarge, Frame1IsKey) { + const vpx_rational timebase = { 1, 30 }; + const int lag_values[] = { 3, 15, 25, -1 }; + + forced_kf_frame_num_ = 1; + for (int i = 0; lag_values[i] != -1; ++i) { + frame_num_ = 0; + cfg_.g_lag_in_frames = lag_values[i]; + libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + timebase.den, timebase.num, 0, 30); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + } +} + +TEST_P(AltRefForcedKeyTestLarge, ForcedFrameIsKey) { + const vpx_rational timebase = { 1, 30 }; + const int lag_values[] = { 3, 15, 25, -1 }; + + for (int i = 0; lag_values[i] != -1; ++i) { + frame_num_ = 0; + forced_kf_frame_num_ = lag_values[i] - 1; + cfg_.g_lag_in_frames = lag_values[i]; + libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + timebase.den, timebase.num, 0, 30); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + } +} + +VP8_INSTANTIATE_TEST_CASE( + AltRefForcedKeyTestLarge, + ::testing::Values(::libvpx_test::kOnePassGood), + ::testing::Range(0, 9)); + +VP9_INSTANTIATE_TEST_CASE( + AltRefForcedKeyTestLarge, + ::testing::Values(::libvpx_test::kOnePassGood), + ::testing::Range(0, 9)); + +VP10_INSTANTIATE_TEST_CASE( + AltRefForcedKeyTestLarge, + ::testing::Values(::libvpx_test::kOnePassGood), + ::testing::Range(0, 9)); + +} // namespace
diff --git a/src/third_party/libvpx/test/android/Android.mk b/src/third_party/libvpx/test/android/Android.mk new file mode 100644 index 0000000..48872a2 --- /dev/null +++ b/src/third_party/libvpx/test/android/Android.mk
@@ -0,0 +1,56 @@ +# Copyright (c) 2013 The WebM project authors. All Rights Reserved. +# +# Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file in the root of the source +# tree. An additional intellectual property rights grant can be found +# in the file PATENTS. All contributing project authors may +# be found in the AUTHORS file in the root of the source tree. +# +# This make file builds vpx_test app for android. +# The test app itself runs on the command line through adb shell +# The paths are really messed up as the libvpx make file +# expects to be made from a parent directory. +CUR_WD := $(call my-dir) +BINDINGS_DIR := $(CUR_WD)/../../.. +LOCAL_PATH := $(CUR_WD)/../../.. + +#libwebm +include $(CLEAR_VARS) +include $(BINDINGS_DIR)/libvpx/third_party/libwebm/Android.mk +LOCAL_PATH := $(CUR_WD)/../../.. + +#libvpx +include $(CLEAR_VARS) +LOCAL_STATIC_LIBRARIES := libwebm +include $(BINDINGS_DIR)/libvpx/build/make/Android.mk +LOCAL_PATH := $(CUR_WD)/../.. + +#libgtest +include $(CLEAR_VARS) +LOCAL_ARM_MODE := arm +LOCAL_CPP_EXTENSION := .cc +LOCAL_MODULE := gtest +LOCAL_C_INCLUDES := $(LOCAL_PATH)/third_party/googletest/src/ +LOCAL_C_INCLUDES += $(LOCAL_PATH)/third_party/googletest/src/include/ +LOCAL_SRC_FILES := ./third_party/googletest/src/src/gtest-all.cc +include $(BUILD_STATIC_LIBRARY) + +#libvpx_test +include $(CLEAR_VARS) +LOCAL_ARM_MODE := arm +LOCAL_MODULE := libvpx_test +LOCAL_STATIC_LIBRARIES := gtest libwebm + +ifeq ($(ENABLE_SHARED),1) + LOCAL_SHARED_LIBRARIES := vpx +else + LOCAL_STATIC_LIBRARIES += vpx +endif + +include $(LOCAL_PATH)/test/test.mk +LOCAL_C_INCLUDES := $(BINDINGS_DIR) +FILTERED_SRC := $(sort $(filter %.cc %.c, $(LIBVPX_TEST_SRCS-yes))) +LOCAL_SRC_FILES := $(addprefix ./test/, $(FILTERED_SRC)) +# some test files depend on *_rtcd.h, ensure they're generated first. +$(eval $(call rtcd_dep_template)) +include $(BUILD_EXECUTABLE)
diff --git a/src/third_party/libvpx/test/android/README b/src/third_party/libvpx/test/android/README new file mode 100644 index 0000000..4a1adcf --- /dev/null +++ b/src/third_party/libvpx/test/android/README
@@ -0,0 +1,32 @@ +Android.mk will build vpx unittests on android. +1) Configure libvpx from the parent directory: +./libvpx/configure --target=armv7-android-gcc --enable-external-build \ + --enable-postproc --disable-install-srcs --enable-multi-res-encoding \ + --enable-temporal-denoising --disable-unit-tests --disable-install-docs \ + --disable-examples --disable-runtime-cpu-detect --sdk-path=$NDK + +2) From the parent directory, invoke ndk-build: +NDK_PROJECT_PATH=. ndk-build APP_BUILD_SCRIPT=./libvpx/test/android/Android.mk \ + APP_ABI=armeabi-v7a APP_PLATFORM=android-18 APP_OPTIM=release \ + APP_STL=gnustl_static + +Note: Both adb and ndk-build are available prebuilt at: + https://chromium.googlesource.com/android_tools + +3) Run get_files.py to download the test files: +python get_files.py -i /path/to/test-data.sha1 -o /path/to/put/files \ + -u http://downloads.webmproject.org/test_data/libvpx + +4) Transfer files to device using adb. Ensure you have proper permissions for +the target + +adb push /path/to/test_files /data/local/tmp +adb push /path/to/built_libs /data/local/tmp + +NOTE: Built_libs defaults to parent_dir/libs/armeabi-v7a + +5) Run tests: +adb shell +(on device) +cd /data/local/tmp +LD_LIBRARY_PATH=. ./vpx_test
diff --git a/src/third_party/libvpx/test/android/get_files.py b/src/third_party/libvpx/test/android/get_files.py new file mode 100644 index 0000000..1c69740 --- /dev/null +++ b/src/third_party/libvpx/test/android/get_files.py
@@ -0,0 +1,118 @@ +# Copyright (c) 2013 The WebM project authors. All Rights Reserved. +# +# Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file in the root of the source +# tree. An additional intellectual property rights grant can be found +# in the file PATENTS. All contributing project authors may +# be found in the AUTHORS file in the root of the source tree. +# +# This simple script pulls test files from the webm homepage +# It is intelligent enough to only pull files if +# 1) File / test_data folder does not exist +# 2) SHA mismatch + +import pycurl +import csv +import hashlib +import re +import os.path +import time +import itertools +import sys +import getopt + +#globals +url = '' +file_list_path = '' +local_resource_path = '' + +# Helper functions: +# A simple function which returns the sha hash of a file in hex +def get_file_sha(filename): + try: + sha_hash = hashlib.sha1() + with open(filename, 'rb') as file: + buf = file.read(HASH_CHUNK) + while len(buf) > 0: + sha_hash.update(buf) + buf = file.read(HASH_CHUNK) + return sha_hash.hexdigest() + except IOError: + print "Error reading " + filename + +# Downloads a file from a url, and then checks the sha against the passed +# in sha +def download_and_check_sha(url, filename, sha): + path = os.path.join(local_resource_path, filename) + fp = open(path, "wb") + curl = pycurl.Curl() + curl.setopt(pycurl.URL, url + "/" + filename) + curl.setopt(pycurl.WRITEDATA, fp) + curl.perform() + curl.close() + fp.close() + return get_file_sha(path) == sha + +#constants +ftp_retries = 3 + +SHA_COL = 0 +NAME_COL = 1 +EXPECTED_COL = 2 +HASH_CHUNK = 65536 + +# Main script +try: + opts, args = \ + getopt.getopt(sys.argv[1:], \ + "u:i:o:", ["url=", "input_csv=", "output_dir="]) +except: + print 'get_files.py -u <url> -i <input_csv> -o <output_dir>' + sys.exit(2) + +for opt, arg in opts: + if opt == '-u': + url = arg + elif opt in ("-i", "--input_csv"): + file_list_path = os.path.join(arg) + elif opt in ("-o", "--output_dir"): + local_resource_path = os.path.join(arg) + +if len(sys.argv) != 7: + print "Expects two paths and a url!" + exit(1) + +if not os.path.isdir(local_resource_path): + os.makedirs(local_resource_path) + +file_list_csv = open(file_list_path, "rb") + +# Our 'csv' file uses multiple spaces as a delimiter, python's +# csv class only uses single character delimiters, so we convert them below +file_list_reader = csv.reader((re.sub(' +', ' ', line) \ + for line in file_list_csv), delimiter = ' ') + +file_shas = [] +file_names = [] + +for row in file_list_reader: + if len(row) != EXPECTED_COL: + continue + file_shas.append(row[SHA_COL]) + file_names.append(row[NAME_COL]) + +file_list_csv.close() + +# Download files, only if they don't already exist and have correct shas +for filename, sha in itertools.izip(file_names, file_shas): + path = os.path.join(local_resource_path, filename) + if os.path.isfile(path) \ + and get_file_sha(path) == sha: + print path + ' exists, skipping' + continue + for retry in range(0, ftp_retries): + print "Downloading " + path + if not download_and_check_sha(url, filename, sha): + print "Sha does not match, retrying..." + else: + break
diff --git a/src/third_party/libvpx/test/android/scrape_gtest_log.py b/src/third_party/libvpx/test/android/scrape_gtest_log.py new file mode 100644 index 0000000..487845c --- /dev/null +++ b/src/third_party/libvpx/test/android/scrape_gtest_log.py
@@ -0,0 +1,57 @@ +# Copyright (c) 2014 The WebM project authors. All Rights Reserved. +# +# Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file in the root of the source +# tree. An additional intellectual property rights grant can be found +# in the file PATENTS. All contributing project authors may +# be found in the AUTHORS file in the root of the source tree. + +"""Standalone script which parses a gtest log for json. + +Json is returned returns as an array. This script is used by the libvpx +waterfall to gather json results mixed in with gtest logs. This is +dubious software engineering. +""" + +import getopt +import json +import os +import re +import sys + + +def main(): + if len(sys.argv) != 3: + print "Expects a file to write json to!" + exit(1) + + try: + opts, _ = \ + getopt.getopt(sys.argv[1:], \ + 'o:', ['output-json=']) + except getopt.GetOptError: + print 'scrape_gtest_log.py -o <output_json>' + sys.exit(2) + + output_json = '' + for opt, arg in opts: + if opt in ('-o', '--output-json'): + output_json = os.path.join(arg) + + blob = sys.stdin.read() + json_string = '[' + ','.join('{' + x + '}' for x in + re.findall(r'{([^}]*.?)}', blob)) + ']' + print blob + + output = json.dumps(json.loads(json_string), indent=4, sort_keys=True) + print output + + path = os.path.dirname(output_json) + if path and not os.path.exists(path): + os.makedirs(path) + + outfile = open(output_json, 'w') + outfile.write(output) + +if __name__ == '__main__': + sys.exit(main())
diff --git a/src/third_party/libvpx/test/aq_segment_test.cc b/src/third_party/libvpx/test/aq_segment_test.cc new file mode 100644 index 0000000..1b9c943 --- /dev/null +++ b/src/third_party/libvpx/test/aq_segment_test.cc
@@ -0,0 +1,109 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "test/codec_factory.h" +#include "test/encode_test_driver.h" +#include "test/i420_video_source.h" +#include "test/util.h" + +namespace { + +class AqSegmentTest + : public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> { + protected: + AqSegmentTest() : EncoderTest(GET_PARAM(0)) {} + virtual ~AqSegmentTest() {} + + virtual void SetUp() { + InitializeConfig(); + SetMode(GET_PARAM(1)); + set_cpu_used_ = GET_PARAM(2); + aq_mode_ = 0; + } + + virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, + ::libvpx_test::Encoder *encoder) { + if (video->frame() == 1) { + encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_); + encoder->Control(VP9E_SET_AQ_MODE, aq_mode_); + encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 100); + } + } + + int set_cpu_used_; + int aq_mode_; +}; + +// Validate that this AQ segmentation mode (AQ=1, variance_ap) +// encodes and decodes without a mismatch. +TEST_P(AqSegmentTest, TestNoMisMatchAQ1) { + cfg_.rc_min_quantizer = 8; + cfg_.rc_max_quantizer = 56; + cfg_.rc_end_usage = VPX_CBR; + cfg_.g_lag_in_frames = 0; + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_target_bitrate = 300; + + aq_mode_ = 1; + + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 100); + + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); +} + +// Validate that this AQ segmentation mode (AQ=2, complexity_aq) +// encodes and decodes without a mismatch. +TEST_P(AqSegmentTest, TestNoMisMatchAQ2) { + cfg_.rc_min_quantizer = 8; + cfg_.rc_max_quantizer = 56; + cfg_.rc_end_usage = VPX_CBR; + cfg_.g_lag_in_frames = 0; + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_target_bitrate = 300; + + aq_mode_ = 2; + + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 100); + + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); +} + +// Validate that this AQ segmentation mode (AQ=3, cyclic_refresh_aq) +// encodes and decodes without a mismatch. +TEST_P(AqSegmentTest, TestNoMisMatchAQ3) { + cfg_.rc_min_quantizer = 8; + cfg_.rc_max_quantizer = 56; + cfg_.rc_end_usage = VPX_CBR; + cfg_.g_lag_in_frames = 0; + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_target_bitrate = 300; + + aq_mode_ = 3; + + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 100); + + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); +} + +VP9_INSTANTIATE_TEST_CASE(AqSegmentTest, + ::testing::Values(::libvpx_test::kRealTime, + ::libvpx_test::kOnePassGood), + ::testing::Range(3, 9)); +} // namespace
diff --git a/src/third_party/libvpx/test/avg_test.cc b/src/third_party/libvpx/test/avg_test.cc new file mode 100644 index 0000000..44d8dd7 --- /dev/null +++ b/src/third_party/libvpx/test/avg_test.cc
@@ -0,0 +1,411 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <limits.h> +#include <stdio.h> +#include <string.h> + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "./vpx_config.h" +#include "./vpx_dsp_rtcd.h" + +#include "test/acm_random.h" +#include "test/clear_system_state.h" +#include "test/register_state_check.h" +#include "test/util.h" +#include "vpx_mem/vpx_mem.h" + +using libvpx_test::ACMRandom; + +namespace { +class AverageTestBase : public ::testing::Test { + public: + AverageTestBase(int width, int height) : width_(width), height_(height) {} + + static void SetUpTestCase() { + source_data_ = reinterpret_cast<uint8_t*>( + vpx_memalign(kDataAlignment, kDataBlockSize)); + } + + static void TearDownTestCase() { + vpx_free(source_data_); + source_data_ = NULL; + } + + virtual void TearDown() { + libvpx_test::ClearSystemState(); + } + + protected: + // Handle blocks up to 4 blocks 64x64 with stride up to 128 + static const int kDataAlignment = 16; + static const int kDataBlockSize = 64 * 128; + + virtual void SetUp() { + source_stride_ = (width_ + 31) & ~31; + rnd_.Reset(ACMRandom::DeterministicSeed()); + } + + // Sum Pixels + unsigned int ReferenceAverage8x8(const uint8_t* source, int pitch) { + unsigned int average = 0; + for (int h = 0; h < 8; ++h) + for (int w = 0; w < 8; ++w) + average += source[h * pitch + w]; + return ((average + 32) >> 6); + } + + unsigned int ReferenceAverage4x4(const uint8_t* source, int pitch) { + unsigned int average = 0; + for (int h = 0; h < 4; ++h) + for (int w = 0; w < 4; ++w) + average += source[h * pitch + w]; + return ((average + 8) >> 4); + } + + void FillConstant(uint8_t fill_constant) { + for (int i = 0; i < width_ * height_; ++i) { + source_data_[i] = fill_constant; + } + } + + void FillRandom() { + for (int i = 0; i < width_ * height_; ++i) { + source_data_[i] = rnd_.Rand8(); + } + } + + int width_, height_; + static uint8_t* source_data_; + int source_stride_; + + ACMRandom rnd_; +}; +typedef unsigned int (*AverageFunction)(const uint8_t* s, int pitch); + +typedef std::tr1::tuple<int, int, int, int, AverageFunction> AvgFunc; + +class AverageTest + : public AverageTestBase, + public ::testing::WithParamInterface<AvgFunc>{ + public: + AverageTest() : AverageTestBase(GET_PARAM(0), GET_PARAM(1)) {} + + protected: + void CheckAverages() { + unsigned int expected = 0; + if (GET_PARAM(3) == 8) { + expected = ReferenceAverage8x8(source_data_+ GET_PARAM(2), + source_stride_); + } else if (GET_PARAM(3) == 4) { + expected = ReferenceAverage4x4(source_data_+ GET_PARAM(2), + source_stride_); + } + + ASM_REGISTER_STATE_CHECK(GET_PARAM(4)(source_data_+ GET_PARAM(2), + source_stride_)); + unsigned int actual = GET_PARAM(4)(source_data_+ GET_PARAM(2), + source_stride_); + + EXPECT_EQ(expected, actual); + } +}; + +typedef void (*IntProRowFunc)(int16_t hbuf[16], uint8_t const *ref, + const int ref_stride, const int height); + +typedef std::tr1::tuple<int, IntProRowFunc, IntProRowFunc> IntProRowParam; + +class IntProRowTest + : public AverageTestBase, + public ::testing::WithParamInterface<IntProRowParam> { + public: + IntProRowTest() + : AverageTestBase(16, GET_PARAM(0)), + hbuf_asm_(NULL), + hbuf_c_(NULL) { + asm_func_ = GET_PARAM(1); + c_func_ = GET_PARAM(2); + } + + protected: + virtual void SetUp() { + hbuf_asm_ = reinterpret_cast<int16_t*>( + vpx_memalign(kDataAlignment, sizeof(*hbuf_asm_) * 16)); + hbuf_c_ = reinterpret_cast<int16_t*>( + vpx_memalign(kDataAlignment, sizeof(*hbuf_c_) * 16)); + } + + virtual void TearDown() { + vpx_free(hbuf_c_); + hbuf_c_ = NULL; + vpx_free(hbuf_asm_); + hbuf_asm_ = NULL; + } + + void RunComparison() { + ASM_REGISTER_STATE_CHECK(c_func_(hbuf_c_, source_data_, 0, height_)); + ASM_REGISTER_STATE_CHECK(asm_func_(hbuf_asm_, source_data_, 0, height_)); + EXPECT_EQ(0, memcmp(hbuf_c_, hbuf_asm_, sizeof(*hbuf_c_) * 16)) + << "Output mismatch"; + } + + private: + IntProRowFunc asm_func_; + IntProRowFunc c_func_; + int16_t *hbuf_asm_; + int16_t *hbuf_c_; +}; + +typedef int16_t (*IntProColFunc)(uint8_t const *ref, const int width); + +typedef std::tr1::tuple<int, IntProColFunc, IntProColFunc> IntProColParam; + +class IntProColTest + : public AverageTestBase, + public ::testing::WithParamInterface<IntProColParam> { + public: + IntProColTest() : AverageTestBase(GET_PARAM(0), 1), sum_asm_(0), sum_c_(0) { + asm_func_ = GET_PARAM(1); + c_func_ = GET_PARAM(2); + } + + protected: + void RunComparison() { + ASM_REGISTER_STATE_CHECK(sum_c_ = c_func_(source_data_, width_)); + ASM_REGISTER_STATE_CHECK(sum_asm_ = asm_func_(source_data_, width_)); + EXPECT_EQ(sum_c_, sum_asm_) << "Output mismatch"; + } + + private: + IntProColFunc asm_func_; + IntProColFunc c_func_; + int16_t sum_asm_; + int16_t sum_c_; +}; + +typedef int (*SatdFunc)(const int16_t *coeffs, int length); +typedef std::tr1::tuple<int, SatdFunc> SatdTestParam; + +class SatdTest + : public ::testing::Test, + public ::testing::WithParamInterface<SatdTestParam> { + protected: + virtual void SetUp() { + satd_size_ = GET_PARAM(0); + satd_func_ = GET_PARAM(1); + rnd_.Reset(ACMRandom::DeterministicSeed()); + src_ = reinterpret_cast<int16_t*>( + vpx_memalign(16, sizeof(*src_) * satd_size_)); + ASSERT_TRUE(src_ != NULL); + } + + virtual void TearDown() { + libvpx_test::ClearSystemState(); + vpx_free(src_); + } + + void FillConstant(const int16_t val) { + for (int i = 0; i < satd_size_; ++i) src_[i] = val; + } + + void FillRandom() { + for (int i = 0; i < satd_size_; ++i) src_[i] = rnd_.Rand16(); + } + + void Check(const int expected) { + int total; + ASM_REGISTER_STATE_CHECK(total = satd_func_(src_, satd_size_)); + EXPECT_EQ(expected, total); + } + + int satd_size_; + + private: + int16_t *src_; + SatdFunc satd_func_; + ACMRandom rnd_; +}; + +uint8_t* AverageTestBase::source_data_ = NULL; + +TEST_P(AverageTest, MinValue) { + FillConstant(0); + CheckAverages(); +} + +TEST_P(AverageTest, MaxValue) { + FillConstant(255); + CheckAverages(); +} + +TEST_P(AverageTest, Random) { + // The reference frame, but not the source frame, may be unaligned for + // certain types of searches. + for (int i = 0; i < 1000; i++) { + FillRandom(); + CheckAverages(); + } +} + +TEST_P(IntProRowTest, MinValue) { + FillConstant(0); + RunComparison(); +} + +TEST_P(IntProRowTest, MaxValue) { + FillConstant(255); + RunComparison(); +} + +TEST_P(IntProRowTest, Random) { + FillRandom(); + RunComparison(); +} + +TEST_P(IntProColTest, MinValue) { + FillConstant(0); + RunComparison(); +} + +TEST_P(IntProColTest, MaxValue) { + FillConstant(255); + RunComparison(); +} + +TEST_P(IntProColTest, Random) { + FillRandom(); + RunComparison(); +} + + +TEST_P(SatdTest, MinValue) { + const int kMin = -32640; + const int expected = -kMin * satd_size_; + FillConstant(kMin); + Check(expected); +} + +TEST_P(SatdTest, MaxValue) { + const int kMax = 32640; + const int expected = kMax * satd_size_; + FillConstant(kMax); + Check(expected); +} + +TEST_P(SatdTest, Random) { + int expected; + switch (satd_size_) { + case 16: expected = 205298; break; + case 64: expected = 1113950; break; + case 256: expected = 4268415; break; + case 1024: expected = 16954082; break; + default: + FAIL() << "Invalid satd size (" << satd_size_ + << ") valid: 16/64/256/1024"; + } + FillRandom(); + Check(expected); +} + +using std::tr1::make_tuple; + +INSTANTIATE_TEST_CASE_P( + C, AverageTest, + ::testing::Values( + make_tuple(16, 16, 1, 8, &vpx_avg_8x8_c), + make_tuple(16, 16, 1, 4, &vpx_avg_4x4_c))); + +INSTANTIATE_TEST_CASE_P( + C, SatdTest, + ::testing::Values( + make_tuple(16, &vpx_satd_c), + make_tuple(64, &vpx_satd_c), + make_tuple(256, &vpx_satd_c), + make_tuple(1024, &vpx_satd_c))); + +#if HAVE_SSE2 +INSTANTIATE_TEST_CASE_P( + SSE2, AverageTest, + ::testing::Values( + make_tuple(16, 16, 0, 8, &vpx_avg_8x8_sse2), + make_tuple(16, 16, 5, 8, &vpx_avg_8x8_sse2), + make_tuple(32, 32, 15, 8, &vpx_avg_8x8_sse2), + make_tuple(16, 16, 0, 4, &vpx_avg_4x4_sse2), + make_tuple(16, 16, 5, 4, &vpx_avg_4x4_sse2), + make_tuple(32, 32, 15, 4, &vpx_avg_4x4_sse2))); + +INSTANTIATE_TEST_CASE_P( + SSE2, IntProRowTest, ::testing::Values( + make_tuple(16, &vpx_int_pro_row_sse2, &vpx_int_pro_row_c), + make_tuple(32, &vpx_int_pro_row_sse2, &vpx_int_pro_row_c), + make_tuple(64, &vpx_int_pro_row_sse2, &vpx_int_pro_row_c))); + +INSTANTIATE_TEST_CASE_P( + SSE2, IntProColTest, ::testing::Values( + make_tuple(16, &vpx_int_pro_col_sse2, &vpx_int_pro_col_c), + make_tuple(32, &vpx_int_pro_col_sse2, &vpx_int_pro_col_c), + make_tuple(64, &vpx_int_pro_col_sse2, &vpx_int_pro_col_c))); + +INSTANTIATE_TEST_CASE_P( + SSE2, SatdTest, + ::testing::Values( + make_tuple(16, &vpx_satd_sse2), + make_tuple(64, &vpx_satd_sse2), + make_tuple(256, &vpx_satd_sse2), + make_tuple(1024, &vpx_satd_sse2))); +#endif + +#if HAVE_NEON +INSTANTIATE_TEST_CASE_P( + NEON, AverageTest, + ::testing::Values( + make_tuple(16, 16, 0, 8, &vpx_avg_8x8_neon), + make_tuple(16, 16, 5, 8, &vpx_avg_8x8_neon), + make_tuple(32, 32, 15, 8, &vpx_avg_8x8_neon), + make_tuple(16, 16, 0, 4, &vpx_avg_4x4_neon), + make_tuple(16, 16, 5, 4, &vpx_avg_4x4_neon), + make_tuple(32, 32, 15, 4, &vpx_avg_4x4_neon))); + +INSTANTIATE_TEST_CASE_P( + NEON, IntProRowTest, ::testing::Values( + make_tuple(16, &vpx_int_pro_row_neon, &vpx_int_pro_row_c), + make_tuple(32, &vpx_int_pro_row_neon, &vpx_int_pro_row_c), + make_tuple(64, &vpx_int_pro_row_neon, &vpx_int_pro_row_c))); + +INSTANTIATE_TEST_CASE_P( + NEON, IntProColTest, ::testing::Values( + make_tuple(16, &vpx_int_pro_col_neon, &vpx_int_pro_col_c), + make_tuple(32, &vpx_int_pro_col_neon, &vpx_int_pro_col_c), + make_tuple(64, &vpx_int_pro_col_neon, &vpx_int_pro_col_c))); + +INSTANTIATE_TEST_CASE_P( + NEON, SatdTest, + ::testing::Values( + make_tuple(16, &vpx_satd_neon), + make_tuple(64, &vpx_satd_neon), + make_tuple(256, &vpx_satd_neon), + make_tuple(1024, &vpx_satd_neon))); +#endif + +#if HAVE_MSA +INSTANTIATE_TEST_CASE_P( + MSA, AverageTest, + ::testing::Values( + make_tuple(16, 16, 0, 8, &vpx_avg_8x8_msa), + make_tuple(16, 16, 5, 8, &vpx_avg_8x8_msa), + make_tuple(32, 32, 15, 8, &vpx_avg_8x8_msa), + make_tuple(16, 16, 0, 4, &vpx_avg_4x4_msa), + make_tuple(16, 16, 5, 4, &vpx_avg_4x4_msa), + make_tuple(32, 32, 15, 4, &vpx_avg_4x4_msa))); +#endif + +} // namespace
diff --git a/src/third_party/libvpx/test/blockiness_test.cc b/src/third_party/libvpx/test/blockiness_test.cc new file mode 100644 index 0000000..0c60baa --- /dev/null +++ b/src/third_party/libvpx/test/blockiness_test.cc
@@ -0,0 +1,229 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <limits.h> +#include <stdio.h> +#include <string.h> + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "./vpx_config.h" +#if CONFIG_VP9_ENCODER +#include "./vp9_rtcd.h" +#endif + +#include "test/acm_random.h" +#include "test/clear_system_state.h" +#include "test/register_state_check.h" +#include "test/util.h" + +#include "vpx_mem/vpx_mem.h" + + +extern "C" +double vp9_get_blockiness(const unsigned char *img1, int img1_pitch, + const unsigned char *img2, int img2_pitch, + int width, int height); + +using libvpx_test::ACMRandom; + +namespace { +class BlockinessTestBase : public ::testing::Test { + public: + BlockinessTestBase(int width, int height) : width_(width), height_(height) {} + + static void SetUpTestCase() { + source_data_ = reinterpret_cast<uint8_t*>( + vpx_memalign(kDataAlignment, kDataBufferSize)); + reference_data_ = reinterpret_cast<uint8_t*>( + vpx_memalign(kDataAlignment, kDataBufferSize)); + } + + static void TearDownTestCase() { + vpx_free(source_data_); + source_data_ = NULL; + vpx_free(reference_data_); + reference_data_ = NULL; + } + + virtual void TearDown() { + libvpx_test::ClearSystemState(); + } + + protected: + // Handle frames up to 640x480 + static const int kDataAlignment = 16; + static const int kDataBufferSize = 640*480; + + virtual void SetUp() { + source_stride_ = (width_ + 31) & ~31; + reference_stride_ = width_ * 2; + rnd_.Reset(ACMRandom::DeterministicSeed()); + } + + void FillConstant(uint8_t *data, int stride, uint8_t fill_constant, + int width, int height) { + for (int h = 0; h < height; ++h) { + for (int w = 0; w < width; ++w) { + data[h * stride + w] = fill_constant; + } + } + } + + void FillConstant(uint8_t *data, int stride, uint8_t fill_constant) { + FillConstant(data, stride, fill_constant, width_, height_); + } + + void FillRandom(uint8_t *data, int stride, int width, int height) { + for (int h = 0; h < height; ++h) { + for (int w = 0; w < width; ++w) { + data[h * stride + w] = rnd_.Rand8(); + } + } + } + + void FillRandom(uint8_t *data, int stride) { + FillRandom(data, stride, width_, height_); + } + + void FillRandomBlocky(uint8_t *data, int stride) { + for (int h = 0; h < height_; h += 4) { + for (int w = 0; w < width_; w += 4) { + FillRandom(data + h * stride + w, stride, 4, 4); + } + } + } + + void FillCheckerboard(uint8_t *data, int stride) { + for (int h = 0; h < height_; h += 4) { + for (int w = 0; w < width_; w += 4) { + if (((h/4) ^ (w/4)) & 1) + FillConstant(data + h * stride + w, stride, 255, 4, 4); + else + FillConstant(data + h * stride + w, stride, 0, 4, 4); + } + } + } + + void Blur(uint8_t *data, int stride, int taps) { + int sum = 0; + int half_taps = taps / 2; + for (int h = 0; h < height_; ++h) { + for (int w = 0; w < taps; ++w) { + sum += data[w + h * stride]; + } + for (int w = taps; w < width_; ++w) { + sum += data[w + h * stride] - data[w - taps + h * stride]; + data[w - half_taps + h * stride] = (sum + half_taps) / taps; + } + } + for (int w = 0; w < width_; ++w) { + for (int h = 0; h < taps; ++h) { + sum += data[h + w * stride]; + } + for (int h = taps; h < height_; ++h) { + sum += data[w + h * stride] - data[(h - taps) * stride + w]; + data[(h - half_taps) * stride + w] = (sum + half_taps) / taps; + } + } + } + int width_, height_; + static uint8_t* source_data_; + int source_stride_; + static uint8_t* reference_data_; + int reference_stride_; + + ACMRandom rnd_; +}; + +#if CONFIG_VP9_ENCODER +typedef std::tr1::tuple<int, int> BlockinessParam; +class BlockinessVP9Test + : public BlockinessTestBase, + public ::testing::WithParamInterface<BlockinessParam> { + public: + BlockinessVP9Test() : BlockinessTestBase(GET_PARAM(0), GET_PARAM(1)) {} + + protected: + int CheckBlockiness() { + return vp9_get_blockiness(source_data_, source_stride_, + reference_data_, reference_stride_, + width_, height_); + } +}; +#endif // CONFIG_VP9_ENCODER + +uint8_t* BlockinessTestBase::source_data_ = NULL; +uint8_t* BlockinessTestBase::reference_data_ = NULL; + +#if CONFIG_VP9_ENCODER +TEST_P(BlockinessVP9Test, SourceBlockierThanReference) { + // Source is blockier than reference. + FillRandomBlocky(source_data_, source_stride_); + FillConstant(reference_data_, reference_stride_, 128); + int super_blocky = CheckBlockiness(); + + EXPECT_EQ(0, super_blocky) << "Blocky source should produce 0 blockiness."; +} + +TEST_P(BlockinessVP9Test, ReferenceBlockierThanSource) { + // Source is blockier than reference. + FillConstant(source_data_, source_stride_, 128); + FillRandomBlocky(reference_data_, reference_stride_); + int super_blocky = CheckBlockiness(); + + EXPECT_GT(super_blocky, 0.0) + << "Blocky reference should score high for blockiness."; +} + +TEST_P(BlockinessVP9Test, BlurringDecreasesBlockiness) { + // Source is blockier than reference. + FillConstant(source_data_, source_stride_, 128); + FillRandomBlocky(reference_data_, reference_stride_); + int super_blocky = CheckBlockiness(); + + Blur(reference_data_, reference_stride_, 4); + int less_blocky = CheckBlockiness(); + + EXPECT_GT(super_blocky, less_blocky) + << "A straight blur should decrease blockiness."; +} + +TEST_P(BlockinessVP9Test, WorstCaseBlockiness) { + // Source is blockier than reference. + FillConstant(source_data_, source_stride_, 128); + FillCheckerboard(reference_data_, reference_stride_); + + int super_blocky = CheckBlockiness(); + + Blur(reference_data_, reference_stride_, 4); + int less_blocky = CheckBlockiness(); + + EXPECT_GT(super_blocky, less_blocky) + << "A straight blur should decrease blockiness."; +} +#endif // CONFIG_VP9_ENCODER + + +using std::tr1::make_tuple; + +//------------------------------------------------------------------------------ +// C functions + +#if CONFIG_VP9_ENCODER +const BlockinessParam c_vp9_tests[] = { + make_tuple(320, 240), + make_tuple(318, 242), + make_tuple(318, 238), +}; +INSTANTIATE_TEST_CASE_P(C, BlockinessVP9Test, ::testing::ValuesIn(c_vp9_tests)); +#endif + +} // namespace
diff --git a/src/third_party/libvpx/test/borders_test.cc b/src/third_party/libvpx/test/borders_test.cc new file mode 100644 index 0000000..ff3812c --- /dev/null +++ b/src/third_party/libvpx/test/borders_test.cc
@@ -0,0 +1,86 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include <climits> +#include <vector> +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "test/codec_factory.h" +#include "test/encode_test_driver.h" +#include "test/i420_video_source.h" +#include "test/util.h" + +namespace { + +class BordersTest : public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> { + protected: + BordersTest() : EncoderTest(GET_PARAM(0)) {} + virtual ~BordersTest() {} + + virtual void SetUp() { + InitializeConfig(); + SetMode(GET_PARAM(1)); + } + + virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, + ::libvpx_test::Encoder *encoder) { + if (video->frame() == 1) { + encoder->Control(VP8E_SET_CPUUSED, 1); + encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1); + encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7); + encoder->Control(VP8E_SET_ARNR_STRENGTH, 5); + encoder->Control(VP8E_SET_ARNR_TYPE, 3); + } + } + + virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) { + if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) { + } + } +}; + +TEST_P(BordersTest, TestEncodeHighBitrate) { + // Validate that this non multiple of 64 wide clip encodes and decodes + // without a mismatch when passing in a very low max q. This pushes + // the encoder to producing lots of big partitions which will likely + // extend into the border and test the border condition. + cfg_.g_lag_in_frames = 25; + cfg_.rc_2pass_vbr_minsection_pct = 5; + cfg_.rc_2pass_vbr_maxsection_pct = 2000; + cfg_.rc_target_bitrate = 2000; + cfg_.rc_max_quantizer = 10; + + ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0, + 40); + + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); +} +TEST_P(BordersTest, TestLowBitrate) { + // Validate that this clip encodes and decodes without a mismatch + // when passing in a very high min q. This pushes the encoder to producing + // lots of small partitions which might will test the other condition. + + cfg_.g_lag_in_frames = 25; + cfg_.rc_2pass_vbr_minsection_pct = 5; + cfg_.rc_2pass_vbr_maxsection_pct = 2000; + cfg_.rc_target_bitrate = 200; + cfg_.rc_min_quantizer = 40; + + ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0, + 40); + + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); +} + +VP9_INSTANTIATE_TEST_CASE(BordersTest, ::testing::Values( + ::libvpx_test::kTwoPassGood)); + +VP10_INSTANTIATE_TEST_CASE(BordersTest, ::testing::Values( + ::libvpx_test::kTwoPassGood)); +} // namespace
diff --git a/src/third_party/libvpx/test/byte_alignment_test.cc b/src/third_party/libvpx/test/byte_alignment_test.cc new file mode 100644 index 0000000..3a808b0 --- /dev/null +++ b/src/third_party/libvpx/test/byte_alignment_test.cc
@@ -0,0 +1,189 @@ +/* + * Copyright (c) 2014 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <string> + +#include "./vpx_config.h" +#include "test/codec_factory.h" +#include "test/decode_test_driver.h" +#include "test/md5_helper.h" +#include "test/util.h" +#if CONFIG_WEBM_IO +#include "test/webm_video_source.h" +#endif + +namespace { + +#if CONFIG_WEBM_IO + +const int kLegacyByteAlignment = 0; +const int kLegacyYPlaneByteAlignment = 32; +const int kNumPlanesToCheck = 3; +const char kVP9TestFile[] = "vp90-2-02-size-lf-1920x1080.webm"; +const char kVP9Md5File[] = "vp90-2-02-size-lf-1920x1080.webm.md5"; + +struct ByteAlignmentTestParam { + int byte_alignment; + vpx_codec_err_t expected_value; + bool decode_remaining; +}; + +const ByteAlignmentTestParam kBaTestParams[] = { + {kLegacyByteAlignment, VPX_CODEC_OK, true}, + {32, VPX_CODEC_OK, true}, + {64, VPX_CODEC_OK, true}, + {128, VPX_CODEC_OK, true}, + {256, VPX_CODEC_OK, true}, + {512, VPX_CODEC_OK, true}, + {1024, VPX_CODEC_OK, true}, + {1, VPX_CODEC_INVALID_PARAM, false}, + {-2, VPX_CODEC_INVALID_PARAM, false}, + {4, VPX_CODEC_INVALID_PARAM, false}, + {16, VPX_CODEC_INVALID_PARAM, false}, + {255, VPX_CODEC_INVALID_PARAM, false}, + {2048, VPX_CODEC_INVALID_PARAM, false}, +}; + +// Class for testing byte alignment of reference buffers. +class ByteAlignmentTest + : public ::testing::TestWithParam<ByteAlignmentTestParam> { + protected: + ByteAlignmentTest() + : video_(NULL), + decoder_(NULL), + md5_file_(NULL) {} + + virtual void SetUp() { + video_ = new libvpx_test::WebMVideoSource(kVP9TestFile); + ASSERT_TRUE(video_ != NULL); + video_->Init(); + video_->Begin(); + + const vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t(); + decoder_ = new libvpx_test::VP9Decoder(cfg, 0); + ASSERT_TRUE(decoder_ != NULL); + + OpenMd5File(kVP9Md5File); + } + + virtual void TearDown() { + if (md5_file_ != NULL) + fclose(md5_file_); + + delete decoder_; + delete video_; + } + + void SetByteAlignment(int byte_alignment, vpx_codec_err_t expected_value) { + decoder_->Control(VP9_SET_BYTE_ALIGNMENT, byte_alignment, expected_value); + } + + vpx_codec_err_t DecodeOneFrame(int byte_alignment_to_check) { + const vpx_codec_err_t res = + decoder_->DecodeFrame(video_->cxdata(), video_->frame_size()); + CheckDecodedFrames(byte_alignment_to_check); + if (res == VPX_CODEC_OK) + video_->Next(); + return res; + } + + vpx_codec_err_t DecodeRemainingFrames(int byte_alignment_to_check) { + for (; video_->cxdata() != NULL; video_->Next()) { + const vpx_codec_err_t res = + decoder_->DecodeFrame(video_->cxdata(), video_->frame_size()); + if (res != VPX_CODEC_OK) + return res; + CheckDecodedFrames(byte_alignment_to_check); + } + return VPX_CODEC_OK; + } + + private: + // Check if |data| is aligned to |byte_alignment_to_check|. + // |byte_alignment_to_check| must be a power of 2. + void CheckByteAlignment(const uint8_t *data, int byte_alignment_to_check) { + ASSERT_EQ(0u, reinterpret_cast<size_t>(data) % byte_alignment_to_check); + } + + // Iterate through the planes of the decoded frames and check for + // alignment based off |byte_alignment_to_check|. + void CheckDecodedFrames(int byte_alignment_to_check) { + libvpx_test::DxDataIterator dec_iter = decoder_->GetDxData(); + const vpx_image_t *img; + + // Get decompressed data + while ((img = dec_iter.Next()) != NULL) { + if (byte_alignment_to_check == kLegacyByteAlignment) { + CheckByteAlignment(img->planes[0], kLegacyYPlaneByteAlignment); + } else { + for (int i = 0; i < kNumPlanesToCheck; ++i) { + CheckByteAlignment(img->planes[i], byte_alignment_to_check); + } + } + CheckMd5(*img); + } + } + + // TODO(fgalligan): Move the MD5 testing code into another class. + void OpenMd5File(const std::string &md5_file_name_) { + md5_file_ = libvpx_test::OpenTestDataFile(md5_file_name_); + ASSERT_TRUE(md5_file_ != NULL) << "MD5 file open failed. Filename: " + << md5_file_name_; + } + + void CheckMd5(const vpx_image_t &img) { + ASSERT_TRUE(md5_file_ != NULL); + char expected_md5[33]; + char junk[128]; + + // Read correct md5 checksums. + const int res = fscanf(md5_file_, "%s %s", expected_md5, junk); + ASSERT_NE(EOF, res) << "Read md5 data failed"; + expected_md5[32] = '\0'; + + ::libvpx_test::MD5 md5_res; + md5_res.Add(&img); + const char *const actual_md5 = md5_res.Get(); + + // Check md5 match. + ASSERT_STREQ(expected_md5, actual_md5) << "MD5 checksums don't match"; + } + + libvpx_test::WebMVideoSource *video_; + libvpx_test::VP9Decoder *decoder_; + FILE *md5_file_; +}; + +TEST_F(ByteAlignmentTest, SwitchByteAlignment) { + const int num_elements = 14; + const int byte_alignments[] = { 0, 32, 64, 128, 256, 512, 1024, + 0, 1024, 32, 512, 64, 256, 128 }; + + for (int i = 0; i < num_elements; ++i) { + SetByteAlignment(byte_alignments[i], VPX_CODEC_OK); + ASSERT_EQ(VPX_CODEC_OK, DecodeOneFrame(byte_alignments[i])); + } + SetByteAlignment(byte_alignments[0], VPX_CODEC_OK); + ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames(byte_alignments[0])); +} + +TEST_P(ByteAlignmentTest, TestAlignment) { + const ByteAlignmentTestParam t = GetParam(); + SetByteAlignment(t.byte_alignment, t.expected_value); + if (t.decode_remaining) + ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames(t.byte_alignment)); +} + +INSTANTIATE_TEST_CASE_P(Alignments, ByteAlignmentTest, + ::testing::ValuesIn(kBaTestParams)); + +#endif // CONFIG_WEBM_IO + +} // namespace
diff --git a/src/third_party/libvpx/test/clear_system_state.h b/src/third_party/libvpx/test/clear_system_state.h new file mode 100644 index 0000000..5e76797 --- /dev/null +++ b/src/third_party/libvpx/test/clear_system_state.h
@@ -0,0 +1,29 @@ +/* + * Copyright (c) 2013 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#ifndef TEST_CLEAR_SYSTEM_STATE_H_ +#define TEST_CLEAR_SYSTEM_STATE_H_ + +#include "./vpx_config.h" +#if ARCH_X86 || ARCH_X86_64 +# include "vpx_ports/x86.h" +#endif + +namespace libvpx_test { + +// Reset system to a known state. This function should be used for all non-API +// test cases. +inline void ClearSystemState() { +#if ARCH_X86 || ARCH_X86_64 + vpx_reset_mmx_state(); +#endif +} + +} // namespace libvpx_test +#endif // TEST_CLEAR_SYSTEM_STATE_H_
diff --git a/src/third_party/libvpx/test/codec_factory.h b/src/third_party/libvpx/test/codec_factory.h new file mode 100644 index 0000000..09c9cf9 --- /dev/null +++ b/src/third_party/libvpx/test/codec_factory.h
@@ -0,0 +1,348 @@ +/* + * Copyright (c) 2013 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#ifndef TEST_CODEC_FACTORY_H_ +#define TEST_CODEC_FACTORY_H_ + +#include "./vpx_config.h" +#include "vpx/vpx_decoder.h" +#include "vpx/vpx_encoder.h" +#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER || CONFIG_VP10_ENCODER +#include "vpx/vp8cx.h" +#endif +#if CONFIG_VP8_DECODER || CONFIG_VP9_DECODER || CONFIG_VP10_DECODER +#include "vpx/vp8dx.h" +#endif + +#include "test/decode_test_driver.h" +#include "test/encode_test_driver.h" +namespace libvpx_test { + +const int kCodecFactoryParam = 0; + +class CodecFactory { + public: + CodecFactory() {} + + virtual ~CodecFactory() {} + + virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg, + unsigned long deadline) const = 0; + + virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg, + const vpx_codec_flags_t flags, + unsigned long deadline) // NOLINT(runtime/int) + const = 0; + + virtual Encoder* CreateEncoder(vpx_codec_enc_cfg_t cfg, + unsigned long deadline, + const unsigned long init_flags, + TwopassStatsStore *stats) const = 0; + + virtual vpx_codec_err_t DefaultEncoderConfig(vpx_codec_enc_cfg_t *cfg, + int usage) const = 0; +}; + +/* Provide CodecTestWith<n>Params classes for a variable number of parameters + * to avoid having to include a pointer to the CodecFactory in every test + * definition. + */ +template<class T1> +class CodecTestWithParam : public ::testing::TestWithParam< + std::tr1::tuple< const libvpx_test::CodecFactory*, T1 > > { +}; + +template<class T1, class T2> +class CodecTestWith2Params : public ::testing::TestWithParam< + std::tr1::tuple< const libvpx_test::CodecFactory*, T1, T2 > > { +}; + +template<class T1, class T2, class T3> +class CodecTestWith3Params : public ::testing::TestWithParam< + std::tr1::tuple< const libvpx_test::CodecFactory*, T1, T2, T3 > > { +}; + +/* + * VP8 Codec Definitions + */ +#if CONFIG_VP8 +class VP8Decoder : public Decoder { + public: + VP8Decoder(vpx_codec_dec_cfg_t cfg, unsigned long deadline) + : Decoder(cfg, deadline) {} + + VP8Decoder(vpx_codec_dec_cfg_t cfg, const vpx_codec_flags_t flag, + unsigned long deadline) // NOLINT + : Decoder(cfg, flag, deadline) {} + + protected: + virtual vpx_codec_iface_t* CodecInterface() const { +#if CONFIG_VP8_DECODER + return &vpx_codec_vp8_dx_algo; +#else + return NULL; +#endif + } +}; + +class VP8Encoder : public Encoder { + public: + VP8Encoder(vpx_codec_enc_cfg_t cfg, unsigned long deadline, + const unsigned long init_flags, TwopassStatsStore *stats) + : Encoder(cfg, deadline, init_flags, stats) {} + + protected: + virtual vpx_codec_iface_t* CodecInterface() const { +#if CONFIG_VP8_ENCODER + return &vpx_codec_vp8_cx_algo; +#else + return NULL; +#endif + } +}; + +class VP8CodecFactory : public CodecFactory { + public: + VP8CodecFactory() : CodecFactory() {} + + virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg, + unsigned long deadline) const { + return CreateDecoder(cfg, 0, deadline); + } + + virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg, + const vpx_codec_flags_t flags, + unsigned long deadline) const { // NOLINT +#if CONFIG_VP8_DECODER + return new VP8Decoder(cfg, flags, deadline); +#else + return NULL; +#endif + } + + virtual Encoder* CreateEncoder(vpx_codec_enc_cfg_t cfg, + unsigned long deadline, + const unsigned long init_flags, + TwopassStatsStore *stats) const { +#if CONFIG_VP8_ENCODER + return new VP8Encoder(cfg, deadline, init_flags, stats); +#else + return NULL; +#endif + } + + virtual vpx_codec_err_t DefaultEncoderConfig(vpx_codec_enc_cfg_t *cfg, + int usage) const { +#if CONFIG_VP8_ENCODER + return vpx_codec_enc_config_default(&vpx_codec_vp8_cx_algo, cfg, usage); +#else + return VPX_CODEC_INCAPABLE; +#endif + } +}; + +const libvpx_test::VP8CodecFactory kVP8; + +#define VP8_INSTANTIATE_TEST_CASE(test, ...)\ + INSTANTIATE_TEST_CASE_P(VP8, test, \ + ::testing::Combine( \ + ::testing::Values(static_cast<const libvpx_test::CodecFactory*>( \ + &libvpx_test::kVP8)), \ + __VA_ARGS__)) +#else +#define VP8_INSTANTIATE_TEST_CASE(test, ...) +#endif // CONFIG_VP8 + + +/* + * VP9 Codec Definitions + */ +#if CONFIG_VP9 +class VP9Decoder : public Decoder { + public: + VP9Decoder(vpx_codec_dec_cfg_t cfg, unsigned long deadline) + : Decoder(cfg, deadline) {} + + VP9Decoder(vpx_codec_dec_cfg_t cfg, const vpx_codec_flags_t flag, + unsigned long deadline) // NOLINT + : Decoder(cfg, flag, deadline) {} + + protected: + virtual vpx_codec_iface_t* CodecInterface() const { +#if CONFIG_VP9_DECODER + return &vpx_codec_vp9_dx_algo; +#else + return NULL; +#endif + } +}; + +class VP9Encoder : public Encoder { + public: + VP9Encoder(vpx_codec_enc_cfg_t cfg, unsigned long deadline, + const unsigned long init_flags, TwopassStatsStore *stats) + : Encoder(cfg, deadline, init_flags, stats) {} + + protected: + virtual vpx_codec_iface_t* CodecInterface() const { +#if CONFIG_VP9_ENCODER + return &vpx_codec_vp9_cx_algo; +#else + return NULL; +#endif + } +}; + +class VP9CodecFactory : public CodecFactory { + public: + VP9CodecFactory() : CodecFactory() {} + + virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg, + unsigned long deadline) const { + return CreateDecoder(cfg, 0, deadline); + } + + virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg, + const vpx_codec_flags_t flags, + unsigned long deadline) const { // NOLINT +#if CONFIG_VP9_DECODER + return new VP9Decoder(cfg, flags, deadline); +#else + return NULL; +#endif + } + + virtual Encoder* CreateEncoder(vpx_codec_enc_cfg_t cfg, + unsigned long deadline, + const unsigned long init_flags, + TwopassStatsStore *stats) const { +#if CONFIG_VP9_ENCODER + return new VP9Encoder(cfg, deadline, init_flags, stats); +#else + return NULL; +#endif + } + + virtual vpx_codec_err_t DefaultEncoderConfig(vpx_codec_enc_cfg_t *cfg, + int usage) const { +#if CONFIG_VP9_ENCODER + return vpx_codec_enc_config_default(&vpx_codec_vp9_cx_algo, cfg, usage); +#elif CONFIG_VP10_ENCODER + return vpx_codec_enc_config_default(&vpx_codec_vp10_cx_algo, cfg, usage); +#else + return VPX_CODEC_INCAPABLE; +#endif + } +}; + +const libvpx_test::VP9CodecFactory kVP9; + +#define VP9_INSTANTIATE_TEST_CASE(test, ...)\ + INSTANTIATE_TEST_CASE_P(VP9, test, \ + ::testing::Combine( \ + ::testing::Values(static_cast<const libvpx_test::CodecFactory*>( \ + &libvpx_test::kVP9)), \ + __VA_ARGS__)) +#else +#define VP9_INSTANTIATE_TEST_CASE(test, ...) +#endif // CONFIG_VP9 + +/* + * VP10 Codec Definitions + */ +#if CONFIG_VP10 +class VP10Decoder : public Decoder { + public: + VP10Decoder(vpx_codec_dec_cfg_t cfg, unsigned long deadline) + : Decoder(cfg, deadline) {} + + VP10Decoder(vpx_codec_dec_cfg_t cfg, const vpx_codec_flags_t flag, + unsigned long deadline) // NOLINT + : Decoder(cfg, flag, deadline) {} + + protected: + virtual vpx_codec_iface_t* CodecInterface() const { +#if CONFIG_VP10_DECODER + return &vpx_codec_vp10_dx_algo; +#else + return NULL; +#endif + } +}; + +class VP10Encoder : public Encoder { + public: + VP10Encoder(vpx_codec_enc_cfg_t cfg, unsigned long deadline, + const unsigned long init_flags, TwopassStatsStore *stats) + : Encoder(cfg, deadline, init_flags, stats) {} + + protected: + virtual vpx_codec_iface_t* CodecInterface() const { +#if CONFIG_VP10_ENCODER + return &vpx_codec_vp10_cx_algo; +#else + return NULL; +#endif + } +}; + +class VP10CodecFactory : public CodecFactory { + public: + VP10CodecFactory() : CodecFactory() {} + + virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg, + unsigned long deadline) const { + return CreateDecoder(cfg, 0, deadline); + } + + virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg, + const vpx_codec_flags_t flags, + unsigned long deadline) const { // NOLINT +#if CONFIG_VP10_DECODER + return new VP10Decoder(cfg, flags, deadline); +#else + return NULL; +#endif + } + + virtual Encoder* CreateEncoder(vpx_codec_enc_cfg_t cfg, + unsigned long deadline, + const unsigned long init_flags, + TwopassStatsStore *stats) const { +#if CONFIG_VP10_ENCODER + return new VP10Encoder(cfg, deadline, init_flags, stats); +#else + return NULL; +#endif + } + + virtual vpx_codec_err_t DefaultEncoderConfig(vpx_codec_enc_cfg_t *cfg, + int usage) const { +#if CONFIG_VP10_ENCODER + return vpx_codec_enc_config_default(&vpx_codec_vp10_cx_algo, cfg, usage); +#else + return VPX_CODEC_INCAPABLE; +#endif + } +}; + +const libvpx_test::VP10CodecFactory kVP10; + +#define VP10_INSTANTIATE_TEST_CASE(test, ...)\ + INSTANTIATE_TEST_CASE_P(VP10, test, \ + ::testing::Combine( \ + ::testing::Values(static_cast<const libvpx_test::CodecFactory*>( \ + &libvpx_test::kVP10)), \ + __VA_ARGS__)) +#else +#define VP10_INSTANTIATE_TEST_CASE(test, ...) +#endif // CONFIG_VP10 + +} // namespace libvpx_test +#endif // TEST_CODEC_FACTORY_H_
diff --git a/src/third_party/libvpx/test/config_test.cc b/src/third_party/libvpx/test/config_test.cc new file mode 100644 index 0000000..0493110 --- /dev/null +++ b/src/third_party/libvpx/test/config_test.cc
@@ -0,0 +1,60 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "test/codec_factory.h" +#include "test/encode_test_driver.h" +#include "test/util.h" +#include "test/video_source.h" + +namespace { + +class ConfigTest : public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> { + protected: + ConfigTest() : EncoderTest(GET_PARAM(0)), + frame_count_in_(0), frame_count_out_(0), frame_count_max_(0) {} + virtual ~ConfigTest() {} + + virtual void SetUp() { + InitializeConfig(); + SetMode(GET_PARAM(1)); + } + + virtual void BeginPassHook(unsigned int /*pass*/) { + frame_count_in_ = 0; + frame_count_out_ = 0; + } + + virtual void PreEncodeFrameHook(libvpx_test::VideoSource* /*video*/) { + ++frame_count_in_; + abort_ |= (frame_count_in_ >= frame_count_max_); + } + + virtual void FramePktHook(const vpx_codec_cx_pkt_t* /*pkt*/) { + ++frame_count_out_; + } + + unsigned int frame_count_in_; + unsigned int frame_count_out_; + unsigned int frame_count_max_; +}; + +TEST_P(ConfigTest, LagIsDisabled) { + frame_count_max_ = 2; + cfg_.g_lag_in_frames = 15; + + libvpx_test::DummyVideoSource video; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + + EXPECT_EQ(frame_count_in_, frame_count_out_); +} + +VP8_INSTANTIATE_TEST_CASE(ConfigTest, ONE_PASS_TEST_MODES); +} // namespace
diff --git a/src/third_party/libvpx/test/consistency_test.cc b/src/third_party/libvpx/test/consistency_test.cc new file mode 100644 index 0000000..9c2fd55 --- /dev/null +++ b/src/third_party/libvpx/test/consistency_test.cc
@@ -0,0 +1,224 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <limits.h> +#include <stdio.h> +#include <string.h> + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "./vpx_config.h" +#if CONFIG_VP9_ENCODER +#include "./vp9_rtcd.h" +#endif + +#include "test/acm_random.h" +#include "test/clear_system_state.h" +#include "test/register_state_check.h" +#include "test/util.h" +#include "vpx_dsp/ssim.h" +#include "vpx_mem/vpx_mem.h" + +extern "C" +double vpx_get_ssim_metrics(uint8_t *img1, int img1_pitch, + uint8_t *img2, int img2_pitch, + int width, int height, + Ssimv *sv2, Metrics *m, + int do_inconsistency); + +using libvpx_test::ACMRandom; + +namespace { +class ConsistencyTestBase : public ::testing::Test { + public: + ConsistencyTestBase(int width, int height) : width_(width), height_(height) {} + + static void SetUpTestCase() { + source_data_[0] = reinterpret_cast<uint8_t*>( + vpx_memalign(kDataAlignment, kDataBufferSize)); + reference_data_[0] = reinterpret_cast<uint8_t*>( + vpx_memalign(kDataAlignment, kDataBufferSize)); + source_data_[1] = reinterpret_cast<uint8_t*>( + vpx_memalign(kDataAlignment, kDataBufferSize)); + reference_data_[1] = reinterpret_cast<uint8_t*>( + vpx_memalign(kDataAlignment, kDataBufferSize)); + ssim_array_ = new Ssimv[kDataBufferSize / 16]; + } + + static void ClearSsim() { + memset(ssim_array_, 0, kDataBufferSize / 16); + } + static void TearDownTestCase() { + vpx_free(source_data_[0]); + source_data_[0] = NULL; + vpx_free(reference_data_[0]); + reference_data_[0] = NULL; + vpx_free(source_data_[1]); + source_data_[1] = NULL; + vpx_free(reference_data_[1]); + reference_data_[1] = NULL; + + delete[] ssim_array_; + } + + virtual void TearDown() { + libvpx_test::ClearSystemState(); + } + + protected: + // Handle frames up to 640x480 + static const int kDataAlignment = 16; + static const int kDataBufferSize = 640*480; + + virtual void SetUp() { + source_stride_ = (width_ + 31) & ~31; + reference_stride_ = width_ * 2; + rnd_.Reset(ACMRandom::DeterministicSeed()); + } + + void FillRandom(uint8_t *data, int stride, int width, int height) { + for (int h = 0; h < height; ++h) { + for (int w = 0; w < width; ++w) { + data[h * stride + w] = rnd_.Rand8(); + } + } + } + + void FillRandom(uint8_t *data, int stride) { + FillRandom(data, stride, width_, height_); + } + + void Copy(uint8_t *reference, uint8_t *source) { + memcpy(reference, source, kDataBufferSize); + } + + void Blur(uint8_t *data, int stride, int taps) { + int sum = 0; + int half_taps = taps / 2; + for (int h = 0; h < height_; ++h) { + for (int w = 0; w < taps; ++w) { + sum += data[w + h * stride]; + } + for (int w = taps; w < width_; ++w) { + sum += data[w + h * stride] - data[w - taps + h * stride]; + data[w - half_taps + h * stride] = (sum + half_taps) / taps; + } + } + for (int w = 0; w < width_; ++w) { + for (int h = 0; h < taps; ++h) { + sum += data[h + w * stride]; + } + for (int h = taps; h < height_; ++h) { + sum += data[w + h * stride] - data[(h - taps) * stride + w]; + data[(h - half_taps) * stride + w] = (sum + half_taps) / taps; + } + } + } + int width_, height_; + static uint8_t* source_data_[2]; + int source_stride_; + static uint8_t* reference_data_[2]; + int reference_stride_; + static Ssimv *ssim_array_; + Metrics metrics_; + + ACMRandom rnd_; +}; + +#if CONFIG_VP9_ENCODER +typedef std::tr1::tuple<int, int> ConsistencyParam; +class ConsistencyVP9Test + : public ConsistencyTestBase, + public ::testing::WithParamInterface<ConsistencyParam> { + public: + ConsistencyVP9Test() : ConsistencyTestBase(GET_PARAM(0), GET_PARAM(1)) {} + + protected: + double CheckConsistency(int frame) { + EXPECT_LT(frame, 2)<< "Frame to check has to be less than 2."; + return + vpx_get_ssim_metrics(source_data_[frame], source_stride_, + reference_data_[frame], reference_stride_, + width_, height_, ssim_array_, &metrics_, 1); + } +}; +#endif // CONFIG_VP9_ENCODER + +uint8_t* ConsistencyTestBase::source_data_[2] = {NULL, NULL}; +uint8_t* ConsistencyTestBase::reference_data_[2] = {NULL, NULL}; +Ssimv* ConsistencyTestBase::ssim_array_ = NULL; + +#if CONFIG_VP9_ENCODER +TEST_P(ConsistencyVP9Test, ConsistencyIsZero) { + FillRandom(source_data_[0], source_stride_); + Copy(source_data_[1], source_data_[0]); + Copy(reference_data_[0], source_data_[0]); + Blur(reference_data_[0], reference_stride_, 3); + Copy(reference_data_[1], source_data_[0]); + Blur(reference_data_[1], reference_stride_, 3); + + double inconsistency = CheckConsistency(1); + inconsistency = CheckConsistency(0); + EXPECT_EQ(inconsistency, 0.0) + << "Should have 0 inconsistency if they are exactly the same."; + + // If sources are not consistent reference frames inconsistency should + // be less than if the source is consistent. + FillRandom(source_data_[0], source_stride_); + FillRandom(source_data_[1], source_stride_); + FillRandom(reference_data_[0], reference_stride_); + FillRandom(reference_data_[1], reference_stride_); + CheckConsistency(0); + inconsistency = CheckConsistency(1); + + Copy(source_data_[1], source_data_[0]); + CheckConsistency(0); + double inconsistency2 = CheckConsistency(1); + EXPECT_LT(inconsistency, inconsistency2) + << "Should have less inconsistency if source itself is inconsistent."; + + // Less of a blur should be less inconsistent than more blur coming off a + // a frame with no blur. + ClearSsim(); + FillRandom(source_data_[0], source_stride_); + Copy(source_data_[1], source_data_[0]); + Copy(reference_data_[0], source_data_[0]); + Copy(reference_data_[1], source_data_[0]); + Blur(reference_data_[1], reference_stride_, 4); + CheckConsistency(0); + inconsistency = CheckConsistency(1); + ClearSsim(); + Copy(reference_data_[1], source_data_[0]); + Blur(reference_data_[1], reference_stride_, 8); + CheckConsistency(0); + inconsistency2 = CheckConsistency(1); + + EXPECT_LT(inconsistency, inconsistency2) + << "Stronger Blur should produce more inconsistency."; +} +#endif // CONFIG_VP9_ENCODER + + +using std::tr1::make_tuple; + +//------------------------------------------------------------------------------ +// C functions + +#if CONFIG_VP9_ENCODER +const ConsistencyParam c_vp9_tests[] = { + make_tuple(320, 240), + make_tuple(318, 242), + make_tuple(318, 238), +}; +INSTANTIATE_TEST_CASE_P(C, ConsistencyVP9Test, + ::testing::ValuesIn(c_vp9_tests)); +#endif + +} // namespace
diff --git a/src/third_party/libvpx/test/convolve_test.cc b/src/third_party/libvpx/test/convolve_test.cc new file mode 100644 index 0000000..73b0edb --- /dev/null +++ b/src/third_party/libvpx/test/convolve_test.cc
@@ -0,0 +1,1238 @@ +/* + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <string.h> + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "./vpx_config.h" +#include "./vp9_rtcd.h" +#include "./vpx_dsp_rtcd.h" +#include "test/acm_random.h" +#include "test/clear_system_state.h" +#include "test/register_state_check.h" +#include "test/util.h" +#include "vp9/common/vp9_common.h" +#include "vp9/common/vp9_filter.h" +#include "vpx_dsp/vpx_dsp_common.h" +#include "vpx_dsp/vpx_filter.h" +#include "vpx_mem/vpx_mem.h" +#include "vpx_ports/mem.h" + +namespace { + +static const unsigned int kMaxDimension = 64; + +typedef void (*ConvolveFunc)(const uint8_t *src, ptrdiff_t src_stride, + uint8_t *dst, ptrdiff_t dst_stride, + const int16_t *filter_x, int filter_x_stride, + const int16_t *filter_y, int filter_y_stride, + int w, int h); + +struct ConvolveFunctions { + ConvolveFunctions(ConvolveFunc copy, ConvolveFunc avg, + ConvolveFunc h8, ConvolveFunc h8_avg, + ConvolveFunc v8, ConvolveFunc v8_avg, + ConvolveFunc hv8, ConvolveFunc hv8_avg, + ConvolveFunc sh8, ConvolveFunc sh8_avg, + ConvolveFunc sv8, ConvolveFunc sv8_avg, + ConvolveFunc shv8, ConvolveFunc shv8_avg, + int bd) + : copy_(copy), avg_(avg), h8_(h8), v8_(v8), hv8_(hv8), h8_avg_(h8_avg), + v8_avg_(v8_avg), hv8_avg_(hv8_avg), sh8_(sh8), sv8_(sv8), shv8_(shv8), + sh8_avg_(sh8_avg), sv8_avg_(sv8_avg), shv8_avg_(shv8_avg), + use_highbd_(bd) {} + + ConvolveFunc copy_; + ConvolveFunc avg_; + ConvolveFunc h8_; + ConvolveFunc v8_; + ConvolveFunc hv8_; + ConvolveFunc h8_avg_; + ConvolveFunc v8_avg_; + ConvolveFunc hv8_avg_; + ConvolveFunc sh8_; // scaled horiz + ConvolveFunc sv8_; // scaled vert + ConvolveFunc shv8_; // scaled horiz/vert + ConvolveFunc sh8_avg_; // scaled avg horiz + ConvolveFunc sv8_avg_; // scaled avg vert + ConvolveFunc shv8_avg_; // scaled avg horiz/vert + int use_highbd_; // 0 if high bitdepth not used, else the actual bit depth. +}; + +typedef std::tr1::tuple<int, int, const ConvolveFunctions *> ConvolveParam; + +#define ALL_SIZES(convolve_fn) \ + make_tuple(4, 4, &convolve_fn), \ + make_tuple(8, 4, &convolve_fn), \ + make_tuple(4, 8, &convolve_fn), \ + make_tuple(8, 8, &convolve_fn), \ + make_tuple(16, 8, &convolve_fn), \ + make_tuple(8, 16, &convolve_fn), \ + make_tuple(16, 16, &convolve_fn), \ + make_tuple(32, 16, &convolve_fn), \ + make_tuple(16, 32, &convolve_fn), \ + make_tuple(32, 32, &convolve_fn), \ + make_tuple(64, 32, &convolve_fn), \ + make_tuple(32, 64, &convolve_fn), \ + make_tuple(64, 64, &convolve_fn) + +// Reference 8-tap subpixel filter, slightly modified to fit into this test. +#define VP9_FILTER_WEIGHT 128 +#define VP9_FILTER_SHIFT 7 +uint8_t clip_pixel(int x) { + return x < 0 ? 0 : + x > 255 ? 255 : + x; +} + +void filter_block2d_8_c(const uint8_t *src_ptr, + const unsigned int src_stride, + const int16_t *HFilter, + const int16_t *VFilter, + uint8_t *dst_ptr, + unsigned int dst_stride, + unsigned int output_width, + unsigned int output_height) { + // Between passes, we use an intermediate buffer whose height is extended to + // have enough horizontally filtered values as input for the vertical pass. + // This buffer is allocated to be big enough for the largest block type we + // support. + const int kInterp_Extend = 4; + const unsigned int intermediate_height = + (kInterp_Extend - 1) + output_height + kInterp_Extend; + unsigned int i, j; + + // Size of intermediate_buffer is max_intermediate_height * filter_max_width, + // where max_intermediate_height = (kInterp_Extend - 1) + filter_max_height + // + kInterp_Extend + // = 3 + 16 + 4 + // = 23 + // and filter_max_width = 16 + // + uint8_t intermediate_buffer[71 * kMaxDimension]; + const int intermediate_next_stride = + 1 - static_cast<int>(intermediate_height * output_width); + + // Horizontal pass (src -> transposed intermediate). + uint8_t *output_ptr = intermediate_buffer; + const int src_next_row_stride = src_stride - output_width; + src_ptr -= (kInterp_Extend - 1) * src_stride + (kInterp_Extend - 1); + for (i = 0; i < intermediate_height; ++i) { + for (j = 0; j < output_width; ++j) { + // Apply filter... + const int temp = (src_ptr[0] * HFilter[0]) + + (src_ptr[1] * HFilter[1]) + + (src_ptr[2] * HFilter[2]) + + (src_ptr[3] * HFilter[3]) + + (src_ptr[4] * HFilter[4]) + + (src_ptr[5] * HFilter[5]) + + (src_ptr[6] * HFilter[6]) + + (src_ptr[7] * HFilter[7]) + + (VP9_FILTER_WEIGHT >> 1); // Rounding + + // Normalize back to 0-255... + *output_ptr = clip_pixel(temp >> VP9_FILTER_SHIFT); + ++src_ptr; + output_ptr += intermediate_height; + } + src_ptr += src_next_row_stride; + output_ptr += intermediate_next_stride; + } + + // Vertical pass (transposed intermediate -> dst). + src_ptr = intermediate_buffer; + const int dst_next_row_stride = dst_stride - output_width; + for (i = 0; i < output_height; ++i) { + for (j = 0; j < output_width; ++j) { + // Apply filter... + const int temp = (src_ptr[0] * VFilter[0]) + + (src_ptr[1] * VFilter[1]) + + (src_ptr[2] * VFilter[2]) + + (src_ptr[3] * VFilter[3]) + + (src_ptr[4] * VFilter[4]) + + (src_ptr[5] * VFilter[5]) + + (src_ptr[6] * VFilter[6]) + + (src_ptr[7] * VFilter[7]) + + (VP9_FILTER_WEIGHT >> 1); // Rounding + + // Normalize back to 0-255... + *dst_ptr++ = clip_pixel(temp >> VP9_FILTER_SHIFT); + src_ptr += intermediate_height; + } + src_ptr += intermediate_next_stride; + dst_ptr += dst_next_row_stride; + } +} + +void block2d_average_c(uint8_t *src, + unsigned int src_stride, + uint8_t *output_ptr, + unsigned int output_stride, + unsigned int output_width, + unsigned int output_height) { + unsigned int i, j; + for (i = 0; i < output_height; ++i) { + for (j = 0; j < output_width; ++j) { + output_ptr[j] = (output_ptr[j] + src[i * src_stride + j] + 1) >> 1; + } + output_ptr += output_stride; + } +} + +void filter_average_block2d_8_c(const uint8_t *src_ptr, + const unsigned int src_stride, + const int16_t *HFilter, + const int16_t *VFilter, + uint8_t *dst_ptr, + unsigned int dst_stride, + unsigned int output_width, + unsigned int output_height) { + uint8_t tmp[kMaxDimension * kMaxDimension]; + + assert(output_width <= kMaxDimension); + assert(output_height <= kMaxDimension); + filter_block2d_8_c(src_ptr, src_stride, HFilter, VFilter, tmp, 64, + output_width, output_height); + block2d_average_c(tmp, 64, dst_ptr, dst_stride, + output_width, output_height); +} + +#if CONFIG_VP9_HIGHBITDEPTH +void highbd_filter_block2d_8_c(const uint16_t *src_ptr, + const unsigned int src_stride, + const int16_t *HFilter, + const int16_t *VFilter, + uint16_t *dst_ptr, + unsigned int dst_stride, + unsigned int output_width, + unsigned int output_height, + int bd) { + // Between passes, we use an intermediate buffer whose height is extended to + // have enough horizontally filtered values as input for the vertical pass. + // This buffer is allocated to be big enough for the largest block type we + // support. + const int kInterp_Extend = 4; + const unsigned int intermediate_height = + (kInterp_Extend - 1) + output_height + kInterp_Extend; + + /* Size of intermediate_buffer is max_intermediate_height * filter_max_width, + * where max_intermediate_height = (kInterp_Extend - 1) + filter_max_height + * + kInterp_Extend + * = 3 + 16 + 4 + * = 23 + * and filter_max_width = 16 + */ + uint16_t intermediate_buffer[71 * kMaxDimension]; + const int intermediate_next_stride = + 1 - static_cast<int>(intermediate_height * output_width); + + // Horizontal pass (src -> transposed intermediate). + { + uint16_t *output_ptr = intermediate_buffer; + const int src_next_row_stride = src_stride - output_width; + unsigned int i, j; + src_ptr -= (kInterp_Extend - 1) * src_stride + (kInterp_Extend - 1); + for (i = 0; i < intermediate_height; ++i) { + for (j = 0; j < output_width; ++j) { + // Apply filter... + const int temp = (src_ptr[0] * HFilter[0]) + + (src_ptr[1] * HFilter[1]) + + (src_ptr[2] * HFilter[2]) + + (src_ptr[3] * HFilter[3]) + + (src_ptr[4] * HFilter[4]) + + (src_ptr[5] * HFilter[5]) + + (src_ptr[6] * HFilter[6]) + + (src_ptr[7] * HFilter[7]) + + (VP9_FILTER_WEIGHT >> 1); // Rounding + + // Normalize back to 0-255... + *output_ptr = clip_pixel_highbd(temp >> VP9_FILTER_SHIFT, bd); + ++src_ptr; + output_ptr += intermediate_height; + } + src_ptr += src_next_row_stride; + output_ptr += intermediate_next_stride; + } + } + + // Vertical pass (transposed intermediate -> dst). + { + uint16_t *src_ptr = intermediate_buffer; + const int dst_next_row_stride = dst_stride - output_width; + unsigned int i, j; + for (i = 0; i < output_height; ++i) { + for (j = 0; j < output_width; ++j) { + // Apply filter... + const int temp = (src_ptr[0] * VFilter[0]) + + (src_ptr[1] * VFilter[1]) + + (src_ptr[2] * VFilter[2]) + + (src_ptr[3] * VFilter[3]) + + (src_ptr[4] * VFilter[4]) + + (src_ptr[5] * VFilter[5]) + + (src_ptr[6] * VFilter[6]) + + (src_ptr[7] * VFilter[7]) + + (VP9_FILTER_WEIGHT >> 1); // Rounding + + // Normalize back to 0-255... + *dst_ptr++ = clip_pixel_highbd(temp >> VP9_FILTER_SHIFT, bd); + src_ptr += intermediate_height; + } + src_ptr += intermediate_next_stride; + dst_ptr += dst_next_row_stride; + } + } +} + +void highbd_block2d_average_c(uint16_t *src, + unsigned int src_stride, + uint16_t *output_ptr, + unsigned int output_stride, + unsigned int output_width, + unsigned int output_height) { + unsigned int i, j; + for (i = 0; i < output_height; ++i) { + for (j = 0; j < output_width; ++j) { + output_ptr[j] = (output_ptr[j] + src[i * src_stride + j] + 1) >> 1; + } + output_ptr += output_stride; + } +} + +void highbd_filter_average_block2d_8_c(const uint16_t *src_ptr, + const unsigned int src_stride, + const int16_t *HFilter, + const int16_t *VFilter, + uint16_t *dst_ptr, + unsigned int dst_stride, + unsigned int output_width, + unsigned int output_height, + int bd) { + uint16_t tmp[kMaxDimension * kMaxDimension]; + + assert(output_width <= kMaxDimension); + assert(output_height <= kMaxDimension); + highbd_filter_block2d_8_c(src_ptr, src_stride, HFilter, VFilter, tmp, 64, + output_width, output_height, bd); + highbd_block2d_average_c(tmp, 64, dst_ptr, dst_stride, + output_width, output_height); +} +#endif // CONFIG_VP9_HIGHBITDEPTH + +class ConvolveTest : public ::testing::TestWithParam<ConvolveParam> { + public: + static void SetUpTestCase() { + // Force input_ to be unaligned, output to be 16 byte aligned. + input_ = reinterpret_cast<uint8_t*>( + vpx_memalign(kDataAlignment, kInputBufferSize + 1)) + 1; + output_ = reinterpret_cast<uint8_t*>( + vpx_memalign(kDataAlignment, kOutputBufferSize)); + output_ref_ = reinterpret_cast<uint8_t*>( + vpx_memalign(kDataAlignment, kOutputBufferSize)); +#if CONFIG_VP9_HIGHBITDEPTH + input16_ = reinterpret_cast<uint16_t*>( + vpx_memalign(kDataAlignment, + (kInputBufferSize + 1) * sizeof(uint16_t))) + 1; + output16_ = reinterpret_cast<uint16_t*>( + vpx_memalign(kDataAlignment, (kOutputBufferSize) * sizeof(uint16_t))); + output16_ref_ = reinterpret_cast<uint16_t*>( + vpx_memalign(kDataAlignment, (kOutputBufferSize) * sizeof(uint16_t))); +#endif + } + + virtual void TearDown() { libvpx_test::ClearSystemState(); } + + static void TearDownTestCase() { + vpx_free(input_ - 1); + input_ = NULL; + vpx_free(output_); + output_ = NULL; + vpx_free(output_ref_); + output_ref_ = NULL; +#if CONFIG_VP9_HIGHBITDEPTH + vpx_free(input16_ - 1); + input16_ = NULL; + vpx_free(output16_); + output16_ = NULL; + vpx_free(output16_ref_); + output16_ref_ = NULL; +#endif + } + + protected: + static const int kDataAlignment = 16; + static const int kOuterBlockSize = 256; + static const int kInputStride = kOuterBlockSize; + static const int kOutputStride = kOuterBlockSize; + static const int kInputBufferSize = kOuterBlockSize * kOuterBlockSize; + static const int kOutputBufferSize = kOuterBlockSize * kOuterBlockSize; + + int Width() const { return GET_PARAM(0); } + int Height() const { return GET_PARAM(1); } + int BorderLeft() const { + const int center = (kOuterBlockSize - Width()) / 2; + return (center + (kDataAlignment - 1)) & ~(kDataAlignment - 1); + } + int BorderTop() const { return (kOuterBlockSize - Height()) / 2; } + + bool IsIndexInBorder(int i) { + return (i < BorderTop() * kOuterBlockSize || + i >= (BorderTop() + Height()) * kOuterBlockSize || + i % kOuterBlockSize < BorderLeft() || + i % kOuterBlockSize >= (BorderLeft() + Width())); + } + + virtual void SetUp() { + UUT_ = GET_PARAM(2); +#if CONFIG_VP9_HIGHBITDEPTH + if (UUT_->use_highbd_ != 0) + mask_ = (1 << UUT_->use_highbd_) - 1; + else + mask_ = 255; +#endif + /* Set up guard blocks for an inner block centered in the outer block */ + for (int i = 0; i < kOutputBufferSize; ++i) { + if (IsIndexInBorder(i)) + output_[i] = 255; + else + output_[i] = 0; + } + + ::libvpx_test::ACMRandom prng; + for (int i = 0; i < kInputBufferSize; ++i) { + if (i & 1) { + input_[i] = 255; +#if CONFIG_VP9_HIGHBITDEPTH + input16_[i] = mask_; +#endif + } else { + input_[i] = prng.Rand8Extremes(); +#if CONFIG_VP9_HIGHBITDEPTH + input16_[i] = prng.Rand16() & mask_; +#endif + } + } + } + + void SetConstantInput(int value) { + memset(input_, value, kInputBufferSize); +#if CONFIG_VP9_HIGHBITDEPTH + vpx_memset16(input16_, value, kInputBufferSize); +#endif + } + + void CopyOutputToRef() { + memcpy(output_ref_, output_, kOutputBufferSize); +#if CONFIG_VP9_HIGHBITDEPTH + memcpy(output16_ref_, output16_, kOutputBufferSize); +#endif + } + + void CheckGuardBlocks() { + for (int i = 0; i < kOutputBufferSize; ++i) { + if (IsIndexInBorder(i)) + EXPECT_EQ(255, output_[i]); + } + } + + uint8_t *input() const { +#if CONFIG_VP9_HIGHBITDEPTH + if (UUT_->use_highbd_ == 0) { + return input_ + BorderTop() * kOuterBlockSize + BorderLeft(); + } else { + return CONVERT_TO_BYTEPTR(input16_ + BorderTop() * kOuterBlockSize + + BorderLeft()); + } +#else + return input_ + BorderTop() * kOuterBlockSize + BorderLeft(); +#endif + } + + uint8_t *output() const { +#if CONFIG_VP9_HIGHBITDEPTH + if (UUT_->use_highbd_ == 0) { + return output_ + BorderTop() * kOuterBlockSize + BorderLeft(); + } else { + return CONVERT_TO_BYTEPTR(output16_ + BorderTop() * kOuterBlockSize + + BorderLeft()); + } +#else + return output_ + BorderTop() * kOuterBlockSize + BorderLeft(); +#endif + } + + uint8_t *output_ref() const { +#if CONFIG_VP9_HIGHBITDEPTH + if (UUT_->use_highbd_ == 0) { + return output_ref_ + BorderTop() * kOuterBlockSize + BorderLeft(); + } else { + return CONVERT_TO_BYTEPTR(output16_ref_ + BorderTop() * kOuterBlockSize + + BorderLeft()); + } +#else + return output_ref_ + BorderTop() * kOuterBlockSize + BorderLeft(); +#endif + } + + uint16_t lookup(uint8_t *list, int index) const { +#if CONFIG_VP9_HIGHBITDEPTH + if (UUT_->use_highbd_ == 0) { + return list[index]; + } else { + return CONVERT_TO_SHORTPTR(list)[index]; + } +#else + return list[index]; +#endif + } + + void assign_val(uint8_t *list, int index, uint16_t val) const { +#if CONFIG_VP9_HIGHBITDEPTH + if (UUT_->use_highbd_ == 0) { + list[index] = (uint8_t) val; + } else { + CONVERT_TO_SHORTPTR(list)[index] = val; + } +#else + list[index] = (uint8_t) val; +#endif + } + + void wrapper_filter_average_block2d_8_c(const uint8_t *src_ptr, + const unsigned int src_stride, + const int16_t *HFilter, + const int16_t *VFilter, + uint8_t *dst_ptr, + unsigned int dst_stride, + unsigned int output_width, + unsigned int output_height) { +#if CONFIG_VP9_HIGHBITDEPTH + if (UUT_->use_highbd_ == 0) { + filter_average_block2d_8_c(src_ptr, src_stride, HFilter, VFilter, + dst_ptr, dst_stride, output_width, + output_height); + } else { + highbd_filter_average_block2d_8_c(CONVERT_TO_SHORTPTR(src_ptr), + src_stride, HFilter, VFilter, + CONVERT_TO_SHORTPTR(dst_ptr), + dst_stride, output_width, output_height, + UUT_->use_highbd_); + } +#else + filter_average_block2d_8_c(src_ptr, src_stride, HFilter, VFilter, + dst_ptr, dst_stride, output_width, + output_height); +#endif + } + + void wrapper_filter_block2d_8_c(const uint8_t *src_ptr, + const unsigned int src_stride, + const int16_t *HFilter, + const int16_t *VFilter, + uint8_t *dst_ptr, + unsigned int dst_stride, + unsigned int output_width, + unsigned int output_height) { +#if CONFIG_VP9_HIGHBITDEPTH + if (UUT_->use_highbd_ == 0) { + filter_block2d_8_c(src_ptr, src_stride, HFilter, VFilter, + dst_ptr, dst_stride, output_width, output_height); + } else { + highbd_filter_block2d_8_c(CONVERT_TO_SHORTPTR(src_ptr), src_stride, + HFilter, VFilter, + CONVERT_TO_SHORTPTR(dst_ptr), dst_stride, + output_width, output_height, UUT_->use_highbd_); + } +#else + filter_block2d_8_c(src_ptr, src_stride, HFilter, VFilter, + dst_ptr, dst_stride, output_width, output_height); +#endif + } + + const ConvolveFunctions* UUT_; + static uint8_t* input_; + static uint8_t* output_; + static uint8_t* output_ref_; +#if CONFIG_VP9_HIGHBITDEPTH + static uint16_t* input16_; + static uint16_t* output16_; + static uint16_t* output16_ref_; + int mask_; +#endif +}; + +uint8_t* ConvolveTest::input_ = NULL; +uint8_t* ConvolveTest::output_ = NULL; +uint8_t* ConvolveTest::output_ref_ = NULL; +#if CONFIG_VP9_HIGHBITDEPTH +uint16_t* ConvolveTest::input16_ = NULL; +uint16_t* ConvolveTest::output16_ = NULL; +uint16_t* ConvolveTest::output16_ref_ = NULL; +#endif + +TEST_P(ConvolveTest, GuardBlocks) { + CheckGuardBlocks(); +} + +TEST_P(ConvolveTest, Copy) { + uint8_t* const in = input(); + uint8_t* const out = output(); + + ASM_REGISTER_STATE_CHECK( + UUT_->copy_(in, kInputStride, out, kOutputStride, NULL, 0, NULL, 0, + Width(), Height())); + + CheckGuardBlocks(); + + for (int y = 0; y < Height(); ++y) + for (int x = 0; x < Width(); ++x) + ASSERT_EQ(lookup(out, y * kOutputStride + x), + lookup(in, y * kInputStride + x)) + << "(" << x << "," << y << ")"; +} + +TEST_P(ConvolveTest, Avg) { + uint8_t* const in = input(); + uint8_t* const out = output(); + uint8_t* const out_ref = output_ref(); + CopyOutputToRef(); + + ASM_REGISTER_STATE_CHECK( + UUT_->avg_(in, kInputStride, out, kOutputStride, NULL, 0, NULL, 0, + Width(), Height())); + + CheckGuardBlocks(); + + for (int y = 0; y < Height(); ++y) + for (int x = 0; x < Width(); ++x) + ASSERT_EQ(lookup(out, y * kOutputStride + x), + ROUND_POWER_OF_TWO(lookup(in, y * kInputStride + x) + + lookup(out_ref, y * kOutputStride + x), 1)) + << "(" << x << "," << y << ")"; +} + +TEST_P(ConvolveTest, CopyHoriz) { + uint8_t* const in = input(); + uint8_t* const out = output(); + DECLARE_ALIGNED(256, const int16_t, filter8[8]) = {0, 0, 0, 128, 0, 0, 0, 0}; + + ASM_REGISTER_STATE_CHECK( + UUT_->sh8_(in, kInputStride, out, kOutputStride, filter8, 16, filter8, 16, + Width(), Height())); + + CheckGuardBlocks(); + + for (int y = 0; y < Height(); ++y) + for (int x = 0; x < Width(); ++x) + ASSERT_EQ(lookup(out, y * kOutputStride + x), + lookup(in, y * kInputStride + x)) + << "(" << x << "," << y << ")"; +} + +TEST_P(ConvolveTest, CopyVert) { + uint8_t* const in = input(); + uint8_t* const out = output(); + DECLARE_ALIGNED(256, const int16_t, filter8[8]) = {0, 0, 0, 128, 0, 0, 0, 0}; + + ASM_REGISTER_STATE_CHECK( + UUT_->sv8_(in, kInputStride, out, kOutputStride, filter8, 16, filter8, 16, + Width(), Height())); + + CheckGuardBlocks(); + + for (int y = 0; y < Height(); ++y) + for (int x = 0; x < Width(); ++x) + ASSERT_EQ(lookup(out, y * kOutputStride + x), + lookup(in, y * kInputStride + x)) + << "(" << x << "," << y << ")"; +} + +TEST_P(ConvolveTest, Copy2D) { + uint8_t* const in = input(); + uint8_t* const out = output(); + DECLARE_ALIGNED(256, const int16_t, filter8[8]) = {0, 0, 0, 128, 0, 0, 0, 0}; + + ASM_REGISTER_STATE_CHECK( + UUT_->shv8_(in, kInputStride, out, kOutputStride, filter8, 16, filter8, + 16, Width(), Height())); + + CheckGuardBlocks(); + + for (int y = 0; y < Height(); ++y) + for (int x = 0; x < Width(); ++x) + ASSERT_EQ(lookup(out, y * kOutputStride + x), + lookup(in, y * kInputStride + x)) + << "(" << x << "," << y << ")"; +} + +const int kNumFilterBanks = 4; +const int kNumFilters = 16; + +TEST(ConvolveTest, FiltersWontSaturateWhenAddedPairwise) { + for (int filter_bank = 0; filter_bank < kNumFilterBanks; ++filter_bank) { + const InterpKernel *filters = + vp9_filter_kernels[static_cast<INTERP_FILTER>(filter_bank)]; + for (int i = 0; i < kNumFilters; i++) { + const int p0 = filters[i][0] + filters[i][1]; + const int p1 = filters[i][2] + filters[i][3]; + const int p2 = filters[i][4] + filters[i][5]; + const int p3 = filters[i][6] + filters[i][7]; + EXPECT_LE(p0, 128); + EXPECT_LE(p1, 128); + EXPECT_LE(p2, 128); + EXPECT_LE(p3, 128); + EXPECT_LE(p0 + p3, 128); + EXPECT_LE(p0 + p3 + p1, 128); + EXPECT_LE(p0 + p3 + p1 + p2, 128); + EXPECT_EQ(p0 + p1 + p2 + p3, 128); + } + } +} + +const int16_t kInvalidFilter[8] = { 0 }; + +TEST_P(ConvolveTest, MatchesReferenceSubpixelFilter) { + uint8_t* const in = input(); + uint8_t* const out = output(); +#if CONFIG_VP9_HIGHBITDEPTH + uint8_t ref8[kOutputStride * kMaxDimension]; + uint16_t ref16[kOutputStride * kMaxDimension]; + uint8_t* ref; + if (UUT_->use_highbd_ == 0) { + ref = ref8; + } else { + ref = CONVERT_TO_BYTEPTR(ref16); + } +#else + uint8_t ref[kOutputStride * kMaxDimension]; +#endif + + for (int filter_bank = 0; filter_bank < kNumFilterBanks; ++filter_bank) { + const InterpKernel *filters = + vp9_filter_kernels[static_cast<INTERP_FILTER>(filter_bank)]; + + for (int filter_x = 0; filter_x < kNumFilters; ++filter_x) { + for (int filter_y = 0; filter_y < kNumFilters; ++filter_y) { + wrapper_filter_block2d_8_c(in, kInputStride, + filters[filter_x], filters[filter_y], + ref, kOutputStride, + Width(), Height()); + + if (filter_x && filter_y) + ASM_REGISTER_STATE_CHECK( + UUT_->hv8_(in, kInputStride, out, kOutputStride, + filters[filter_x], 16, filters[filter_y], 16, + Width(), Height())); + else if (filter_y) + ASM_REGISTER_STATE_CHECK( + UUT_->v8_(in, kInputStride, out, kOutputStride, + kInvalidFilter, 16, filters[filter_y], 16, + Width(), Height())); + else if (filter_x) + ASM_REGISTER_STATE_CHECK( + UUT_->h8_(in, kInputStride, out, kOutputStride, + filters[filter_x], 16, kInvalidFilter, 16, + Width(), Height())); + else + ASM_REGISTER_STATE_CHECK( + UUT_->copy_(in, kInputStride, out, kOutputStride, + kInvalidFilter, 0, kInvalidFilter, 0, + Width(), Height())); + + CheckGuardBlocks(); + + for (int y = 0; y < Height(); ++y) + for (int x = 0; x < Width(); ++x) + ASSERT_EQ(lookup(ref, y * kOutputStride + x), + lookup(out, y * kOutputStride + x)) + << "mismatch at (" << x << "," << y << "), " + << "filters (" << filter_bank << "," + << filter_x << "," << filter_y << ")"; + } + } + } +} + +TEST_P(ConvolveTest, MatchesReferenceAveragingSubpixelFilter) { + uint8_t* const in = input(); + uint8_t* const out = output(); +#if CONFIG_VP9_HIGHBITDEPTH + uint8_t ref8[kOutputStride * kMaxDimension]; + uint16_t ref16[kOutputStride * kMaxDimension]; + uint8_t* ref; + if (UUT_->use_highbd_ == 0) { + ref = ref8; + } else { + ref = CONVERT_TO_BYTEPTR(ref16); + } +#else + uint8_t ref[kOutputStride * kMaxDimension]; +#endif + + // Populate ref and out with some random data + ::libvpx_test::ACMRandom prng; + for (int y = 0; y < Height(); ++y) { + for (int x = 0; x < Width(); ++x) { + uint16_t r; +#if CONFIG_VP9_HIGHBITDEPTH + if (UUT_->use_highbd_ == 0 || UUT_->use_highbd_ == 8) { + r = prng.Rand8Extremes(); + } else { + r = prng.Rand16() & mask_; + } +#else + r = prng.Rand8Extremes(); +#endif + + assign_val(out, y * kOutputStride + x, r); + assign_val(ref, y * kOutputStride + x, r); + } + } + + for (int filter_bank = 0; filter_bank < kNumFilterBanks; ++filter_bank) { + const InterpKernel *filters = + vp9_filter_kernels[static_cast<INTERP_FILTER>(filter_bank)]; + + for (int filter_x = 0; filter_x < kNumFilters; ++filter_x) { + for (int filter_y = 0; filter_y < kNumFilters; ++filter_y) { + wrapper_filter_average_block2d_8_c(in, kInputStride, + filters[filter_x], filters[filter_y], + ref, kOutputStride, + Width(), Height()); + + if (filter_x && filter_y) + ASM_REGISTER_STATE_CHECK( + UUT_->hv8_avg_(in, kInputStride, out, kOutputStride, + filters[filter_x], 16, filters[filter_y], 16, + Width(), Height())); + else if (filter_y) + ASM_REGISTER_STATE_CHECK( + UUT_->v8_avg_(in, kInputStride, out, kOutputStride, + kInvalidFilter, 16, filters[filter_y], 16, + Width(), Height())); + else if (filter_x) + ASM_REGISTER_STATE_CHECK( + UUT_->h8_avg_(in, kInputStride, out, kOutputStride, + filters[filter_x], 16, kInvalidFilter, 16, + Width(), Height())); + else + ASM_REGISTER_STATE_CHECK( + UUT_->avg_(in, kInputStride, out, kOutputStride, + kInvalidFilter, 0, kInvalidFilter, 0, + Width(), Height())); + + CheckGuardBlocks(); + + for (int y = 0; y < Height(); ++y) + for (int x = 0; x < Width(); ++x) + ASSERT_EQ(lookup(ref, y * kOutputStride + x), + lookup(out, y * kOutputStride + x)) + << "mismatch at (" << x << "," << y << "), " + << "filters (" << filter_bank << "," + << filter_x << "," << filter_y << ")"; + } + } + } +} + +TEST_P(ConvolveTest, FilterExtremes) { + uint8_t *const in = input(); + uint8_t *const out = output(); +#if CONFIG_VP9_HIGHBITDEPTH + uint8_t ref8[kOutputStride * kMaxDimension]; + uint16_t ref16[kOutputStride * kMaxDimension]; + uint8_t *ref; + if (UUT_->use_highbd_ == 0) { + ref = ref8; + } else { + ref = CONVERT_TO_BYTEPTR(ref16); + } +#else + uint8_t ref[kOutputStride * kMaxDimension]; +#endif + + // Populate ref and out with some random data + ::libvpx_test::ACMRandom prng; + for (int y = 0; y < Height(); ++y) { + for (int x = 0; x < Width(); ++x) { + uint16_t r; +#if CONFIG_VP9_HIGHBITDEPTH + if (UUT_->use_highbd_ == 0 || UUT_->use_highbd_ == 8) { + r = prng.Rand8Extremes(); + } else { + r = prng.Rand16() & mask_; + } +#else + r = prng.Rand8Extremes(); +#endif + assign_val(out, y * kOutputStride + x, r); + assign_val(ref, y * kOutputStride + x, r); + } + } + + for (int axis = 0; axis < 2; axis++) { + int seed_val = 0; + while (seed_val < 256) { + for (int y = 0; y < 8; ++y) { + for (int x = 0; x < 8; ++x) { +#if CONFIG_VP9_HIGHBITDEPTH + assign_val(in, y * kOutputStride + x - SUBPEL_TAPS / 2 + 1, + ((seed_val >> (axis ? y : x)) & 1) * mask_); +#else + assign_val(in, y * kOutputStride + x - SUBPEL_TAPS / 2 + 1, + ((seed_val >> (axis ? y : x)) & 1) * 255); +#endif + if (axis) seed_val++; + } + if (axis) + seed_val-= 8; + else + seed_val++; + } + if (axis) seed_val += 8; + + for (int filter_bank = 0; filter_bank < kNumFilterBanks; ++filter_bank) { + const InterpKernel *filters = + vp9_filter_kernels[static_cast<INTERP_FILTER>(filter_bank)]; + for (int filter_x = 0; filter_x < kNumFilters; ++filter_x) { + for (int filter_y = 0; filter_y < kNumFilters; ++filter_y) { + wrapper_filter_block2d_8_c(in, kInputStride, + filters[filter_x], filters[filter_y], + ref, kOutputStride, + Width(), Height()); + if (filter_x && filter_y) + ASM_REGISTER_STATE_CHECK( + UUT_->hv8_(in, kInputStride, out, kOutputStride, + filters[filter_x], 16, filters[filter_y], 16, + Width(), Height())); + else if (filter_y) + ASM_REGISTER_STATE_CHECK( + UUT_->v8_(in, kInputStride, out, kOutputStride, + kInvalidFilter, 16, filters[filter_y], 16, + Width(), Height())); + else if (filter_x) + ASM_REGISTER_STATE_CHECK( + UUT_->h8_(in, kInputStride, out, kOutputStride, + filters[filter_x], 16, kInvalidFilter, 16, + Width(), Height())); + else + ASM_REGISTER_STATE_CHECK( + UUT_->copy_(in, kInputStride, out, kOutputStride, + kInvalidFilter, 0, kInvalidFilter, 0, + Width(), Height())); + + for (int y = 0; y < Height(); ++y) + for (int x = 0; x < Width(); ++x) + ASSERT_EQ(lookup(ref, y * kOutputStride + x), + lookup(out, y * kOutputStride + x)) + << "mismatch at (" << x << "," << y << "), " + << "filters (" << filter_bank << "," + << filter_x << "," << filter_y << ")"; + } + } + } + } + } +} + +/* This test exercises that enough rows and columns are filtered with every + possible initial fractional positions and scaling steps. */ +TEST_P(ConvolveTest, CheckScalingFiltering) { + uint8_t* const in = input(); + uint8_t* const out = output(); + const InterpKernel *const eighttap = vp9_filter_kernels[EIGHTTAP]; + + SetConstantInput(127); + + for (int frac = 0; frac < 16; ++frac) { + for (int step = 1; step <= 32; ++step) { + /* Test the horizontal and vertical filters in combination. */ + ASM_REGISTER_STATE_CHECK(UUT_->shv8_(in, kInputStride, out, kOutputStride, + eighttap[frac], step, + eighttap[frac], step, + Width(), Height())); + + CheckGuardBlocks(); + + for (int y = 0; y < Height(); ++y) { + for (int x = 0; x < Width(); ++x) { + ASSERT_EQ(lookup(in, y * kInputStride + x), + lookup(out, y * kOutputStride + x)) + << "x == " << x << ", y == " << y + << ", frac == " << frac << ", step == " << step; + } + } + } + } +} + +using std::tr1::make_tuple; + +#if CONFIG_VP9_HIGHBITDEPTH +#define WRAP(func, bd) \ +void wrap_ ## func ## _ ## bd(const uint8_t *src, ptrdiff_t src_stride, \ + uint8_t *dst, ptrdiff_t dst_stride, \ + const int16_t *filter_x, \ + int filter_x_stride, \ + const int16_t *filter_y, \ + int filter_y_stride, \ + int w, int h) { \ + vpx_highbd_ ## func(src, src_stride, dst, dst_stride, filter_x, \ + filter_x_stride, filter_y, filter_y_stride, \ + w, h, bd); \ +} +#if HAVE_SSE2 && ARCH_X86_64 +#if CONFIG_USE_X86INC +WRAP(convolve_copy_sse2, 8) +WRAP(convolve_avg_sse2, 8) +WRAP(convolve_copy_sse2, 10) +WRAP(convolve_avg_sse2, 10) +WRAP(convolve_copy_sse2, 12) +WRAP(convolve_avg_sse2, 12) +#endif // CONFIG_USE_X86INC +WRAP(convolve8_horiz_sse2, 8) +WRAP(convolve8_avg_horiz_sse2, 8) +WRAP(convolve8_vert_sse2, 8) +WRAP(convolve8_avg_vert_sse2, 8) +WRAP(convolve8_sse2, 8) +WRAP(convolve8_avg_sse2, 8) +WRAP(convolve8_horiz_sse2, 10) +WRAP(convolve8_avg_horiz_sse2, 10) +WRAP(convolve8_vert_sse2, 10) +WRAP(convolve8_avg_vert_sse2, 10) +WRAP(convolve8_sse2, 10) +WRAP(convolve8_avg_sse2, 10) +WRAP(convolve8_horiz_sse2, 12) +WRAP(convolve8_avg_horiz_sse2, 12) +WRAP(convolve8_vert_sse2, 12) +WRAP(convolve8_avg_vert_sse2, 12) +WRAP(convolve8_sse2, 12) +WRAP(convolve8_avg_sse2, 12) +#endif // HAVE_SSE2 && ARCH_X86_64 + +WRAP(convolve_copy_c, 8) +WRAP(convolve_avg_c, 8) +WRAP(convolve8_horiz_c, 8) +WRAP(convolve8_avg_horiz_c, 8) +WRAP(convolve8_vert_c, 8) +WRAP(convolve8_avg_vert_c, 8) +WRAP(convolve8_c, 8) +WRAP(convolve8_avg_c, 8) +WRAP(convolve_copy_c, 10) +WRAP(convolve_avg_c, 10) +WRAP(convolve8_horiz_c, 10) +WRAP(convolve8_avg_horiz_c, 10) +WRAP(convolve8_vert_c, 10) +WRAP(convolve8_avg_vert_c, 10) +WRAP(convolve8_c, 10) +WRAP(convolve8_avg_c, 10) +WRAP(convolve_copy_c, 12) +WRAP(convolve_avg_c, 12) +WRAP(convolve8_horiz_c, 12) +WRAP(convolve8_avg_horiz_c, 12) +WRAP(convolve8_vert_c, 12) +WRAP(convolve8_avg_vert_c, 12) +WRAP(convolve8_c, 12) +WRAP(convolve8_avg_c, 12) +#undef WRAP + +const ConvolveFunctions convolve8_c( + wrap_convolve_copy_c_8, wrap_convolve_avg_c_8, + wrap_convolve8_horiz_c_8, wrap_convolve8_avg_horiz_c_8, + wrap_convolve8_vert_c_8, wrap_convolve8_avg_vert_c_8, + wrap_convolve8_c_8, wrap_convolve8_avg_c_8, + wrap_convolve8_horiz_c_8, wrap_convolve8_avg_horiz_c_8, + wrap_convolve8_vert_c_8, wrap_convolve8_avg_vert_c_8, + wrap_convolve8_c_8, wrap_convolve8_avg_c_8, 8); +const ConvolveFunctions convolve10_c( + wrap_convolve_copy_c_10, wrap_convolve_avg_c_10, + wrap_convolve8_horiz_c_10, wrap_convolve8_avg_horiz_c_10, + wrap_convolve8_vert_c_10, wrap_convolve8_avg_vert_c_10, + wrap_convolve8_c_10, wrap_convolve8_avg_c_10, + wrap_convolve8_horiz_c_10, wrap_convolve8_avg_horiz_c_10, + wrap_convolve8_vert_c_10, wrap_convolve8_avg_vert_c_10, + wrap_convolve8_c_10, wrap_convolve8_avg_c_10, 10); +const ConvolveFunctions convolve12_c( + wrap_convolve_copy_c_12, wrap_convolve_avg_c_12, + wrap_convolve8_horiz_c_12, wrap_convolve8_avg_horiz_c_12, + wrap_convolve8_vert_c_12, wrap_convolve8_avg_vert_c_12, + wrap_convolve8_c_12, wrap_convolve8_avg_c_12, + wrap_convolve8_horiz_c_12, wrap_convolve8_avg_horiz_c_12, + wrap_convolve8_vert_c_12, wrap_convolve8_avg_vert_c_12, + wrap_convolve8_c_12, wrap_convolve8_avg_c_12, 12); +const ConvolveParam kArrayConvolve_c[] = { + ALL_SIZES(convolve8_c), + ALL_SIZES(convolve10_c), + ALL_SIZES(convolve12_c) +}; + +#else +const ConvolveFunctions convolve8_c( + vpx_convolve_copy_c, vpx_convolve_avg_c, + vpx_convolve8_horiz_c, vpx_convolve8_avg_horiz_c, + vpx_convolve8_vert_c, vpx_convolve8_avg_vert_c, + vpx_convolve8_c, vpx_convolve8_avg_c, + vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c, + vpx_scaled_vert_c, vpx_scaled_avg_vert_c, + vpx_scaled_2d_c, vpx_scaled_avg_2d_c, 0); +const ConvolveParam kArrayConvolve_c[] = { ALL_SIZES(convolve8_c) }; +#endif +INSTANTIATE_TEST_CASE_P(C, ConvolveTest, + ::testing::ValuesIn(kArrayConvolve_c)); + +#if HAVE_SSE2 && ARCH_X86_64 +#if CONFIG_VP9_HIGHBITDEPTH +const ConvolveFunctions convolve8_sse2( +#if CONFIG_USE_X86INC + wrap_convolve_copy_sse2_8, wrap_convolve_avg_sse2_8, +#else + wrap_convolve_copy_c_8, wrap_convolve_avg_c_8, +#endif // CONFIG_USE_X86INC + wrap_convolve8_horiz_sse2_8, wrap_convolve8_avg_horiz_sse2_8, + wrap_convolve8_vert_sse2_8, wrap_convolve8_avg_vert_sse2_8, + wrap_convolve8_sse2_8, wrap_convolve8_avg_sse2_8, + wrap_convolve8_horiz_sse2_8, wrap_convolve8_avg_horiz_sse2_8, + wrap_convolve8_vert_sse2_8, wrap_convolve8_avg_vert_sse2_8, + wrap_convolve8_sse2_8, wrap_convolve8_avg_sse2_8, 8); +const ConvolveFunctions convolve10_sse2( +#if CONFIG_USE_X86INC + wrap_convolve_copy_sse2_10, wrap_convolve_avg_sse2_10, +#else + wrap_convolve_copy_c_10, wrap_convolve_avg_c_10, +#endif // CONFIG_USE_X86INC + wrap_convolve8_horiz_sse2_10, wrap_convolve8_avg_horiz_sse2_10, + wrap_convolve8_vert_sse2_10, wrap_convolve8_avg_vert_sse2_10, + wrap_convolve8_sse2_10, wrap_convolve8_avg_sse2_10, + wrap_convolve8_horiz_sse2_10, wrap_convolve8_avg_horiz_sse2_10, + wrap_convolve8_vert_sse2_10, wrap_convolve8_avg_vert_sse2_10, + wrap_convolve8_sse2_10, wrap_convolve8_avg_sse2_10, 10); +const ConvolveFunctions convolve12_sse2( +#if CONFIG_USE_X86INC + wrap_convolve_copy_sse2_12, wrap_convolve_avg_sse2_12, +#else + wrap_convolve_copy_c_12, wrap_convolve_avg_c_12, +#endif // CONFIG_USE_X86INC + wrap_convolve8_horiz_sse2_12, wrap_convolve8_avg_horiz_sse2_12, + wrap_convolve8_vert_sse2_12, wrap_convolve8_avg_vert_sse2_12, + wrap_convolve8_sse2_12, wrap_convolve8_avg_sse2_12, + wrap_convolve8_horiz_sse2_12, wrap_convolve8_avg_horiz_sse2_12, + wrap_convolve8_vert_sse2_12, wrap_convolve8_avg_vert_sse2_12, + wrap_convolve8_sse2_12, wrap_convolve8_avg_sse2_12, 12); +const ConvolveParam kArrayConvolve_sse2[] = { + ALL_SIZES(convolve8_sse2), + ALL_SIZES(convolve10_sse2), + ALL_SIZES(convolve12_sse2) +}; +#else +const ConvolveFunctions convolve8_sse2( +#if CONFIG_USE_X86INC + vpx_convolve_copy_sse2, vpx_convolve_avg_sse2, +#else + vpx_convolve_copy_c, vpx_convolve_avg_c, +#endif // CONFIG_USE_X86INC + vpx_convolve8_horiz_sse2, vpx_convolve8_avg_horiz_sse2, + vpx_convolve8_vert_sse2, vpx_convolve8_avg_vert_sse2, + vpx_convolve8_sse2, vpx_convolve8_avg_sse2, + vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c, + vpx_scaled_vert_c, vpx_scaled_avg_vert_c, + vpx_scaled_2d_c, vpx_scaled_avg_2d_c, 0); + +const ConvolveParam kArrayConvolve_sse2[] = { ALL_SIZES(convolve8_sse2) }; +#endif // CONFIG_VP9_HIGHBITDEPTH +INSTANTIATE_TEST_CASE_P(SSE2, ConvolveTest, + ::testing::ValuesIn(kArrayConvolve_sse2)); +#endif + +#if HAVE_SSSE3 +const ConvolveFunctions convolve8_ssse3( + vpx_convolve_copy_c, vpx_convolve_avg_c, + vpx_convolve8_horiz_ssse3, vpx_convolve8_avg_horiz_ssse3, + vpx_convolve8_vert_ssse3, vpx_convolve8_avg_vert_ssse3, + vpx_convolve8_ssse3, vpx_convolve8_avg_ssse3, + vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c, + vpx_scaled_vert_c, vpx_scaled_avg_vert_c, + vpx_scaled_2d_ssse3, vpx_scaled_avg_2d_c, 0); + +const ConvolveParam kArrayConvolve8_ssse3[] = { ALL_SIZES(convolve8_ssse3) }; +INSTANTIATE_TEST_CASE_P(SSSE3, ConvolveTest, + ::testing::ValuesIn(kArrayConvolve8_ssse3)); +#endif + +#if HAVE_AVX2 && HAVE_SSSE3 +const ConvolveFunctions convolve8_avx2( + vpx_convolve_copy_c, vpx_convolve_avg_c, + vpx_convolve8_horiz_avx2, vpx_convolve8_avg_horiz_ssse3, + vpx_convolve8_vert_avx2, vpx_convolve8_avg_vert_ssse3, + vpx_convolve8_avx2, vpx_convolve8_avg_ssse3, + vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c, + vpx_scaled_vert_c, vpx_scaled_avg_vert_c, + vpx_scaled_2d_c, vpx_scaled_avg_2d_c, 0); + +const ConvolveParam kArrayConvolve8_avx2[] = { ALL_SIZES(convolve8_avx2) }; +INSTANTIATE_TEST_CASE_P(AVX2, ConvolveTest, + ::testing::ValuesIn(kArrayConvolve8_avx2)); +#endif // HAVE_AVX2 && HAVE_SSSE3 + +#if HAVE_NEON +#if HAVE_NEON_ASM +const ConvolveFunctions convolve8_neon( + vpx_convolve_copy_neon, vpx_convolve_avg_neon, + vpx_convolve8_horiz_neon, vpx_convolve8_avg_horiz_neon, + vpx_convolve8_vert_neon, vpx_convolve8_avg_vert_neon, + vpx_convolve8_neon, vpx_convolve8_avg_neon, + vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c, + vpx_scaled_vert_c, vpx_scaled_avg_vert_c, + vpx_scaled_2d_c, vpx_scaled_avg_2d_c, 0); +#else // HAVE_NEON +const ConvolveFunctions convolve8_neon( + vpx_convolve_copy_neon, vpx_convolve_avg_neon, + vpx_convolve8_horiz_neon, vpx_convolve8_avg_horiz_neon, + vpx_convolve8_vert_neon, vpx_convolve8_avg_vert_neon, + vpx_convolve8_neon, vpx_convolve8_avg_neon, + vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c, + vpx_scaled_vert_c, vpx_scaled_avg_vert_c, + vpx_scaled_2d_c, vpx_scaled_avg_2d_c, 0); +#endif // HAVE_NEON_ASM + +const ConvolveParam kArrayConvolve8_neon[] = { ALL_SIZES(convolve8_neon) }; +INSTANTIATE_TEST_CASE_P(NEON, ConvolveTest, + ::testing::ValuesIn(kArrayConvolve8_neon)); +#endif // HAVE_NEON + +#if HAVE_DSPR2 +const ConvolveFunctions convolve8_dspr2( + vpx_convolve_copy_dspr2, vpx_convolve_avg_dspr2, + vpx_convolve8_horiz_dspr2, vpx_convolve8_avg_horiz_dspr2, + vpx_convolve8_vert_dspr2, vpx_convolve8_avg_vert_dspr2, + vpx_convolve8_dspr2, vpx_convolve8_avg_dspr2, + vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c, + vpx_scaled_vert_c, vpx_scaled_avg_vert_c, + vpx_scaled_2d_c, vpx_scaled_avg_2d_c, 0); + +const ConvolveParam kArrayConvolve8_dspr2[] = { ALL_SIZES(convolve8_dspr2) }; +INSTANTIATE_TEST_CASE_P(DSPR2, ConvolveTest, + ::testing::ValuesIn(kArrayConvolve8_dspr2)); +#endif // HAVE_DSPR2 + +#if HAVE_MSA +const ConvolveFunctions convolve8_msa( + vpx_convolve_copy_msa, vpx_convolve_avg_msa, + vpx_convolve8_horiz_msa, vpx_convolve8_avg_horiz_msa, + vpx_convolve8_vert_msa, vpx_convolve8_avg_vert_msa, + vpx_convolve8_msa, vpx_convolve8_avg_msa, + vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c, + vpx_scaled_vert_c, vpx_scaled_avg_vert_c, + vpx_scaled_2d_c, vpx_scaled_avg_2d_c, 0); + +const ConvolveParam kArrayConvolve8_msa[] = { ALL_SIZES(convolve8_msa) }; +INSTANTIATE_TEST_CASE_P(MSA, ConvolveTest, + ::testing::ValuesIn(kArrayConvolve8_msa)); +#endif // HAVE_MSA +} // namespace
diff --git a/src/third_party/libvpx/test/cpu_speed_test.cc b/src/third_party/libvpx/test/cpu_speed_test.cc new file mode 100644 index 0000000..572834c --- /dev/null +++ b/src/third_party/libvpx/test/cpu_speed_test.cc
@@ -0,0 +1,166 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "test/codec_factory.h" +#include "test/encode_test_driver.h" +#include "test/i420_video_source.h" +#include "test/util.h" +#include "test/y4m_video_source.h" + +namespace { + +const int kMaxPSNR = 100; + +class CpuSpeedTest + : public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> { + protected: + CpuSpeedTest() + : EncoderTest(GET_PARAM(0)), + encoding_mode_(GET_PARAM(1)), + set_cpu_used_(GET_PARAM(2)), + min_psnr_(kMaxPSNR), + tune_content_(VP9E_CONTENT_DEFAULT) {} + virtual ~CpuSpeedTest() {} + + virtual void SetUp() { + InitializeConfig(); + SetMode(encoding_mode_); + if (encoding_mode_ != ::libvpx_test::kRealTime) { + cfg_.g_lag_in_frames = 25; + cfg_.rc_end_usage = VPX_VBR; + } else { + cfg_.g_lag_in_frames = 0; + cfg_.rc_end_usage = VPX_CBR; + } + } + + virtual void BeginPassHook(unsigned int /*pass*/) { + min_psnr_ = kMaxPSNR; + } + + virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, + ::libvpx_test::Encoder *encoder) { + if (video->frame() == 1) { + encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_); + encoder->Control(VP9E_SET_TUNE_CONTENT, tune_content_); + if (encoding_mode_ != ::libvpx_test::kRealTime) { + encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1); + encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7); + encoder->Control(VP8E_SET_ARNR_STRENGTH, 5); + encoder->Control(VP8E_SET_ARNR_TYPE, 3); + } + } + } + + virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) { + if (pkt->data.psnr.psnr[0] < min_psnr_) + min_psnr_ = pkt->data.psnr.psnr[0]; + } + + ::libvpx_test::TestMode encoding_mode_; + int set_cpu_used_; + double min_psnr_; + int tune_content_; +}; + +TEST_P(CpuSpeedTest, TestQ0) { + // Validate that this non multiple of 64 wide clip encodes and decodes + // without a mismatch when passing in a very low max q. This pushes + // the encoder to producing lots of big partitions which will likely + // extend into the border and test the border condition. + cfg_.rc_2pass_vbr_minsection_pct = 5; + cfg_.rc_2pass_vbr_maxsection_pct = 2000; + cfg_.rc_target_bitrate = 400; + cfg_.rc_max_quantizer = 0; + cfg_.rc_min_quantizer = 0; + + ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0, + 20); + + init_flags_ = VPX_CODEC_USE_PSNR; + + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + EXPECT_GE(min_psnr_, kMaxPSNR); +} + +TEST_P(CpuSpeedTest, TestScreencastQ0) { + ::libvpx_test::Y4mVideoSource video("screendata.y4m", 0, 25); + cfg_.g_timebase = video.timebase(); + cfg_.rc_2pass_vbr_minsection_pct = 5; + cfg_.rc_2pass_vbr_maxsection_pct = 2000; + cfg_.rc_target_bitrate = 400; + cfg_.rc_max_quantizer = 0; + cfg_.rc_min_quantizer = 0; + + init_flags_ = VPX_CODEC_USE_PSNR; + + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + EXPECT_GE(min_psnr_, kMaxPSNR); +} + +TEST_P(CpuSpeedTest, TestTuneScreen) { + ::libvpx_test::Y4mVideoSource video("screendata.y4m", 0, 25); + cfg_.g_timebase = video.timebase(); + cfg_.rc_2pass_vbr_minsection_pct = 5; + cfg_.rc_2pass_vbr_minsection_pct = 2000; + cfg_.rc_target_bitrate = 2000; + cfg_.rc_max_quantizer = 63; + cfg_.rc_min_quantizer = 0; + tune_content_ = VP9E_CONTENT_SCREEN; + + init_flags_ = VPX_CODEC_USE_PSNR; + + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); +} + +TEST_P(CpuSpeedTest, TestEncodeHighBitrate) { + // Validate that this non multiple of 64 wide clip encodes and decodes + // without a mismatch when passing in a very low max q. This pushes + // the encoder to producing lots of big partitions which will likely + // extend into the border and test the border condition. + cfg_.rc_2pass_vbr_minsection_pct = 5; + cfg_.rc_2pass_vbr_maxsection_pct = 2000; + cfg_.rc_target_bitrate = 12000; + cfg_.rc_max_quantizer = 10; + cfg_.rc_min_quantizer = 0; + + ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0, + 20); + + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); +} + +TEST_P(CpuSpeedTest, TestLowBitrate) { + // Validate that this clip encodes and decodes without a mismatch + // when passing in a very high min q. This pushes the encoder to producing + // lots of small partitions which might will test the other condition. + cfg_.rc_2pass_vbr_minsection_pct = 5; + cfg_.rc_2pass_vbr_maxsection_pct = 2000; + cfg_.rc_target_bitrate = 200; + cfg_.rc_min_quantizer = 40; + + ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0, + 20); + + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); +} + +VP9_INSTANTIATE_TEST_CASE( + CpuSpeedTest, + ::testing::Values(::libvpx_test::kTwoPassGood, ::libvpx_test::kOnePassGood, + ::libvpx_test::kRealTime), + ::testing::Range(0, 9)); + +VP10_INSTANTIATE_TEST_CASE( + CpuSpeedTest, + ::testing::Values(::libvpx_test::kTwoPassGood, ::libvpx_test::kOnePassGood), + ::testing::Range(0, 3)); +} // namespace
diff --git a/src/third_party/libvpx/test/cq_test.cc b/src/third_party/libvpx/test/cq_test.cc new file mode 100644 index 0000000..4e8019a --- /dev/null +++ b/src/third_party/libvpx/test/cq_test.cc
@@ -0,0 +1,134 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include <cmath> +#include <map> +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "test/codec_factory.h" +#include "test/encode_test_driver.h" +#include "test/i420_video_source.h" +#include "test/util.h" + +namespace { + +// CQ level range: [kCQLevelMin, kCQLevelMax). +const int kCQLevelMin = 4; +const int kCQLevelMax = 63; +const int kCQLevelStep = 8; +const unsigned int kCQTargetBitrate = 2000; + +class CQTest : public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWithParam<int> { + public: + // maps the cqlevel to the bitrate produced. + typedef std::map<int, uint32_t> BitrateMap; + + static void SetUpTestCase() { + bitrates_.clear(); + } + + static void TearDownTestCase() { + ASSERT_TRUE(!HasFailure()) + << "skipping bitrate validation due to earlier failure."; + uint32_t prev_actual_bitrate = kCQTargetBitrate; + for (BitrateMap::const_iterator iter = bitrates_.begin(); + iter != bitrates_.end(); ++iter) { + const uint32_t cq_actual_bitrate = iter->second; + EXPECT_LE(cq_actual_bitrate, prev_actual_bitrate) + << "cq_level: " << iter->first + << ", bitrate should decrease with increase in CQ level."; + prev_actual_bitrate = cq_actual_bitrate; + } + } + + protected: + CQTest() : EncoderTest(GET_PARAM(0)), cq_level_(GET_PARAM(1)) { + init_flags_ = VPX_CODEC_USE_PSNR; + } + + virtual ~CQTest() {} + + virtual void SetUp() { + InitializeConfig(); + SetMode(libvpx_test::kTwoPassGood); + } + + virtual void BeginPassHook(unsigned int /*pass*/) { + file_size_ = 0; + psnr_ = 0.0; + n_frames_ = 0; + } + + virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video, + libvpx_test::Encoder *encoder) { + if (video->frame() == 1) { + if (cfg_.rc_end_usage == VPX_CQ) { + encoder->Control(VP8E_SET_CQ_LEVEL, cq_level_); + } + encoder->Control(VP8E_SET_CPUUSED, 3); + } + } + + virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) { + psnr_ += pow(10.0, pkt->data.psnr.psnr[0] / 10.0); + n_frames_++; + } + + virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) { + file_size_ += pkt->data.frame.sz; + } + + double GetLinearPSNROverBitrate() const { + double avg_psnr = log10(psnr_ / n_frames_) * 10.0; + return pow(10.0, avg_psnr / 10.0) / file_size_; + } + + int cq_level() const { return cq_level_; } + size_t file_size() const { return file_size_; } + int n_frames() const { return n_frames_; } + + static BitrateMap bitrates_; + + private: + int cq_level_; + size_t file_size_; + double psnr_; + int n_frames_; +}; + +CQTest::BitrateMap CQTest::bitrates_; + +TEST_P(CQTest, LinearPSNRIsHigherForCQLevel) { + const vpx_rational timebase = { 33333333, 1000000000 }; + cfg_.g_timebase = timebase; + cfg_.rc_target_bitrate = kCQTargetBitrate; + cfg_.g_lag_in_frames = 25; + + cfg_.rc_end_usage = VPX_CQ; + libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + timebase.den, timebase.num, 0, 30); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + const double cq_psnr_lin = GetLinearPSNROverBitrate(); + const unsigned int cq_actual_bitrate = + static_cast<unsigned int>(file_size()) * 8 * 30 / (n_frames() * 1000); + EXPECT_LE(cq_actual_bitrate, kCQTargetBitrate); + bitrates_[cq_level()] = cq_actual_bitrate; + + // try targeting the approximate same bitrate with VBR mode + cfg_.rc_end_usage = VPX_VBR; + cfg_.rc_target_bitrate = cq_actual_bitrate; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + const double vbr_psnr_lin = GetLinearPSNROverBitrate(); + EXPECT_GE(cq_psnr_lin, vbr_psnr_lin); +} + +VP8_INSTANTIATE_TEST_CASE(CQTest, + ::testing::Range(kCQLevelMin, kCQLevelMax, + kCQLevelStep)); +} // namespace
diff --git a/src/third_party/libvpx/test/datarate_test.cc b/src/third_party/libvpx/test/datarate_test.cc new file mode 100644 index 0000000..2f1db9c --- /dev/null +++ b/src/third_party/libvpx/test/datarate_test.cc
@@ -0,0 +1,1156 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include "./vpx_config.h" +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "test/codec_factory.h" +#include "test/encode_test_driver.h" +#include "test/i420_video_source.h" +#include "test/util.h" +#include "test/y4m_video_source.h" +#include "vpx/vpx_codec.h" + +namespace { + +class DatarateTestLarge : public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> { + public: + DatarateTestLarge() : EncoderTest(GET_PARAM(0)) {} + + virtual ~DatarateTestLarge() {} + + protected: + virtual void SetUp() { + InitializeConfig(); + SetMode(GET_PARAM(1)); + ResetModel(); + } + + virtual void ResetModel() { + last_pts_ = 0; + bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz; + frame_number_ = 0; + first_drop_ = 0; + bits_total_ = 0; + duration_ = 0.0; + denoiser_offon_test_ = 0; + denoiser_offon_period_ = -1; + } + + virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, + ::libvpx_test::Encoder *encoder) { + if (video->frame() == 0) + encoder->Control(VP8E_SET_NOISE_SENSITIVITY, denoiser_on_); + + if (denoiser_offon_test_) { + ASSERT_GT(denoiser_offon_period_, 0) + << "denoiser_offon_period_ is not positive."; + if ((video->frame() + 1) % denoiser_offon_period_ == 0) { + // Flip denoiser_on_ periodically + denoiser_on_ ^= 1; + } + encoder->Control(VP8E_SET_NOISE_SENSITIVITY, denoiser_on_); + } + + const vpx_rational_t tb = video->timebase(); + timebase_ = static_cast<double>(tb.num) / tb.den; + duration_ = 0; + } + + virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) { + // Time since last timestamp = duration. + vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_; + + // TODO(jimbankoski): Remove these lines when the issue: + // http://code.google.com/p/webm/issues/detail?id=496 is fixed. + // For now the codec assumes buffer starts at starting buffer rate + // plus one frame's time. + if (last_pts_ == 0) + duration = 1; + + // Add to the buffer the bits we'd expect from a constant bitrate server. + bits_in_buffer_model_ += static_cast<int64_t>( + duration * timebase_ * cfg_.rc_target_bitrate * 1000); + + /* Test the buffer model here before subtracting the frame. Do so because + * the way the leaky bucket model works in libvpx is to allow the buffer to + * empty - and then stop showing frames until we've got enough bits to + * show one. As noted in comment below (issue 495), this does not currently + * apply to key frames. For now exclude key frames in condition below. */ + const bool key_frame = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) + ? true: false; + if (!key_frame) { + ASSERT_GE(bits_in_buffer_model_, 0) << "Buffer Underrun at frame " + << pkt->data.frame.pts; + } + + const int64_t frame_size_in_bits = pkt->data.frame.sz * 8; + + // Subtract from the buffer the bits associated with a played back frame. + bits_in_buffer_model_ -= frame_size_in_bits; + + // Update the running total of bits for end of test datarate checks. + bits_total_ += frame_size_in_bits; + + // If first drop not set and we have a drop set it to this time. + if (!first_drop_ && duration > 1) + first_drop_ = last_pts_ + 1; + + // Update the most recent pts. + last_pts_ = pkt->data.frame.pts; + + // We update this so that we can calculate the datarate minus the last + // frame encoded in the file. + bits_in_last_frame_ = frame_size_in_bits; + + ++frame_number_; + } + + virtual void EndPassHook(void) { + if (bits_total_) { + const double file_size_in_kb = bits_total_ / 1000.; // bits per kilobit + + duration_ = (last_pts_ + 1) * timebase_; + + // Effective file datarate includes the time spent prebuffering. + effective_datarate_ = (bits_total_ - bits_in_last_frame_) / 1000.0 + / (cfg_.rc_buf_initial_sz / 1000.0 + duration_); + + file_datarate_ = file_size_in_kb / duration_; + } + } + + vpx_codec_pts_t last_pts_; + int64_t bits_in_buffer_model_; + double timebase_; + int frame_number_; + vpx_codec_pts_t first_drop_; + int64_t bits_total_; + double duration_; + double file_datarate_; + double effective_datarate_; + size_t bits_in_last_frame_; + int denoiser_on_; + int denoiser_offon_test_; + int denoiser_offon_period_; +}; + +#if CONFIG_TEMPORAL_DENOISING +// Check basic datarate targeting, for a single bitrate, but loop over the +// various denoiser settings. +TEST_P(DatarateTestLarge, DenoiserLevels) { + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_dropframe_thresh = 1; + cfg_.rc_max_quantizer = 56; + cfg_.rc_end_usage = VPX_CBR; + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 140); + for (int j = 1; j < 5; ++j) { + // Run over the denoiser levels. + // For the temporal denoiser (#if CONFIG_TEMPORAL_DENOISING) the level j + // refers to the 4 denoiser modes: denoiserYonly, denoiserOnYUV, + // denoiserOnAggressive, and denoiserOnAdaptive. + // For the spatial denoiser (if !CONFIG_TEMPORAL_DENOISING), the level j + // refers to the blur thresholds: 20, 40, 60 80. + // The j = 0 case (denoiser off) is covered in the tests below. + denoiser_on_ = j; + cfg_.rc_target_bitrate = 300; + ResetModel(); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95) + << " The datarate for the file exceeds the target!"; + + ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.3) + << " The datarate for the file missed the target!"; + } +} + +// Check basic datarate targeting, for a single bitrate, when denoiser is off +// and on. +TEST_P(DatarateTestLarge, DenoiserOffOn) { + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_dropframe_thresh = 1; + cfg_.rc_max_quantizer = 56; + cfg_.rc_end_usage = VPX_CBR; + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 299); + cfg_.rc_target_bitrate = 300; + ResetModel(); + // The denoiser is off by default. + denoiser_on_ = 0; + // Set the offon test flag. + denoiser_offon_test_ = 1; + denoiser_offon_period_ = 100; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95) + << " The datarate for the file exceeds the target!"; + ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.3) + << " The datarate for the file missed the target!"; +} +#endif // CONFIG_TEMPORAL_DENOISING + +TEST_P(DatarateTestLarge, BasicBufferModel) { + denoiser_on_ = 0; + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_dropframe_thresh = 1; + cfg_.rc_max_quantizer = 56; + cfg_.rc_end_usage = VPX_CBR; + // 2 pass cbr datarate control has a bug hidden by the small # of + // frames selected in this encode. The problem is that even if the buffer is + // negative we produce a keyframe on a cutscene. Ignoring datarate + // constraints + // TODO(jimbankoski): ( Fix when issue + // http://code.google.com/p/webm/issues/detail?id=495 is addressed. ) + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 140); + + // There is an issue for low bitrates in real-time mode, where the + // effective_datarate slightly overshoots the target bitrate. + // This is same the issue as noted about (#495). + // TODO(jimbankoski/marpan): Update test to run for lower bitrates (< 100), + // when the issue is resolved. + for (int i = 100; i < 800; i += 200) { + cfg_.rc_target_bitrate = i; + ResetModel(); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95) + << " The datarate for the file exceeds the target!"; + + ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.3) + << " The datarate for the file missed the target!"; + } +} + +TEST_P(DatarateTestLarge, ChangingDropFrameThresh) { + denoiser_on_ = 0; + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_max_quantizer = 36; + cfg_.rc_end_usage = VPX_CBR; + cfg_.rc_target_bitrate = 200; + cfg_.kf_mode = VPX_KF_DISABLED; + + const int frame_count = 40; + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, frame_count); + + // Here we check that the first dropped frame gets earlier and earlier + // as the drop frame threshold is increased. + + const int kDropFrameThreshTestStep = 30; + vpx_codec_pts_t last_drop = frame_count; + for (int i = 1; i < 91; i += kDropFrameThreshTestStep) { + cfg_.rc_dropframe_thresh = i; + ResetModel(); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_LE(first_drop_, last_drop) + << " The first dropped frame for drop_thresh " << i + << " > first dropped frame for drop_thresh " + << i - kDropFrameThreshTestStep; + last_drop = first_drop_; + } +} + +class DatarateTestVP9Large : public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> { + public: + DatarateTestVP9Large() : EncoderTest(GET_PARAM(0)) {} + + protected: + virtual ~DatarateTestVP9Large() {} + + virtual void SetUp() { + InitializeConfig(); + SetMode(GET_PARAM(1)); + set_cpu_used_ = GET_PARAM(2); + ResetModel(); + } + + virtual void ResetModel() { + last_pts_ = 0; + bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz; + frame_number_ = 0; + tot_frame_number_ = 0; + first_drop_ = 0; + num_drops_ = 0; + // Denoiser is off by default. + denoiser_on_ = 0; + // For testing up to 3 layers. + for (int i = 0; i < 3; ++i) { + bits_total_[i] = 0; + } + denoiser_offon_test_ = 0; + denoiser_offon_period_ = -1; + } + + // + // Frame flags and layer id for temporal layers. + // + + // For two layers, test pattern is: + // 1 3 + // 0 2 ..... + // For three layers, test pattern is: + // 1 3 5 7 + // 2 6 + // 0 4 .... + // LAST is always update on base/layer 0, GOLDEN is updated on layer 1. + // For this 3 layer example, the 2nd enhancement layer (layer 2) does not + // update any reference frames. + int SetFrameFlags(int frame_num, int num_temp_layers) { + int frame_flags = 0; + if (num_temp_layers == 2) { + if (frame_num % 2 == 0) { + // Layer 0: predict from L and ARF, update L. + frame_flags = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF; + } else { + // Layer 1: predict from L, G and ARF, and update G. + frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_UPD_ENTROPY; + } + } else if (num_temp_layers == 3) { + if (frame_num % 4 == 0) { + // Layer 0: predict from L and ARF; update L. + frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | + VP8_EFLAG_NO_REF_GF; + } else if ((frame_num - 2) % 4 == 0) { + // Layer 1: predict from L, G, ARF; update G. + frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST; + } else if ((frame_num - 1) % 2 == 0) { + // Layer 2: predict from L, G, ARF; update none. + frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | + VP8_EFLAG_NO_UPD_LAST; + } + } + return frame_flags; + } + + int SetLayerId(int frame_num, int num_temp_layers) { + int layer_id = 0; + if (num_temp_layers == 2) { + if (frame_num % 2 == 0) { + layer_id = 0; + } else { + layer_id = 1; + } + } else if (num_temp_layers == 3) { + if (frame_num % 4 == 0) { + layer_id = 0; + } else if ((frame_num - 2) % 4 == 0) { + layer_id = 1; + } else if ((frame_num - 1) % 2 == 0) { + layer_id = 2; + } + } + return layer_id; + } + + virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, + ::libvpx_test::Encoder *encoder) { + if (video->frame() == 0) + encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_); + + if (denoiser_offon_test_) { + ASSERT_GT(denoiser_offon_period_, 0) + << "denoiser_offon_period_ is not positive."; + if ((video->frame() + 1) % denoiser_offon_period_ == 0) { + // Flip denoiser_on_ periodically + denoiser_on_ ^= 1; + } + } + + encoder->Control(VP9E_SET_NOISE_SENSITIVITY, denoiser_on_); + + if (cfg_.ts_number_layers > 1) { + if (video->frame() == 0) { + encoder->Control(VP9E_SET_SVC, 1); + } + vpx_svc_layer_id_t layer_id; + layer_id.spatial_layer_id = 0; + frame_flags_ = SetFrameFlags(video->frame(), cfg_.ts_number_layers); + layer_id.temporal_layer_id = SetLayerId(video->frame(), + cfg_.ts_number_layers); + encoder->Control(VP9E_SET_SVC_LAYER_ID, &layer_id); + } + const vpx_rational_t tb = video->timebase(); + timebase_ = static_cast<double>(tb.num) / tb.den; + duration_ = 0; + } + + + virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) { + // Time since last timestamp = duration. + vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_; + + if (duration > 1) { + // If first drop not set and we have a drop set it to this time. + if (!first_drop_) + first_drop_ = last_pts_ + 1; + // Update the number of frame drops. + num_drops_ += static_cast<int>(duration - 1); + // Update counter for total number of frames (#frames input to encoder). + // Needed for setting the proper layer_id below. + tot_frame_number_ += static_cast<int>(duration - 1); + } + + int layer = SetLayerId(tot_frame_number_, cfg_.ts_number_layers); + + // Add to the buffer the bits we'd expect from a constant bitrate server. + bits_in_buffer_model_ += static_cast<int64_t>( + duration * timebase_ * cfg_.rc_target_bitrate * 1000); + + // Buffer should not go negative. + ASSERT_GE(bits_in_buffer_model_, 0) << "Buffer Underrun at frame " + << pkt->data.frame.pts; + + const size_t frame_size_in_bits = pkt->data.frame.sz * 8; + + // Update the total encoded bits. For temporal layers, update the cumulative + // encoded bits per layer. + for (int i = layer; i < static_cast<int>(cfg_.ts_number_layers); ++i) { + bits_total_[i] += frame_size_in_bits; + } + + // Update the most recent pts. + last_pts_ = pkt->data.frame.pts; + ++frame_number_; + ++tot_frame_number_; + } + + virtual void EndPassHook(void) { + for (int layer = 0; layer < static_cast<int>(cfg_.ts_number_layers); + ++layer) { + duration_ = (last_pts_ + 1) * timebase_; + if (bits_total_[layer]) { + // Effective file datarate: + effective_datarate_[layer] = (bits_total_[layer] / 1000.0) / duration_; + } + } + } + + vpx_codec_pts_t last_pts_; + double timebase_; + int frame_number_; // Counter for number of non-dropped/encoded frames. + int tot_frame_number_; // Counter for total number of input frames. + int64_t bits_total_[3]; + double duration_; + double effective_datarate_[3]; + int set_cpu_used_; + int64_t bits_in_buffer_model_; + vpx_codec_pts_t first_drop_; + int num_drops_; + int denoiser_on_; + int denoiser_offon_test_; + int denoiser_offon_period_; +}; + +// Check basic rate targeting for VBR mode. +TEST_P(DatarateTestVP9Large, BasicRateTargetingVBR) { + cfg_.rc_min_quantizer = 0; + cfg_.rc_max_quantizer = 63; + cfg_.g_error_resilient = 0; + cfg_.rc_end_usage = VPX_VBR; + cfg_.g_lag_in_frames = 0; + + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 300); + for (int i = 400; i <= 800; i += 400) { + cfg_.rc_target_bitrate = i; + ResetModel(); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.75) + << " The datarate for the file is lower than target by too much!"; + ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.25) + << " The datarate for the file is greater than target by too much!"; + } +} + +// Check basic rate targeting for CBR, +TEST_P(DatarateTestVP9Large, BasicRateTargeting) { + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_dropframe_thresh = 1; + cfg_.rc_min_quantizer = 0; + cfg_.rc_max_quantizer = 63; + cfg_.rc_end_usage = VPX_CBR; + cfg_.g_lag_in_frames = 0; + + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 140); + for (int i = 150; i < 800; i += 200) { + cfg_.rc_target_bitrate = i; + ResetModel(); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85) + << " The datarate for the file is lower than target by too much!"; + ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15) + << " The datarate for the file is greater than target by too much!"; + } +} + +// Check basic rate targeting for CBR. +TEST_P(DatarateTestVP9Large, BasicRateTargeting444) { + ::libvpx_test::Y4mVideoSource video("rush_hour_444.y4m", 0, 140); + + cfg_.g_profile = 1; + cfg_.g_timebase = video.timebase(); + + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_dropframe_thresh = 1; + cfg_.rc_min_quantizer = 0; + cfg_.rc_max_quantizer = 63; + cfg_.rc_end_usage = VPX_CBR; + + for (int i = 250; i < 900; i += 200) { + cfg_.rc_target_bitrate = i; + ResetModel(); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_GE(static_cast<double>(cfg_.rc_target_bitrate), + effective_datarate_[0] * 0.85) + << " The datarate for the file exceeds the target by too much!"; + ASSERT_LE(static_cast<double>(cfg_.rc_target_bitrate), + effective_datarate_[0] * 1.15) + << " The datarate for the file missed the target!" + << cfg_.rc_target_bitrate << " "<< effective_datarate_; + } +} + +// Check that (1) the first dropped frame gets earlier and earlier +// as the drop frame threshold is increased, and (2) that the total number of +// frame drops does not decrease as we increase frame drop threshold. +// Use a lower qp-max to force some frame drops. +TEST_P(DatarateTestVP9Large, ChangingDropFrameThresh) { + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_undershoot_pct = 20; + cfg_.rc_undershoot_pct = 20; + cfg_.rc_dropframe_thresh = 10; + cfg_.rc_min_quantizer = 0; + cfg_.rc_max_quantizer = 50; + cfg_.rc_end_usage = VPX_CBR; + cfg_.rc_target_bitrate = 200; + cfg_.g_lag_in_frames = 0; + // TODO(marpan): Investigate datarate target failures with a smaller keyframe + // interval (128). + cfg_.kf_max_dist = 9999; + + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 140); + + const int kDropFrameThreshTestStep = 30; + vpx_codec_pts_t last_drop = 140; + int last_num_drops = 0; + for (int i = 10; i < 100; i += kDropFrameThreshTestStep) { + cfg_.rc_dropframe_thresh = i; + ResetModel(); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85) + << " The datarate for the file is lower than target by too much!"; + ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15) + << " The datarate for the file is greater than target by too much!"; + ASSERT_LE(first_drop_, last_drop) + << " The first dropped frame for drop_thresh " << i + << " > first dropped frame for drop_thresh " + << i - kDropFrameThreshTestStep; + ASSERT_GE(num_drops_, last_num_drops * 0.85) + << " The number of dropped frames for drop_thresh " << i + << " < number of dropped frames for drop_thresh " + << i - kDropFrameThreshTestStep; + last_drop = first_drop_; + last_num_drops = num_drops_; + } +} + +// Check basic rate targeting for 2 temporal layers. +TEST_P(DatarateTestVP9Large, BasicRateTargeting2TemporalLayers) { + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_dropframe_thresh = 1; + cfg_.rc_min_quantizer = 0; + cfg_.rc_max_quantizer = 63; + cfg_.rc_end_usage = VPX_CBR; + cfg_.g_lag_in_frames = 0; + + // 2 Temporal layers, no spatial layers: Framerate decimation (2, 1). + cfg_.ss_number_layers = 1; + cfg_.ts_number_layers = 2; + cfg_.ts_rate_decimator[0] = 2; + cfg_.ts_rate_decimator[1] = 1; + + cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS; + + if (deadline_ == VPX_DL_REALTIME) + cfg_.g_error_resilient = 1; + + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 200); + for (int i = 200; i <= 800; i += 200) { + cfg_.rc_target_bitrate = i; + ResetModel(); + // 60-40 bitrate allocation for 2 temporal layers. + cfg_.layer_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100; + cfg_.layer_target_bitrate[1] = cfg_.rc_target_bitrate; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) { + ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.85) + << " The datarate for the file is lower than target by too much, " + "for layer: " << j; + ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.15) + << " The datarate for the file is greater than target by too much, " + "for layer: " << j; + } + } +} + +// Check basic rate targeting for 3 temporal layers. +TEST_P(DatarateTestVP9Large, BasicRateTargeting3TemporalLayers) { + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_dropframe_thresh = 1; + cfg_.rc_min_quantizer = 0; + cfg_.rc_max_quantizer = 63; + cfg_.rc_end_usage = VPX_CBR; + cfg_.g_lag_in_frames = 0; + + // 3 Temporal layers, no spatial layers: Framerate decimation (4, 2, 1). + cfg_.ss_number_layers = 1; + cfg_.ts_number_layers = 3; + cfg_.ts_rate_decimator[0] = 4; + cfg_.ts_rate_decimator[1] = 2; + cfg_.ts_rate_decimator[2] = 1; + + cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS; + + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 200); + for (int i = 200; i <= 800; i += 200) { + cfg_.rc_target_bitrate = i; + ResetModel(); + // 40-20-40 bitrate allocation for 3 temporal layers. + cfg_.layer_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100; + cfg_.layer_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100; + cfg_.layer_target_bitrate[2] = cfg_.rc_target_bitrate; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) { + // TODO(yaowu): Work out more stable rc control strategy and + // Adjust the thresholds to be tighter than .75. + ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.75) + << " The datarate for the file is lower than target by too much, " + "for layer: " << j; + // TODO(yaowu): Work out more stable rc control strategy and + // Adjust the thresholds to be tighter than 1.25. + ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.25) + << " The datarate for the file is greater than target by too much, " + "for layer: " << j; + } + } +} + +// Check basic rate targeting for 3 temporal layers, with frame dropping. +// Only for one (low) bitrate with lower max_quantizer, and somewhat higher +// frame drop threshold, to force frame dropping. +TEST_P(DatarateTestVP9Large, BasicRateTargeting3TemporalLayersFrameDropping) { + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + // Set frame drop threshold and rc_max_quantizer to force some frame drops. + cfg_.rc_dropframe_thresh = 20; + cfg_.rc_max_quantizer = 45; + cfg_.rc_min_quantizer = 0; + cfg_.rc_end_usage = VPX_CBR; + cfg_.g_lag_in_frames = 0; + + // 3 Temporal layers, no spatial layers: Framerate decimation (4, 2, 1). + cfg_.ss_number_layers = 1; + cfg_.ts_number_layers = 3; + cfg_.ts_rate_decimator[0] = 4; + cfg_.ts_rate_decimator[1] = 2; + cfg_.ts_rate_decimator[2] = 1; + + cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS; + + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 200); + cfg_.rc_target_bitrate = 200; + ResetModel(); + // 40-20-40 bitrate allocation for 3 temporal layers. + cfg_.layer_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100; + cfg_.layer_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100; + cfg_.layer_target_bitrate[2] = cfg_.rc_target_bitrate; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) { + ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.85) + << " The datarate for the file is lower than target by too much, " + "for layer: " << j; + ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.15) + << " The datarate for the file is greater than target by too much, " + "for layer: " << j; + // Expect some frame drops in this test: for this 200 frames test, + // expect at least 10% and not more than 60% drops. + ASSERT_GE(num_drops_, 20); + ASSERT_LE(num_drops_, 130); + } +} + +#if CONFIG_VP9_TEMPORAL_DENOISING +// Check basic datarate targeting, for a single bitrate, when denoiser is on. +TEST_P(DatarateTestVP9Large, DenoiserLevels) { + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_dropframe_thresh = 1; + cfg_.rc_min_quantizer = 2; + cfg_.rc_max_quantizer = 56; + cfg_.rc_end_usage = VPX_CBR; + cfg_.g_lag_in_frames = 0; + + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 140); + + // For the temporal denoiser (#if CONFIG_VP9_TEMPORAL_DENOISING), + // there is only one denoiser mode: denoiserYonly(which is 1), + // but may add more modes in the future. + cfg_.rc_target_bitrate = 300; + ResetModel(); + // Turn on the denoiser. + denoiser_on_ = 1; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85) + << " The datarate for the file is lower than target by too much!"; + ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15) + << " The datarate for the file is greater than target by too much!"; +} + +// Check basic datarate targeting, for a single bitrate, when denoiser is off +// and on. +TEST_P(DatarateTestVP9Large, DenoiserOffOn) { + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_dropframe_thresh = 1; + cfg_.rc_min_quantizer = 2; + cfg_.rc_max_quantizer = 56; + cfg_.rc_end_usage = VPX_CBR; + cfg_.g_lag_in_frames = 0; + + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 299); + + // For the temporal denoiser (#if CONFIG_VP9_TEMPORAL_DENOISING), + // there is only one denoiser mode: denoiserYonly(which is 1), + // but may add more modes in the future. + cfg_.rc_target_bitrate = 300; + ResetModel(); + // The denoiser is off by default. + denoiser_on_ = 0; + // Set the offon test flag. + denoiser_offon_test_ = 1; + denoiser_offon_period_ = 100; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85) + << " The datarate for the file is lower than target by too much!"; + ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15) + << " The datarate for the file is greater than target by too much!"; +} +#endif // CONFIG_VP9_TEMPORAL_DENOISING + +class DatarateOnePassCbrSvc : public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> { + public: + DatarateOnePassCbrSvc() : EncoderTest(GET_PARAM(0)) {} + virtual ~DatarateOnePassCbrSvc() {} + protected: + virtual void SetUp() { + InitializeConfig(); + SetMode(GET_PARAM(1)); + speed_setting_ = GET_PARAM(2); + ResetModel(); + } + virtual void ResetModel() { + last_pts_ = 0; + bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz; + frame_number_ = 0; + first_drop_ = 0; + bits_total_ = 0; + duration_ = 0.0; + mismatch_psnr_ = 0.0; + mismatch_nframes_ = 0; + } + virtual void BeginPassHook(unsigned int /*pass*/) { + } + virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, + ::libvpx_test::Encoder *encoder) { + if (video->frame() == 0) { + int i; + for (i = 0; i < VPX_MAX_LAYERS; ++i) { + svc_params_.max_quantizers[i] = 63; + svc_params_.min_quantizers[i] = 0; + } + encoder->Control(VP9E_SET_SVC, 1); + encoder->Control(VP9E_SET_SVC_PARAMETERS, &svc_params_); + encoder->Control(VP8E_SET_CPUUSED, speed_setting_); + encoder->Control(VP9E_SET_TILE_COLUMNS, 0); + encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 300); + encoder->Control(VP9E_SET_TILE_COLUMNS, (cfg_.g_threads >> 1)); + } + const vpx_rational_t tb = video->timebase(); + timebase_ = static_cast<double>(tb.num) / tb.den; + duration_ = 0; + } + virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) { + vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_; + if (last_pts_ == 0) + duration = 1; + bits_in_buffer_model_ += static_cast<int64_t>( + duration * timebase_ * cfg_.rc_target_bitrate * 1000); + const bool key_frame = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) + ? true: false; + if (!key_frame) { + ASSERT_GE(bits_in_buffer_model_, 0) << "Buffer Underrun at frame " + << pkt->data.frame.pts; + } + const size_t frame_size_in_bits = pkt->data.frame.sz * 8; + bits_in_buffer_model_ -= frame_size_in_bits; + bits_total_ += frame_size_in_bits; + if (!first_drop_ && duration > 1) + first_drop_ = last_pts_ + 1; + last_pts_ = pkt->data.frame.pts; + bits_in_last_frame_ = frame_size_in_bits; + ++frame_number_; + } + virtual void EndPassHook(void) { + if (bits_total_) { + const double file_size_in_kb = bits_total_ / 1000.; // bits per kilobit + duration_ = (last_pts_ + 1) * timebase_; + file_datarate_ = file_size_in_kb / duration_; + } + } + + virtual void MismatchHook(const vpx_image_t *img1, + const vpx_image_t *img2) { + double mismatch_psnr = compute_psnr(img1, img2); + mismatch_psnr_ += mismatch_psnr; + ++mismatch_nframes_; + } + + unsigned int GetMismatchFrames() { + return mismatch_nframes_; + } + + vpx_codec_pts_t last_pts_; + int64_t bits_in_buffer_model_; + double timebase_; + int frame_number_; + vpx_codec_pts_t first_drop_; + int64_t bits_total_; + double duration_; + double file_datarate_; + size_t bits_in_last_frame_; + vpx_svc_extra_cfg_t svc_params_; + int speed_setting_; + double mismatch_psnr_; + int mismatch_nframes_; +}; +static void assign_layer_bitrates(vpx_codec_enc_cfg_t *const enc_cfg, + const vpx_svc_extra_cfg_t *svc_params, + int spatial_layers, + int temporal_layers, + int temporal_layering_mode) { + int sl, spatial_layer_target; + float total = 0; + float alloc_ratio[VPX_MAX_LAYERS] = {0}; + for (sl = 0; sl < spatial_layers; ++sl) { + if (svc_params->scaling_factor_den[sl] > 0) { + alloc_ratio[sl] = (float)(svc_params->scaling_factor_num[sl] * + 1.0 / svc_params->scaling_factor_den[sl]); + total += alloc_ratio[sl]; + } + } + for (sl = 0; sl < spatial_layers; ++sl) { + enc_cfg->ss_target_bitrate[sl] = spatial_layer_target = + (unsigned int)(enc_cfg->rc_target_bitrate * + alloc_ratio[sl] / total); + const int index = sl * temporal_layers; + if (temporal_layering_mode == 3) { + enc_cfg->layer_target_bitrate[index] = + spatial_layer_target >> 1; + enc_cfg->layer_target_bitrate[index + 1] = + (spatial_layer_target >> 1) + (spatial_layer_target >> 2); + enc_cfg->layer_target_bitrate[index + 2] = + spatial_layer_target; + } else if (temporal_layering_mode == 2) { + enc_cfg->layer_target_bitrate[index] = + spatial_layer_target * 2 / 3; + enc_cfg->layer_target_bitrate[index + 1] = + spatial_layer_target; + } + } +} + +// Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and +// 3 temporal layers. Run CIF clip with 1 thread. +TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayers) { + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_min_quantizer = 0; + cfg_.rc_max_quantizer = 63; + cfg_.rc_end_usage = VPX_CBR; + cfg_.g_lag_in_frames = 0; + cfg_.ss_number_layers = 2; + cfg_.ts_number_layers = 3; + cfg_.ts_rate_decimator[0] = 4; + cfg_.ts_rate_decimator[1] = 2; + cfg_.ts_rate_decimator[2] = 1; + cfg_.g_error_resilient = 1; + cfg_.g_threads = 1; + cfg_.temporal_layering_mode = 3; + svc_params_.scaling_factor_num[0] = 144; + svc_params_.scaling_factor_den[0] = 288; + svc_params_.scaling_factor_num[1] = 288; + svc_params_.scaling_factor_den[1] = 288; + cfg_.rc_dropframe_thresh = 10; + cfg_.kf_max_dist = 9999; + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 200); + // TODO(wonkap/marpan): Check that effective_datarate for each layer hits the + // layer target_bitrate. + for (int i = 200; i <= 800; i += 200) { + cfg_.rc_target_bitrate = i; + ResetModel(); + assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, + cfg_.ts_number_layers, cfg_.temporal_layering_mode); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85) + << " The datarate for the file exceeds the target by too much!"; + ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.15) + << " The datarate for the file is lower than the target by too much!"; + EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames()); + } +} + +// Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and 3 +// temporal layers. Run CIF clip with 1 thread, and few short key frame periods. +TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayersSmallKf) { + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_min_quantizer = 0; + cfg_.rc_max_quantizer = 63; + cfg_.rc_end_usage = VPX_CBR; + cfg_.g_lag_in_frames = 0; + cfg_.ss_number_layers = 2; + cfg_.ts_number_layers = 3; + cfg_.ts_rate_decimator[0] = 4; + cfg_.ts_rate_decimator[1] = 2; + cfg_.ts_rate_decimator[2] = 1; + cfg_.g_error_resilient = 1; + cfg_.g_threads = 1; + cfg_.temporal_layering_mode = 3; + svc_params_.scaling_factor_num[0] = 144; + svc_params_.scaling_factor_den[0] = 288; + svc_params_.scaling_factor_num[1] = 288; + svc_params_.scaling_factor_den[1] = 288; + cfg_.rc_dropframe_thresh = 10; + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 200); + cfg_.rc_target_bitrate = 400; + // For this 3 temporal layer case, pattern repeats every 4 frames, so choose + // 4 key neighboring key frame periods (so key frame will land on 0-2-1-2). + for (int j = 64; j <= 67; j++) { + cfg_.kf_max_dist = j; + ResetModel(); + assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, + cfg_.ts_number_layers, cfg_.temporal_layering_mode); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85) + << " The datarate for the file exceeds the target by too much!"; + ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.15) + << " The datarate for the file is lower than the target by too much!"; + EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames()); + } +} + +// Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and +// 3 temporal layers. Run HD clip with 4 threads. +TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayers4threads) { + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_min_quantizer = 0; + cfg_.rc_max_quantizer = 63; + cfg_.rc_end_usage = VPX_CBR; + cfg_.g_lag_in_frames = 0; + cfg_.ss_number_layers = 2; + cfg_.ts_number_layers = 3; + cfg_.ts_rate_decimator[0] = 4; + cfg_.ts_rate_decimator[1] = 2; + cfg_.ts_rate_decimator[2] = 1; + cfg_.g_error_resilient = 1; + cfg_.g_threads = 4; + cfg_.temporal_layering_mode = 3; + svc_params_.scaling_factor_num[0] = 144; + svc_params_.scaling_factor_den[0] = 288; + svc_params_.scaling_factor_num[1] = 288; + svc_params_.scaling_factor_den[1] = 288; + cfg_.rc_dropframe_thresh = 10; + cfg_.kf_max_dist = 9999; + ::libvpx_test::I420VideoSource video("niklas_1280_720_30.y4m", 1280, 720, + 30, 1, 0, 300); + cfg_.rc_target_bitrate = 800; + ResetModel(); + assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, + cfg_.ts_number_layers, cfg_.temporal_layering_mode); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85) + << " The datarate for the file exceeds the target by too much!"; + ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.15) + << " The datarate for the file is lower than the target by too much!"; + EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames()); +} + +// Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and +// 3 temporal layers. Run CIF clip with 1 thread. +TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayers) { + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_min_quantizer = 0; + cfg_.rc_max_quantizer = 63; + cfg_.rc_end_usage = VPX_CBR; + cfg_.g_lag_in_frames = 0; + cfg_.ss_number_layers = 3; + cfg_.ts_number_layers = 3; + cfg_.ts_rate_decimator[0] = 4; + cfg_.ts_rate_decimator[1] = 2; + cfg_.ts_rate_decimator[2] = 1; + cfg_.g_error_resilient = 1; + cfg_.g_threads = 1; + cfg_.temporal_layering_mode = 3; + svc_params_.scaling_factor_num[0] = 72; + svc_params_.scaling_factor_den[0] = 288; + svc_params_.scaling_factor_num[1] = 144; + svc_params_.scaling_factor_den[1] = 288; + svc_params_.scaling_factor_num[2] = 288; + svc_params_.scaling_factor_den[2] = 288; + cfg_.rc_dropframe_thresh = 10; + cfg_.kf_max_dist = 9999; + ::libvpx_test::I420VideoSource video("niklas_1280_720_30.y4m", 1280, 720, + 30, 1, 0, 300); + cfg_.rc_target_bitrate = 800; + ResetModel(); + assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, + cfg_.ts_number_layers, cfg_.temporal_layering_mode); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85) + << " The datarate for the file exceeds the target by too much!"; + ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.22) + << " The datarate for the file is lower than the target by too much!"; + EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames()); +} + +// Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and 3 +// temporal layers. Run CIF clip with 1 thread, and few short key frame periods. +TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayersSmallKf) { + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_min_quantizer = 0; + cfg_.rc_max_quantizer = 63; + cfg_.rc_end_usage = VPX_CBR; + cfg_.g_lag_in_frames = 0; + cfg_.ss_number_layers = 3; + cfg_.ts_number_layers = 3; + cfg_.ts_rate_decimator[0] = 4; + cfg_.ts_rate_decimator[1] = 2; + cfg_.ts_rate_decimator[2] = 1; + cfg_.g_error_resilient = 1; + cfg_.g_threads = 1; + cfg_.temporal_layering_mode = 3; + svc_params_.scaling_factor_num[0] = 72; + svc_params_.scaling_factor_den[0] = 288; + svc_params_.scaling_factor_num[1] = 144; + svc_params_.scaling_factor_den[1] = 288; + svc_params_.scaling_factor_num[2] = 288; + svc_params_.scaling_factor_den[2] = 288; + cfg_.rc_dropframe_thresh = 10; + ::libvpx_test::I420VideoSource video("niklas_1280_720_30.y4m", 1280, 720, + 30, 1, 0, 300); + cfg_.rc_target_bitrate = 800; + // For this 3 temporal layer case, pattern repeats every 4 frames, so choose + // 4 key neighboring key frame periods (so key frame will land on 0-2-1-2). + for (int j = 32; j <= 35; j++) { + cfg_.kf_max_dist = j; + ResetModel(); + assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, + cfg_.ts_number_layers, cfg_.temporal_layering_mode); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85) + << " The datarate for the file exceeds the target by too much!"; + ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.30) + << " The datarate for the file is lower than the target by too much!"; + EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames()); + } +} + +// Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and +// 3 temporal layers. Run HD clip with 4 threads. +TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayers4threads) { + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_min_quantizer = 0; + cfg_.rc_max_quantizer = 63; + cfg_.rc_end_usage = VPX_CBR; + cfg_.g_lag_in_frames = 0; + cfg_.ss_number_layers = 3; + cfg_.ts_number_layers = 3; + cfg_.ts_rate_decimator[0] = 4; + cfg_.ts_rate_decimator[1] = 2; + cfg_.ts_rate_decimator[2] = 1; + cfg_.g_error_resilient = 1; + cfg_.g_threads = 4; + cfg_.temporal_layering_mode = 3; + svc_params_.scaling_factor_num[0] = 72; + svc_params_.scaling_factor_den[0] = 288; + svc_params_.scaling_factor_num[1] = 144; + svc_params_.scaling_factor_den[1] = 288; + svc_params_.scaling_factor_num[2] = 288; + svc_params_.scaling_factor_den[2] = 288; + cfg_.rc_dropframe_thresh = 10; + cfg_.kf_max_dist = 9999; + ::libvpx_test::I420VideoSource video("niklas_1280_720_30.y4m", 1280, 720, + 30, 1, 0, 300); + cfg_.rc_target_bitrate = 800; + ResetModel(); + assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers, + cfg_.ts_number_layers, cfg_.temporal_layering_mode); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85) + << " The datarate for the file exceeds the target by too much!"; + ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.22) + << " The datarate for the file is lower than the target by too much!"; + EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames()); +} + +VP8_INSTANTIATE_TEST_CASE(DatarateTestLarge, ALL_TEST_MODES); +VP9_INSTANTIATE_TEST_CASE(DatarateTestVP9Large, + ::testing::Values(::libvpx_test::kOnePassGood, + ::libvpx_test::kRealTime), + ::testing::Range(2, 9)); +VP9_INSTANTIATE_TEST_CASE(DatarateOnePassCbrSvc, + ::testing::Values(::libvpx_test::kRealTime), + ::testing::Range(5, 9)); +} // namespace
diff --git a/src/third_party/libvpx/test/dct16x16_test.cc b/src/third_party/libvpx/test/dct16x16_test.cc new file mode 100644 index 0000000..ddaf939 --- /dev/null +++ b/src/third_party/libvpx/test/dct16x16_test.cc
@@ -0,0 +1,994 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <math.h> +#include <stdlib.h> +#include <string.h> + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "./vp9_rtcd.h" +#include "./vpx_dsp_rtcd.h" +#include "test/acm_random.h" +#include "test/clear_system_state.h" +#include "test/register_state_check.h" +#include "test/util.h" +#include "vp9/common/vp9_entropy.h" +#include "vp9/common/vp9_scan.h" +#include "vpx/vpx_codec.h" +#include "vpx/vpx_integer.h" +#include "vpx_ports/mem.h" + +using libvpx_test::ACMRandom; + +namespace { + +#ifdef _MSC_VER +static int round(double x) { + if (x < 0) + return static_cast<int>(ceil(x - 0.5)); + else + return static_cast<int>(floor(x + 0.5)); +} +#endif + +const int kNumCoeffs = 256; +const double C1 = 0.995184726672197; +const double C2 = 0.98078528040323; +const double C3 = 0.956940335732209; +const double C4 = 0.923879532511287; +const double C5 = 0.881921264348355; +const double C6 = 0.831469612302545; +const double C7 = 0.773010453362737; +const double C8 = 0.707106781186548; +const double C9 = 0.634393284163646; +const double C10 = 0.555570233019602; +const double C11 = 0.471396736825998; +const double C12 = 0.38268343236509; +const double C13 = 0.290284677254462; +const double C14 = 0.195090322016128; +const double C15 = 0.098017140329561; + +void butterfly_16x16_dct_1d(double input[16], double output[16]) { + double step[16]; + double intermediate[16]; + double temp1, temp2; + + // step 1 + step[ 0] = input[0] + input[15]; + step[ 1] = input[1] + input[14]; + step[ 2] = input[2] + input[13]; + step[ 3] = input[3] + input[12]; + step[ 4] = input[4] + input[11]; + step[ 5] = input[5] + input[10]; + step[ 6] = input[6] + input[ 9]; + step[ 7] = input[7] + input[ 8]; + step[ 8] = input[7] - input[ 8]; + step[ 9] = input[6] - input[ 9]; + step[10] = input[5] - input[10]; + step[11] = input[4] - input[11]; + step[12] = input[3] - input[12]; + step[13] = input[2] - input[13]; + step[14] = input[1] - input[14]; + step[15] = input[0] - input[15]; + + // step 2 + output[0] = step[0] + step[7]; + output[1] = step[1] + step[6]; + output[2] = step[2] + step[5]; + output[3] = step[3] + step[4]; + output[4] = step[3] - step[4]; + output[5] = step[2] - step[5]; + output[6] = step[1] - step[6]; + output[7] = step[0] - step[7]; + + temp1 = step[ 8] * C7; + temp2 = step[15] * C9; + output[ 8] = temp1 + temp2; + + temp1 = step[ 9] * C11; + temp2 = step[14] * C5; + output[ 9] = temp1 - temp2; + + temp1 = step[10] * C3; + temp2 = step[13] * C13; + output[10] = temp1 + temp2; + + temp1 = step[11] * C15; + temp2 = step[12] * C1; + output[11] = temp1 - temp2; + + temp1 = step[11] * C1; + temp2 = step[12] * C15; + output[12] = temp2 + temp1; + + temp1 = step[10] * C13; + temp2 = step[13] * C3; + output[13] = temp2 - temp1; + + temp1 = step[ 9] * C5; + temp2 = step[14] * C11; + output[14] = temp2 + temp1; + + temp1 = step[ 8] * C9; + temp2 = step[15] * C7; + output[15] = temp2 - temp1; + + // step 3 + step[ 0] = output[0] + output[3]; + step[ 1] = output[1] + output[2]; + step[ 2] = output[1] - output[2]; + step[ 3] = output[0] - output[3]; + + temp1 = output[4] * C14; + temp2 = output[7] * C2; + step[ 4] = temp1 + temp2; + + temp1 = output[5] * C10; + temp2 = output[6] * C6; + step[ 5] = temp1 + temp2; + + temp1 = output[5] * C6; + temp2 = output[6] * C10; + step[ 6] = temp2 - temp1; + + temp1 = output[4] * C2; + temp2 = output[7] * C14; + step[ 7] = temp2 - temp1; + + step[ 8] = output[ 8] + output[11]; + step[ 9] = output[ 9] + output[10]; + step[10] = output[ 9] - output[10]; + step[11] = output[ 8] - output[11]; + + step[12] = output[12] + output[15]; + step[13] = output[13] + output[14]; + step[14] = output[13] - output[14]; + step[15] = output[12] - output[15]; + + // step 4 + output[ 0] = (step[ 0] + step[ 1]); + output[ 8] = (step[ 0] - step[ 1]); + + temp1 = step[2] * C12; + temp2 = step[3] * C4; + temp1 = temp1 + temp2; + output[ 4] = 2*(temp1 * C8); + + temp1 = step[2] * C4; + temp2 = step[3] * C12; + temp1 = temp2 - temp1; + output[12] = 2 * (temp1 * C8); + + output[ 2] = 2 * ((step[4] + step[ 5]) * C8); + output[14] = 2 * ((step[7] - step[ 6]) * C8); + + temp1 = step[4] - step[5]; + temp2 = step[6] + step[7]; + output[ 6] = (temp1 + temp2); + output[10] = (temp1 - temp2); + + intermediate[8] = step[8] + step[14]; + intermediate[9] = step[9] + step[15]; + + temp1 = intermediate[8] * C12; + temp2 = intermediate[9] * C4; + temp1 = temp1 - temp2; + output[3] = 2 * (temp1 * C8); + + temp1 = intermediate[8] * C4; + temp2 = intermediate[9] * C12; + temp1 = temp2 + temp1; + output[13] = 2 * (temp1 * C8); + + output[ 9] = 2 * ((step[10] + step[11]) * C8); + + intermediate[11] = step[10] - step[11]; + intermediate[12] = step[12] + step[13]; + intermediate[13] = step[12] - step[13]; + intermediate[14] = step[ 8] - step[14]; + intermediate[15] = step[ 9] - step[15]; + + output[15] = (intermediate[11] + intermediate[12]); + output[ 1] = -(intermediate[11] - intermediate[12]); + + output[ 7] = 2 * (intermediate[13] * C8); + + temp1 = intermediate[14] * C12; + temp2 = intermediate[15] * C4; + temp1 = temp1 - temp2; + output[11] = -2 * (temp1 * C8); + + temp1 = intermediate[14] * C4; + temp2 = intermediate[15] * C12; + temp1 = temp2 + temp1; + output[ 5] = 2 * (temp1 * C8); +} + +void reference_16x16_dct_2d(int16_t input[256], double output[256]) { + // First transform columns + for (int i = 0; i < 16; ++i) { + double temp_in[16], temp_out[16]; + for (int j = 0; j < 16; ++j) + temp_in[j] = input[j * 16 + i]; + butterfly_16x16_dct_1d(temp_in, temp_out); + for (int j = 0; j < 16; ++j) + output[j * 16 + i] = temp_out[j]; + } + // Then transform rows + for (int i = 0; i < 16; ++i) { + double temp_in[16], temp_out[16]; + for (int j = 0; j < 16; ++j) + temp_in[j] = output[j + i * 16]; + butterfly_16x16_dct_1d(temp_in, temp_out); + // Scale by some magic number + for (int j = 0; j < 16; ++j) + output[j + i * 16] = temp_out[j]/2; + } +} + +typedef void (*FdctFunc)(const int16_t *in, tran_low_t *out, int stride); +typedef void (*IdctFunc)(const tran_low_t *in, uint8_t *out, int stride); +typedef void (*FhtFunc)(const int16_t *in, tran_low_t *out, int stride, + int tx_type); +typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride, + int tx_type); + +typedef std::tr1::tuple<FdctFunc, IdctFunc, int, vpx_bit_depth_t> Dct16x16Param; +typedef std::tr1::tuple<FhtFunc, IhtFunc, int, vpx_bit_depth_t> Ht16x16Param; +typedef std::tr1::tuple<IdctFunc, IdctFunc, int, vpx_bit_depth_t> + Idct16x16Param; + +void fdct16x16_ref(const int16_t *in, tran_low_t *out, int stride, + int /*tx_type*/) { + vpx_fdct16x16_c(in, out, stride); +} + +void idct16x16_ref(const tran_low_t *in, uint8_t *dest, int stride, + int /*tx_type*/) { + vpx_idct16x16_256_add_c(in, dest, stride); +} + +void fht16x16_ref(const int16_t *in, tran_low_t *out, int stride, + int tx_type) { + vp9_fht16x16_c(in, out, stride, tx_type); +} + +void iht16x16_ref(const tran_low_t *in, uint8_t *dest, int stride, + int tx_type) { + vp9_iht16x16_256_add_c(in, dest, stride, tx_type); +} + +#if CONFIG_VP9_HIGHBITDEPTH +void idct16x16_10(const tran_low_t *in, uint8_t *out, int stride) { + vpx_highbd_idct16x16_256_add_c(in, out, stride, 10); +} + +void idct16x16_12(const tran_low_t *in, uint8_t *out, int stride) { + vpx_highbd_idct16x16_256_add_c(in, out, stride, 12); +} + +void idct16x16_10_ref(const tran_low_t *in, uint8_t *out, int stride, + int /*tx_type*/) { + idct16x16_10(in, out, stride); +} + +void idct16x16_12_ref(const tran_low_t *in, uint8_t *out, int stride, + int /*tx_type*/) { + idct16x16_12(in, out, stride); +} + +void iht16x16_10(const tran_low_t *in, uint8_t *out, int stride, int tx_type) { + vp9_highbd_iht16x16_256_add_c(in, out, stride, tx_type, 10); +} + +void iht16x16_12(const tran_low_t *in, uint8_t *out, int stride, int tx_type) { + vp9_highbd_iht16x16_256_add_c(in, out, stride, tx_type, 12); +} + +#if HAVE_SSE2 +void idct16x16_10_add_10_c(const tran_low_t *in, uint8_t *out, int stride) { + vpx_highbd_idct16x16_10_add_c(in, out, stride, 10); +} + +void idct16x16_10_add_12_c(const tran_low_t *in, uint8_t *out, int stride) { + vpx_highbd_idct16x16_10_add_c(in, out, stride, 12); +} + +void idct16x16_256_add_10_sse2(const tran_low_t *in, uint8_t *out, int stride) { + vpx_highbd_idct16x16_256_add_sse2(in, out, stride, 10); +} + +void idct16x16_256_add_12_sse2(const tran_low_t *in, uint8_t *out, int stride) { + vpx_highbd_idct16x16_256_add_sse2(in, out, stride, 12); +} + +void idct16x16_10_add_10_sse2(const tran_low_t *in, uint8_t *out, int stride) { + vpx_highbd_idct16x16_10_add_sse2(in, out, stride, 10); +} + +void idct16x16_10_add_12_sse2(const tran_low_t *in, uint8_t *out, int stride) { + vpx_highbd_idct16x16_10_add_sse2(in, out, stride, 12); +} +#endif // HAVE_SSE2 +#endif // CONFIG_VP9_HIGHBITDEPTH + +class Trans16x16TestBase { + public: + virtual ~Trans16x16TestBase() {} + + protected: + virtual void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) = 0; + + virtual void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) = 0; + + void RunAccuracyCheck() { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + uint32_t max_error = 0; + int64_t total_error = 0; + const int count_test_block = 10000; + for (int i = 0; i < count_test_block; ++i) { + DECLARE_ALIGNED(16, int16_t, test_input_block[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, test_temp_block[kNumCoeffs]); + DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]); + DECLARE_ALIGNED(16, uint8_t, src[kNumCoeffs]); +#if CONFIG_VP9_HIGHBITDEPTH + DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]); + DECLARE_ALIGNED(16, uint16_t, src16[kNumCoeffs]); +#endif + + // Initialize a test block with input range [-mask_, mask_]. + for (int j = 0; j < kNumCoeffs; ++j) { + if (bit_depth_ == VPX_BITS_8) { + src[j] = rnd.Rand8(); + dst[j] = rnd.Rand8(); + test_input_block[j] = src[j] - dst[j]; +#if CONFIG_VP9_HIGHBITDEPTH + } else { + src16[j] = rnd.Rand16() & mask_; + dst16[j] = rnd.Rand16() & mask_; + test_input_block[j] = src16[j] - dst16[j]; +#endif + } + } + + ASM_REGISTER_STATE_CHECK(RunFwdTxfm(test_input_block, + test_temp_block, pitch_)); + if (bit_depth_ == VPX_BITS_8) { + ASM_REGISTER_STATE_CHECK( + RunInvTxfm(test_temp_block, dst, pitch_)); +#if CONFIG_VP9_HIGHBITDEPTH + } else { + ASM_REGISTER_STATE_CHECK( + RunInvTxfm(test_temp_block, CONVERT_TO_BYTEPTR(dst16), pitch_)); +#endif + } + + for (int j = 0; j < kNumCoeffs; ++j) { +#if CONFIG_VP9_HIGHBITDEPTH + const int32_t diff = + bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j]; +#else + const int32_t diff = dst[j] - src[j]; +#endif + const uint32_t error = diff * diff; + if (max_error < error) + max_error = error; + total_error += error; + } + } + + EXPECT_GE(1u << 2 * (bit_depth_ - 8), max_error) + << "Error: 16x16 FHT/IHT has an individual round trip error > 1"; + + EXPECT_GE(count_test_block << 2 * (bit_depth_ - 8), total_error) + << "Error: 16x16 FHT/IHT has average round trip error > 1 per block"; + } + + void RunCoeffCheck() { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + const int count_test_block = 1000; + DECLARE_ALIGNED(16, int16_t, input_block[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, output_block[kNumCoeffs]); + + for (int i = 0; i < count_test_block; ++i) { + // Initialize a test block with input range [-mask_, mask_]. + for (int j = 0; j < kNumCoeffs; ++j) + input_block[j] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_); + + fwd_txfm_ref(input_block, output_ref_block, pitch_, tx_type_); + ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_block, output_block, pitch_)); + + // The minimum quant value is 4. + for (int j = 0; j < kNumCoeffs; ++j) + EXPECT_EQ(output_block[j], output_ref_block[j]); + } + } + + void RunMemCheck() { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + const int count_test_block = 1000; + DECLARE_ALIGNED(16, int16_t, input_extreme_block[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, output_block[kNumCoeffs]); + + for (int i = 0; i < count_test_block; ++i) { + // Initialize a test block with input range [-mask_, mask_]. + for (int j = 0; j < kNumCoeffs; ++j) { + input_extreme_block[j] = rnd.Rand8() % 2 ? mask_ : -mask_; + } + if (i == 0) { + for (int j = 0; j < kNumCoeffs; ++j) + input_extreme_block[j] = mask_; + } else if (i == 1) { + for (int j = 0; j < kNumCoeffs; ++j) + input_extreme_block[j] = -mask_; + } + + fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_); + ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_extreme_block, + output_block, pitch_)); + + // The minimum quant value is 4. + for (int j = 0; j < kNumCoeffs; ++j) { + EXPECT_EQ(output_block[j], output_ref_block[j]); + EXPECT_GE(4 * DCT_MAX_VALUE << (bit_depth_ - 8), abs(output_block[j])) + << "Error: 16x16 FDCT has coefficient larger than 4*DCT_MAX_VALUE"; + } + } + } + + void RunQuantCheck(int dc_thred, int ac_thred) { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + const int count_test_block = 100000; + DECLARE_ALIGNED(16, int16_t, input_extreme_block[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kNumCoeffs]); + + DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]); + DECLARE_ALIGNED(16, uint8_t, ref[kNumCoeffs]); +#if CONFIG_VP9_HIGHBITDEPTH + DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]); + DECLARE_ALIGNED(16, uint16_t, ref16[kNumCoeffs]); +#endif + + for (int i = 0; i < count_test_block; ++i) { + // Initialize a test block with input range [-mask_, mask_]. + for (int j = 0; j < kNumCoeffs; ++j) { + input_extreme_block[j] = rnd.Rand8() % 2 ? mask_ : -mask_; + } + if (i == 0) + for (int j = 0; j < kNumCoeffs; ++j) + input_extreme_block[j] = mask_; + if (i == 1) + for (int j = 0; j < kNumCoeffs; ++j) + input_extreme_block[j] = -mask_; + + fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_); + + // clear reconstructed pixel buffers + memset(dst, 0, kNumCoeffs * sizeof(uint8_t)); + memset(ref, 0, kNumCoeffs * sizeof(uint8_t)); +#if CONFIG_VP9_HIGHBITDEPTH + memset(dst16, 0, kNumCoeffs * sizeof(uint16_t)); + memset(ref16, 0, kNumCoeffs * sizeof(uint16_t)); +#endif + + // quantization with maximum allowed step sizes + output_ref_block[0] = (output_ref_block[0] / dc_thred) * dc_thred; + for (int j = 1; j < kNumCoeffs; ++j) + output_ref_block[j] = (output_ref_block[j] / ac_thred) * ac_thred; + if (bit_depth_ == VPX_BITS_8) { + inv_txfm_ref(output_ref_block, ref, pitch_, tx_type_); + ASM_REGISTER_STATE_CHECK(RunInvTxfm(output_ref_block, dst, pitch_)); +#if CONFIG_VP9_HIGHBITDEPTH + } else { + inv_txfm_ref(output_ref_block, CONVERT_TO_BYTEPTR(ref16), pitch_, + tx_type_); + ASM_REGISTER_STATE_CHECK(RunInvTxfm(output_ref_block, + CONVERT_TO_BYTEPTR(dst16), pitch_)); +#endif + } + if (bit_depth_ == VPX_BITS_8) { + for (int j = 0; j < kNumCoeffs; ++j) + EXPECT_EQ(ref[j], dst[j]); +#if CONFIG_VP9_HIGHBITDEPTH + } else { + for (int j = 0; j < kNumCoeffs; ++j) + EXPECT_EQ(ref16[j], dst16[j]); +#endif + } + } + } + + void RunInvAccuracyCheck() { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + const int count_test_block = 1000; + DECLARE_ALIGNED(16, int16_t, in[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, coeff[kNumCoeffs]); + DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]); + DECLARE_ALIGNED(16, uint8_t, src[kNumCoeffs]); +#if CONFIG_VP9_HIGHBITDEPTH + DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]); + DECLARE_ALIGNED(16, uint16_t, src16[kNumCoeffs]); +#endif // CONFIG_VP9_HIGHBITDEPTH + + for (int i = 0; i < count_test_block; ++i) { + double out_r[kNumCoeffs]; + + // Initialize a test block with input range [-255, 255]. + for (int j = 0; j < kNumCoeffs; ++j) { + if (bit_depth_ == VPX_BITS_8) { + src[j] = rnd.Rand8(); + dst[j] = rnd.Rand8(); + in[j] = src[j] - dst[j]; +#if CONFIG_VP9_HIGHBITDEPTH + } else { + src16[j] = rnd.Rand16() & mask_; + dst16[j] = rnd.Rand16() & mask_; + in[j] = src16[j] - dst16[j]; +#endif // CONFIG_VP9_HIGHBITDEPTH + } + } + + reference_16x16_dct_2d(in, out_r); + for (int j = 0; j < kNumCoeffs; ++j) + coeff[j] = static_cast<tran_low_t>(round(out_r[j])); + + if (bit_depth_ == VPX_BITS_8) { + ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, 16)); +#if CONFIG_VP9_HIGHBITDEPTH + } else { + ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16), + 16)); +#endif // CONFIG_VP9_HIGHBITDEPTH + } + + for (int j = 0; j < kNumCoeffs; ++j) { +#if CONFIG_VP9_HIGHBITDEPTH + const uint32_t diff = + bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j]; +#else + const uint32_t diff = dst[j] - src[j]; +#endif // CONFIG_VP9_HIGHBITDEPTH + const uint32_t error = diff * diff; + EXPECT_GE(1u, error) + << "Error: 16x16 IDCT has error " << error + << " at index " << j; + } + } + } + + void CompareInvReference(IdctFunc ref_txfm, int thresh) { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + const int count_test_block = 10000; + const int eob = 10; + const int16_t *scan = vp9_default_scan_orders[TX_16X16].scan; + DECLARE_ALIGNED(16, tran_low_t, coeff[kNumCoeffs]); + DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]); + DECLARE_ALIGNED(16, uint8_t, ref[kNumCoeffs]); +#if CONFIG_VP9_HIGHBITDEPTH + DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]); + DECLARE_ALIGNED(16, uint16_t, ref16[kNumCoeffs]); +#endif // CONFIG_VP9_HIGHBITDEPTH + + for (int i = 0; i < count_test_block; ++i) { + for (int j = 0; j < kNumCoeffs; ++j) { + if (j < eob) { + // Random values less than the threshold, either positive or negative + coeff[scan[j]] = rnd(thresh) * (1 - 2 * (i % 2)); + } else { + coeff[scan[j]] = 0; + } + if (bit_depth_ == VPX_BITS_8) { + dst[j] = 0; + ref[j] = 0; +#if CONFIG_VP9_HIGHBITDEPTH + } else { + dst16[j] = 0; + ref16[j] = 0; +#endif // CONFIG_VP9_HIGHBITDEPTH + } + } + if (bit_depth_ == VPX_BITS_8) { + ref_txfm(coeff, ref, pitch_); + ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_)); + } else { +#if CONFIG_VP9_HIGHBITDEPTH + ref_txfm(coeff, CONVERT_TO_BYTEPTR(ref16), pitch_); + ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16), + pitch_)); +#endif // CONFIG_VP9_HIGHBITDEPTH + } + + for (int j = 0; j < kNumCoeffs; ++j) { +#if CONFIG_VP9_HIGHBITDEPTH + const uint32_t diff = + bit_depth_ == VPX_BITS_8 ? dst[j] - ref[j] : dst16[j] - ref16[j]; +#else + const uint32_t diff = dst[j] - ref[j]; +#endif // CONFIG_VP9_HIGHBITDEPTH + const uint32_t error = diff * diff; + EXPECT_EQ(0u, error) + << "Error: 16x16 IDCT Comparison has error " << error + << " at index " << j; + } + } + } + + int pitch_; + int tx_type_; + vpx_bit_depth_t bit_depth_; + int mask_; + FhtFunc fwd_txfm_ref; + IhtFunc inv_txfm_ref; +}; + +class Trans16x16DCT + : public Trans16x16TestBase, + public ::testing::TestWithParam<Dct16x16Param> { + public: + virtual ~Trans16x16DCT() {} + + virtual void SetUp() { + fwd_txfm_ = GET_PARAM(0); + inv_txfm_ = GET_PARAM(1); + tx_type_ = GET_PARAM(2); + bit_depth_ = GET_PARAM(3); + pitch_ = 16; + fwd_txfm_ref = fdct16x16_ref; + inv_txfm_ref = idct16x16_ref; + mask_ = (1 << bit_depth_) - 1; +#if CONFIG_VP9_HIGHBITDEPTH + switch (bit_depth_) { + case VPX_BITS_10: + inv_txfm_ref = idct16x16_10_ref; + break; + case VPX_BITS_12: + inv_txfm_ref = idct16x16_12_ref; + break; + default: + inv_txfm_ref = idct16x16_ref; + break; + } +#else + inv_txfm_ref = idct16x16_ref; +#endif + } + virtual void TearDown() { libvpx_test::ClearSystemState(); } + + protected: + void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) { + fwd_txfm_(in, out, stride); + } + void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) { + inv_txfm_(out, dst, stride); + } + + FdctFunc fwd_txfm_; + IdctFunc inv_txfm_; +}; + +TEST_P(Trans16x16DCT, AccuracyCheck) { + RunAccuracyCheck(); +} + +TEST_P(Trans16x16DCT, CoeffCheck) { + RunCoeffCheck(); +} + +TEST_P(Trans16x16DCT, MemCheck) { + RunMemCheck(); +} + +TEST_P(Trans16x16DCT, QuantCheck) { + // Use maximally allowed quantization step sizes for DC and AC + // coefficients respectively. + RunQuantCheck(1336, 1828); +} + +TEST_P(Trans16x16DCT, InvAccuracyCheck) { + RunInvAccuracyCheck(); +} + +class Trans16x16HT + : public Trans16x16TestBase, + public ::testing::TestWithParam<Ht16x16Param> { + public: + virtual ~Trans16x16HT() {} + + virtual void SetUp() { + fwd_txfm_ = GET_PARAM(0); + inv_txfm_ = GET_PARAM(1); + tx_type_ = GET_PARAM(2); + bit_depth_ = GET_PARAM(3); + pitch_ = 16; + fwd_txfm_ref = fht16x16_ref; + inv_txfm_ref = iht16x16_ref; + mask_ = (1 << bit_depth_) - 1; +#if CONFIG_VP9_HIGHBITDEPTH + switch (bit_depth_) { + case VPX_BITS_10: + inv_txfm_ref = iht16x16_10; + break; + case VPX_BITS_12: + inv_txfm_ref = iht16x16_12; + break; + default: + inv_txfm_ref = iht16x16_ref; + break; + } +#else + inv_txfm_ref = iht16x16_ref; +#endif + } + virtual void TearDown() { libvpx_test::ClearSystemState(); } + + protected: + void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) { + fwd_txfm_(in, out, stride, tx_type_); + } + void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) { + inv_txfm_(out, dst, stride, tx_type_); + } + + FhtFunc fwd_txfm_; + IhtFunc inv_txfm_; +}; + +TEST_P(Trans16x16HT, AccuracyCheck) { + RunAccuracyCheck(); +} + +TEST_P(Trans16x16HT, CoeffCheck) { + RunCoeffCheck(); +} + +TEST_P(Trans16x16HT, MemCheck) { + RunMemCheck(); +} + +TEST_P(Trans16x16HT, QuantCheck) { + // The encoder skips any non-DC intra prediction modes, + // when the quantization step size goes beyond 988. + RunQuantCheck(429, 729); +} + +class InvTrans16x16DCT + : public Trans16x16TestBase, + public ::testing::TestWithParam<Idct16x16Param> { + public: + virtual ~InvTrans16x16DCT() {} + + virtual void SetUp() { + ref_txfm_ = GET_PARAM(0); + inv_txfm_ = GET_PARAM(1); + thresh_ = GET_PARAM(2); + bit_depth_ = GET_PARAM(3); + pitch_ = 16; + mask_ = (1 << bit_depth_) - 1; +} + virtual void TearDown() { libvpx_test::ClearSystemState(); } + + protected: + void RunFwdTxfm(int16_t * /*in*/, tran_low_t * /*out*/, int /*stride*/) {} + void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) { + inv_txfm_(out, dst, stride); + } + + IdctFunc ref_txfm_; + IdctFunc inv_txfm_; + int thresh_; +}; + +TEST_P(InvTrans16x16DCT, CompareReference) { + CompareInvReference(ref_txfm_, thresh_); +} + +class PartialTrans16x16Test + : public ::testing::TestWithParam< + std::tr1::tuple<FdctFunc, vpx_bit_depth_t> > { + public: + virtual ~PartialTrans16x16Test() {} + virtual void SetUp() { + fwd_txfm_ = GET_PARAM(0); + bit_depth_ = GET_PARAM(1); + } + + virtual void TearDown() { libvpx_test::ClearSystemState(); } + + protected: + vpx_bit_depth_t bit_depth_; + FdctFunc fwd_txfm_; +}; + +TEST_P(PartialTrans16x16Test, Extremes) { +#if CONFIG_VP9_HIGHBITDEPTH + const int16_t maxval = + static_cast<int16_t>(clip_pixel_highbd(1 << 30, bit_depth_)); +#else + const int16_t maxval = 255; +#endif + const int minval = -maxval; + DECLARE_ALIGNED(16, int16_t, input[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, output[kNumCoeffs]); + + for (int i = 0; i < kNumCoeffs; ++i) input[i] = maxval; + output[0] = 0; + ASM_REGISTER_STATE_CHECK(fwd_txfm_(input, output, 16)); + EXPECT_EQ((maxval * kNumCoeffs) >> 1, output[0]); + + for (int i = 0; i < kNumCoeffs; ++i) input[i] = minval; + output[0] = 0; + ASM_REGISTER_STATE_CHECK(fwd_txfm_(input, output, 16)); + EXPECT_EQ((minval * kNumCoeffs) >> 1, output[0]); +} + +TEST_P(PartialTrans16x16Test, Random) { +#if CONFIG_VP9_HIGHBITDEPTH + const int16_t maxval = + static_cast<int16_t>(clip_pixel_highbd(1 << 30, bit_depth_)); +#else + const int16_t maxval = 255; +#endif + DECLARE_ALIGNED(16, int16_t, input[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, output[kNumCoeffs]); + ACMRandom rnd(ACMRandom::DeterministicSeed()); + + int sum = 0; + for (int i = 0; i < kNumCoeffs; ++i) { + const int val = (i & 1) ? -rnd(maxval + 1) : rnd(maxval + 1); + input[i] = val; + sum += val; + } + output[0] = 0; + ASM_REGISTER_STATE_CHECK(fwd_txfm_(input, output, 16)); + EXPECT_EQ(sum >> 1, output[0]); +} + +using std::tr1::make_tuple; + +#if CONFIG_VP9_HIGHBITDEPTH +INSTANTIATE_TEST_CASE_P( + C, Trans16x16DCT, + ::testing::Values( + make_tuple(&vpx_highbd_fdct16x16_c, &idct16x16_10, 0, VPX_BITS_10), + make_tuple(&vpx_highbd_fdct16x16_c, &idct16x16_12, 0, VPX_BITS_12), + make_tuple(&vpx_fdct16x16_c, &vpx_idct16x16_256_add_c, 0, VPX_BITS_8))); +#else +INSTANTIATE_TEST_CASE_P( + C, Trans16x16DCT, + ::testing::Values( + make_tuple(&vpx_fdct16x16_c, &vpx_idct16x16_256_add_c, 0, VPX_BITS_8))); +#endif // CONFIG_VP9_HIGHBITDEPTH + +#if CONFIG_VP9_HIGHBITDEPTH +INSTANTIATE_TEST_CASE_P( + C, Trans16x16HT, + ::testing::Values( + make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_10, 0, VPX_BITS_10), + make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_10, 1, VPX_BITS_10), + make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_10, 2, VPX_BITS_10), + make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_10, 3, VPX_BITS_10), + make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_12, 0, VPX_BITS_12), + make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_12, 1, VPX_BITS_12), + make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_12, 2, VPX_BITS_12), + make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_12, 3, VPX_BITS_12), + make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 0, VPX_BITS_8), + make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 1, VPX_BITS_8), + make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 2, VPX_BITS_8), + make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 3, VPX_BITS_8))); +INSTANTIATE_TEST_CASE_P( + C, PartialTrans16x16Test, + ::testing::Values(make_tuple(&vpx_highbd_fdct16x16_1_c, VPX_BITS_8), + make_tuple(&vpx_highbd_fdct16x16_1_c, VPX_BITS_10), + make_tuple(&vpx_highbd_fdct16x16_1_c, VPX_BITS_12))); +#else +INSTANTIATE_TEST_CASE_P( + C, Trans16x16HT, + ::testing::Values( + make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 0, VPX_BITS_8), + make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 1, VPX_BITS_8), + make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 2, VPX_BITS_8), + make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 3, VPX_BITS_8))); +INSTANTIATE_TEST_CASE_P(C, PartialTrans16x16Test, + ::testing::Values(make_tuple(&vpx_fdct16x16_1_c, + VPX_BITS_8))); +#endif // CONFIG_VP9_HIGHBITDEPTH + +#if HAVE_NEON_ASM && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + NEON, Trans16x16DCT, + ::testing::Values( + make_tuple(&vpx_fdct16x16_c, + &vpx_idct16x16_256_add_neon, 0, VPX_BITS_8))); +#endif + +#if HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + SSE2, Trans16x16DCT, + ::testing::Values( + make_tuple(&vpx_fdct16x16_sse2, + &vpx_idct16x16_256_add_sse2, 0, VPX_BITS_8))); +INSTANTIATE_TEST_CASE_P( + SSE2, Trans16x16HT, + ::testing::Values( + make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 0, + VPX_BITS_8), + make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 1, + VPX_BITS_8), + make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 2, + VPX_BITS_8), + make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 3, + VPX_BITS_8))); +INSTANTIATE_TEST_CASE_P(SSE2, PartialTrans16x16Test, + ::testing::Values(make_tuple(&vpx_fdct16x16_1_sse2, + VPX_BITS_8))); +#endif // HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE + +#if HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + SSE2, Trans16x16DCT, + ::testing::Values( + make_tuple(&vpx_highbd_fdct16x16_sse2, + &idct16x16_10, 0, VPX_BITS_10), + make_tuple(&vpx_highbd_fdct16x16_c, + &idct16x16_256_add_10_sse2, 0, VPX_BITS_10), + make_tuple(&vpx_highbd_fdct16x16_sse2, + &idct16x16_12, 0, VPX_BITS_12), + make_tuple(&vpx_highbd_fdct16x16_c, + &idct16x16_256_add_12_sse2, 0, VPX_BITS_12), + make_tuple(&vpx_fdct16x16_sse2, + &vpx_idct16x16_256_add_c, 0, VPX_BITS_8))); +INSTANTIATE_TEST_CASE_P( + SSE2, Trans16x16HT, + ::testing::Values( + make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_c, 0, VPX_BITS_8), + make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_c, 1, VPX_BITS_8), + make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_c, 2, VPX_BITS_8), + make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_c, 3, + VPX_BITS_8))); +// Optimizations take effect at a threshold of 3155, so we use a value close to +// that to test both branches. +INSTANTIATE_TEST_CASE_P( + SSE2, InvTrans16x16DCT, + ::testing::Values( + make_tuple(&idct16x16_10_add_10_c, + &idct16x16_10_add_10_sse2, 3167, VPX_BITS_10), + make_tuple(&idct16x16_10, + &idct16x16_256_add_10_sse2, 3167, VPX_BITS_10), + make_tuple(&idct16x16_10_add_12_c, + &idct16x16_10_add_12_sse2, 3167, VPX_BITS_12), + make_tuple(&idct16x16_12, + &idct16x16_256_add_12_sse2, 3167, VPX_BITS_12))); +INSTANTIATE_TEST_CASE_P(SSE2, PartialTrans16x16Test, + ::testing::Values(make_tuple(&vpx_fdct16x16_1_sse2, + VPX_BITS_8))); +#endif // HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE + +#if HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + MSA, Trans16x16DCT, + ::testing::Values( + make_tuple(&vpx_fdct16x16_msa, + &vpx_idct16x16_256_add_msa, 0, VPX_BITS_8))); +INSTANTIATE_TEST_CASE_P( + MSA, Trans16x16HT, + ::testing::Values( + make_tuple(&vp9_fht16x16_msa, &vp9_iht16x16_256_add_msa, 0, VPX_BITS_8), + make_tuple(&vp9_fht16x16_msa, &vp9_iht16x16_256_add_msa, 1, VPX_BITS_8), + make_tuple(&vp9_fht16x16_msa, &vp9_iht16x16_256_add_msa, 2, VPX_BITS_8), + make_tuple(&vp9_fht16x16_msa, &vp9_iht16x16_256_add_msa, 3, + VPX_BITS_8))); +INSTANTIATE_TEST_CASE_P(MSA, PartialTrans16x16Test, + ::testing::Values(make_tuple(&vpx_fdct16x16_1_msa, + VPX_BITS_8))); +#endif // HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +} // namespace
diff --git a/src/third_party/libvpx/test/dct32x32_test.cc b/src/third_party/libvpx/test/dct32x32_test.cc new file mode 100644 index 0000000..16d8825 --- /dev/null +++ b/src/third_party/libvpx/test/dct32x32_test.cc
@@ -0,0 +1,469 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <math.h> +#include <stdlib.h> +#include <string.h> + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "./vp9_rtcd.h" +#include "./vpx_config.h" +#include "./vpx_dsp_rtcd.h" +#include "test/acm_random.h" +#include "test/clear_system_state.h" +#include "test/register_state_check.h" +#include "test/util.h" +#include "vp9/common/vp9_entropy.h" +#include "vpx/vpx_codec.h" +#include "vpx/vpx_integer.h" +#include "vpx_ports/mem.h" + +using libvpx_test::ACMRandom; + +namespace { +#ifdef _MSC_VER +static int round(double x) { + if (x < 0) + return static_cast<int>(ceil(x - 0.5)); + else + return static_cast<int>(floor(x + 0.5)); +} +#endif + +const int kNumCoeffs = 1024; +const double kPi = 3.141592653589793238462643383279502884; +void reference_32x32_dct_1d(const double in[32], double out[32]) { + const double kInvSqrt2 = 0.707106781186547524400844362104; + for (int k = 0; k < 32; k++) { + out[k] = 0.0; + for (int n = 0; n < 32; n++) + out[k] += in[n] * cos(kPi * (2 * n + 1) * k / 64.0); + if (k == 0) + out[k] = out[k] * kInvSqrt2; + } +} + +void reference_32x32_dct_2d(const int16_t input[kNumCoeffs], + double output[kNumCoeffs]) { + // First transform columns + for (int i = 0; i < 32; ++i) { + double temp_in[32], temp_out[32]; + for (int j = 0; j < 32; ++j) + temp_in[j] = input[j*32 + i]; + reference_32x32_dct_1d(temp_in, temp_out); + for (int j = 0; j < 32; ++j) + output[j * 32 + i] = temp_out[j]; + } + // Then transform rows + for (int i = 0; i < 32; ++i) { + double temp_in[32], temp_out[32]; + for (int j = 0; j < 32; ++j) + temp_in[j] = output[j + i*32]; + reference_32x32_dct_1d(temp_in, temp_out); + // Scale by some magic number + for (int j = 0; j < 32; ++j) + output[j + i * 32] = temp_out[j] / 4; + } +} + +typedef void (*FwdTxfmFunc)(const int16_t *in, tran_low_t *out, int stride); +typedef void (*InvTxfmFunc)(const tran_low_t *in, uint8_t *out, int stride); + +typedef std::tr1::tuple<FwdTxfmFunc, InvTxfmFunc, int, vpx_bit_depth_t> + Trans32x32Param; + +#if CONFIG_VP9_HIGHBITDEPTH +void idct32x32_10(const tran_low_t *in, uint8_t *out, int stride) { + vpx_highbd_idct32x32_1024_add_c(in, out, stride, 10); +} + +void idct32x32_12(const tran_low_t *in, uint8_t *out, int stride) { + vpx_highbd_idct32x32_1024_add_c(in, out, stride, 12); +} +#endif // CONFIG_VP9_HIGHBITDEPTH + +class Trans32x32Test : public ::testing::TestWithParam<Trans32x32Param> { + public: + virtual ~Trans32x32Test() {} + virtual void SetUp() { + fwd_txfm_ = GET_PARAM(0); + inv_txfm_ = GET_PARAM(1); + version_ = GET_PARAM(2); // 0: high precision forward transform + // 1: low precision version for rd loop + bit_depth_ = GET_PARAM(3); + mask_ = (1 << bit_depth_) - 1; + } + + virtual void TearDown() { libvpx_test::ClearSystemState(); } + + protected: + int version_; + vpx_bit_depth_t bit_depth_; + int mask_; + FwdTxfmFunc fwd_txfm_; + InvTxfmFunc inv_txfm_; +}; + +TEST_P(Trans32x32Test, AccuracyCheck) { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + uint32_t max_error = 0; + int64_t total_error = 0; + const int count_test_block = 10000; + DECLARE_ALIGNED(16, int16_t, test_input_block[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, test_temp_block[kNumCoeffs]); + DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]); + DECLARE_ALIGNED(16, uint8_t, src[kNumCoeffs]); +#if CONFIG_VP9_HIGHBITDEPTH + DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]); + DECLARE_ALIGNED(16, uint16_t, src16[kNumCoeffs]); +#endif + + for (int i = 0; i < count_test_block; ++i) { + // Initialize a test block with input range [-mask_, mask_]. + for (int j = 0; j < kNumCoeffs; ++j) { + if (bit_depth_ == VPX_BITS_8) { + src[j] = rnd.Rand8(); + dst[j] = rnd.Rand8(); + test_input_block[j] = src[j] - dst[j]; +#if CONFIG_VP9_HIGHBITDEPTH + } else { + src16[j] = rnd.Rand16() & mask_; + dst16[j] = rnd.Rand16() & mask_; + test_input_block[j] = src16[j] - dst16[j]; +#endif + } + } + + ASM_REGISTER_STATE_CHECK(fwd_txfm_(test_input_block, test_temp_block, 32)); + if (bit_depth_ == VPX_BITS_8) { + ASM_REGISTER_STATE_CHECK(inv_txfm_(test_temp_block, dst, 32)); +#if CONFIG_VP9_HIGHBITDEPTH + } else { + ASM_REGISTER_STATE_CHECK(inv_txfm_(test_temp_block, + CONVERT_TO_BYTEPTR(dst16), 32)); +#endif + } + + for (int j = 0; j < kNumCoeffs; ++j) { +#if CONFIG_VP9_HIGHBITDEPTH + const int32_t diff = + bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j]; +#else + const int32_t diff = dst[j] - src[j]; +#endif + const uint32_t error = diff * diff; + if (max_error < error) + max_error = error; + total_error += error; + } + } + + if (version_ == 1) { + max_error /= 2; + total_error /= 45; + } + + EXPECT_GE(1u << 2 * (bit_depth_ - 8), max_error) + << "Error: 32x32 FDCT/IDCT has an individual round-trip error > 1"; + + EXPECT_GE(count_test_block << 2 * (bit_depth_ - 8), total_error) + << "Error: 32x32 FDCT/IDCT has average round-trip error > 1 per block"; +} + +TEST_P(Trans32x32Test, CoeffCheck) { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + const int count_test_block = 1000; + + DECLARE_ALIGNED(16, int16_t, input_block[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, output_block[kNumCoeffs]); + + for (int i = 0; i < count_test_block; ++i) { + for (int j = 0; j < kNumCoeffs; ++j) + input_block[j] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_); + + const int stride = 32; + vpx_fdct32x32_c(input_block, output_ref_block, stride); + ASM_REGISTER_STATE_CHECK(fwd_txfm_(input_block, output_block, stride)); + + if (version_ == 0) { + for (int j = 0; j < kNumCoeffs; ++j) + EXPECT_EQ(output_block[j], output_ref_block[j]) + << "Error: 32x32 FDCT versions have mismatched coefficients"; + } else { + for (int j = 0; j < kNumCoeffs; ++j) + EXPECT_GE(6, abs(output_block[j] - output_ref_block[j])) + << "Error: 32x32 FDCT rd has mismatched coefficients"; + } + } +} + +TEST_P(Trans32x32Test, MemCheck) { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + const int count_test_block = 2000; + + DECLARE_ALIGNED(16, int16_t, input_extreme_block[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, output_block[kNumCoeffs]); + + for (int i = 0; i < count_test_block; ++i) { + // Initialize a test block with input range [-mask_, mask_]. + for (int j = 0; j < kNumCoeffs; ++j) { + input_extreme_block[j] = rnd.Rand8() & 1 ? mask_ : -mask_; + } + if (i == 0) { + for (int j = 0; j < kNumCoeffs; ++j) + input_extreme_block[j] = mask_; + } else if (i == 1) { + for (int j = 0; j < kNumCoeffs; ++j) + input_extreme_block[j] = -mask_; + } + + const int stride = 32; + vpx_fdct32x32_c(input_extreme_block, output_ref_block, stride); + ASM_REGISTER_STATE_CHECK( + fwd_txfm_(input_extreme_block, output_block, stride)); + + // The minimum quant value is 4. + for (int j = 0; j < kNumCoeffs; ++j) { + if (version_ == 0) { + EXPECT_EQ(output_block[j], output_ref_block[j]) + << "Error: 32x32 FDCT versions have mismatched coefficients"; + } else { + EXPECT_GE(6, abs(output_block[j] - output_ref_block[j])) + << "Error: 32x32 FDCT rd has mismatched coefficients"; + } + EXPECT_GE(4 * DCT_MAX_VALUE << (bit_depth_ - 8), abs(output_ref_block[j])) + << "Error: 32x32 FDCT C has coefficient larger than 4*DCT_MAX_VALUE"; + EXPECT_GE(4 * DCT_MAX_VALUE << (bit_depth_ - 8), abs(output_block[j])) + << "Error: 32x32 FDCT has coefficient larger than " + << "4*DCT_MAX_VALUE"; + } + } +} + +TEST_P(Trans32x32Test, InverseAccuracy) { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + const int count_test_block = 1000; + DECLARE_ALIGNED(16, int16_t, in[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, coeff[kNumCoeffs]); + DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]); + DECLARE_ALIGNED(16, uint8_t, src[kNumCoeffs]); +#if CONFIG_VP9_HIGHBITDEPTH + DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]); + DECLARE_ALIGNED(16, uint16_t, src16[kNumCoeffs]); +#endif + + for (int i = 0; i < count_test_block; ++i) { + double out_r[kNumCoeffs]; + + // Initialize a test block with input range [-255, 255] + for (int j = 0; j < kNumCoeffs; ++j) { + if (bit_depth_ == VPX_BITS_8) { + src[j] = rnd.Rand8(); + dst[j] = rnd.Rand8(); + in[j] = src[j] - dst[j]; +#if CONFIG_VP9_HIGHBITDEPTH + } else { + src16[j] = rnd.Rand16() & mask_; + dst16[j] = rnd.Rand16() & mask_; + in[j] = src16[j] - dst16[j]; +#endif + } + } + + reference_32x32_dct_2d(in, out_r); + for (int j = 0; j < kNumCoeffs; ++j) + coeff[j] = static_cast<tran_low_t>(round(out_r[j])); + if (bit_depth_ == VPX_BITS_8) { + ASM_REGISTER_STATE_CHECK(inv_txfm_(coeff, dst, 32)); +#if CONFIG_VP9_HIGHBITDEPTH + } else { + ASM_REGISTER_STATE_CHECK(inv_txfm_(coeff, CONVERT_TO_BYTEPTR(dst16), 32)); +#endif + } + for (int j = 0; j < kNumCoeffs; ++j) { +#if CONFIG_VP9_HIGHBITDEPTH + const int diff = + bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j]; +#else + const int diff = dst[j] - src[j]; +#endif + const int error = diff * diff; + EXPECT_GE(1, error) + << "Error: 32x32 IDCT has error " << error + << " at index " << j; + } + } +} + +class PartialTrans32x32Test + : public ::testing::TestWithParam< + std::tr1::tuple<FwdTxfmFunc, vpx_bit_depth_t> > { + public: + virtual ~PartialTrans32x32Test() {} + virtual void SetUp() { + fwd_txfm_ = GET_PARAM(0); + bit_depth_ = GET_PARAM(1); + } + + virtual void TearDown() { libvpx_test::ClearSystemState(); } + + protected: + vpx_bit_depth_t bit_depth_; + FwdTxfmFunc fwd_txfm_; +}; + +TEST_P(PartialTrans32x32Test, Extremes) { +#if CONFIG_VP9_HIGHBITDEPTH + const int16_t maxval = + static_cast<int16_t>(clip_pixel_highbd(1 << 30, bit_depth_)); +#else + const int16_t maxval = 255; +#endif + const int minval = -maxval; + DECLARE_ALIGNED(16, int16_t, input[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, output[kNumCoeffs]); + + for (int i = 0; i < kNumCoeffs; ++i) input[i] = maxval; + output[0] = 0; + ASM_REGISTER_STATE_CHECK(fwd_txfm_(input, output, 32)); + EXPECT_EQ((maxval * kNumCoeffs) >> 3, output[0]); + + for (int i = 0; i < kNumCoeffs; ++i) input[i] = minval; + output[0] = 0; + ASM_REGISTER_STATE_CHECK(fwd_txfm_(input, output, 32)); + EXPECT_EQ((minval * kNumCoeffs) >> 3, output[0]); +} + +TEST_P(PartialTrans32x32Test, Random) { +#if CONFIG_VP9_HIGHBITDEPTH + const int16_t maxval = + static_cast<int16_t>(clip_pixel_highbd(1 << 30, bit_depth_)); +#else + const int16_t maxval = 255; +#endif + DECLARE_ALIGNED(16, int16_t, input[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, output[kNumCoeffs]); + ACMRandom rnd(ACMRandom::DeterministicSeed()); + + int sum = 0; + for (int i = 0; i < kNumCoeffs; ++i) { + const int val = (i & 1) ? -rnd(maxval + 1) : rnd(maxval + 1); + input[i] = val; + sum += val; + } + output[0] = 0; + ASM_REGISTER_STATE_CHECK(fwd_txfm_(input, output, 32)); + EXPECT_EQ(sum >> 3, output[0]); +} + +using std::tr1::make_tuple; + +#if CONFIG_VP9_HIGHBITDEPTH +INSTANTIATE_TEST_CASE_P( + C, Trans32x32Test, + ::testing::Values( + make_tuple(&vpx_highbd_fdct32x32_c, + &idct32x32_10, 0, VPX_BITS_10), + make_tuple(&vpx_highbd_fdct32x32_rd_c, + &idct32x32_10, 1, VPX_BITS_10), + make_tuple(&vpx_highbd_fdct32x32_c, + &idct32x32_12, 0, VPX_BITS_12), + make_tuple(&vpx_highbd_fdct32x32_rd_c, + &idct32x32_12, 1, VPX_BITS_12), + make_tuple(&vpx_fdct32x32_c, + &vpx_idct32x32_1024_add_c, 0, VPX_BITS_8), + make_tuple(&vpx_fdct32x32_rd_c, + &vpx_idct32x32_1024_add_c, 1, VPX_BITS_8))); +INSTANTIATE_TEST_CASE_P( + C, PartialTrans32x32Test, + ::testing::Values(make_tuple(&vpx_highbd_fdct32x32_1_c, VPX_BITS_8), + make_tuple(&vpx_highbd_fdct32x32_1_c, VPX_BITS_10), + make_tuple(&vpx_highbd_fdct32x32_1_c, VPX_BITS_12))); +#else +INSTANTIATE_TEST_CASE_P( + C, Trans32x32Test, + ::testing::Values( + make_tuple(&vpx_fdct32x32_c, + &vpx_idct32x32_1024_add_c, 0, VPX_BITS_8), + make_tuple(&vpx_fdct32x32_rd_c, + &vpx_idct32x32_1024_add_c, 1, VPX_BITS_8))); +INSTANTIATE_TEST_CASE_P(C, PartialTrans32x32Test, + ::testing::Values(make_tuple(&vpx_fdct32x32_1_c, + VPX_BITS_8))); +#endif // CONFIG_VP9_HIGHBITDEPTH + +#if HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + NEON, Trans32x32Test, + ::testing::Values( + make_tuple(&vpx_fdct32x32_c, + &vpx_idct32x32_1024_add_neon, 0, VPX_BITS_8), + make_tuple(&vpx_fdct32x32_rd_c, + &vpx_idct32x32_1024_add_neon, 1, VPX_BITS_8))); +#endif // HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE + +#if HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + SSE2, Trans32x32Test, + ::testing::Values( + make_tuple(&vpx_fdct32x32_sse2, + &vpx_idct32x32_1024_add_sse2, 0, VPX_BITS_8), + make_tuple(&vpx_fdct32x32_rd_sse2, + &vpx_idct32x32_1024_add_sse2, 1, VPX_BITS_8))); +INSTANTIATE_TEST_CASE_P(SSE2, PartialTrans32x32Test, + ::testing::Values(make_tuple(&vpx_fdct32x32_1_sse2, + VPX_BITS_8))); +#endif // HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE + +#if HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + SSE2, Trans32x32Test, + ::testing::Values( + make_tuple(&vpx_highbd_fdct32x32_sse2, &idct32x32_10, 0, VPX_BITS_10), + make_tuple(&vpx_highbd_fdct32x32_rd_sse2, &idct32x32_10, 1, + VPX_BITS_10), + make_tuple(&vpx_highbd_fdct32x32_sse2, &idct32x32_12, 0, VPX_BITS_12), + make_tuple(&vpx_highbd_fdct32x32_rd_sse2, &idct32x32_12, 1, + VPX_BITS_12), + make_tuple(&vpx_fdct32x32_sse2, &vpx_idct32x32_1024_add_c, 0, + VPX_BITS_8), + make_tuple(&vpx_fdct32x32_rd_sse2, &vpx_idct32x32_1024_add_c, 1, + VPX_BITS_8))); +INSTANTIATE_TEST_CASE_P(SSE2, PartialTrans32x32Test, + ::testing::Values(make_tuple(&vpx_fdct32x32_1_sse2, + VPX_BITS_8))); +#endif // HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE + +#if HAVE_AVX2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + AVX2, Trans32x32Test, + ::testing::Values( + make_tuple(&vpx_fdct32x32_avx2, + &vpx_idct32x32_1024_add_sse2, 0, VPX_BITS_8), + make_tuple(&vpx_fdct32x32_rd_avx2, + &vpx_idct32x32_1024_add_sse2, 1, VPX_BITS_8))); +#endif // HAVE_AVX2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE + +#if HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + MSA, Trans32x32Test, + ::testing::Values( + make_tuple(&vpx_fdct32x32_msa, + &vpx_idct32x32_1024_add_msa, 0, VPX_BITS_8), + make_tuple(&vpx_fdct32x32_rd_msa, + &vpx_idct32x32_1024_add_msa, 1, VPX_BITS_8))); +INSTANTIATE_TEST_CASE_P(MSA, PartialTrans32x32Test, + ::testing::Values(make_tuple(&vpx_fdct32x32_1_msa, + VPX_BITS_8))); +#endif // HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +} // namespace
diff --git a/src/third_party/libvpx/test/decode_api_test.cc b/src/third_party/libvpx/test/decode_api_test.cc new file mode 100644 index 0000000..318351b --- /dev/null +++ b/src/third_party/libvpx/test/decode_api_test.cc
@@ -0,0 +1,151 @@ +/* + * Copyright (c) 2014 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "./vpx_config.h" +#include "test/ivf_video_source.h" +#include "vpx/vp8dx.h" +#include "vpx/vpx_decoder.h" + +namespace { + +#define NELEMENTS(x) static_cast<int>(sizeof(x) / sizeof(x[0])) + +TEST(DecodeAPI, InvalidParams) { + static const vpx_codec_iface_t *kCodecs[] = { +#if CONFIG_VP8_DECODER + &vpx_codec_vp8_dx_algo, +#endif +#if CONFIG_VP9_DECODER + &vpx_codec_vp9_dx_algo, +#endif +#if CONFIG_VP10_DECODER + &vpx_codec_vp10_dx_algo, +#endif + }; + uint8_t buf[1] = {0}; + vpx_codec_ctx_t dec; + + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_dec_init(NULL, NULL, NULL, 0)); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_dec_init(&dec, NULL, NULL, 0)); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_decode(NULL, NULL, 0, NULL, 0)); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_decode(NULL, buf, 0, NULL, 0)); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, + vpx_codec_decode(NULL, buf, NELEMENTS(buf), NULL, 0)); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, + vpx_codec_decode(NULL, NULL, NELEMENTS(buf), NULL, 0)); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_destroy(NULL)); + EXPECT_TRUE(vpx_codec_error(NULL) != NULL); + + for (int i = 0; i < NELEMENTS(kCodecs); ++i) { + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, + vpx_codec_dec_init(NULL, kCodecs[i], NULL, 0)); + + EXPECT_EQ(VPX_CODEC_OK, vpx_codec_dec_init(&dec, kCodecs[i], NULL, 0)); + EXPECT_EQ(VPX_CODEC_UNSUP_BITSTREAM, + vpx_codec_decode(&dec, buf, NELEMENTS(buf), NULL, 0)); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, + vpx_codec_decode(&dec, NULL, NELEMENTS(buf), NULL, 0)); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, + vpx_codec_decode(&dec, buf, 0, NULL, 0)); + + EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&dec)); + } +} + +#if CONFIG_VP8_DECODER +TEST(DecodeAPI, OptionalParams) { + vpx_codec_ctx_t dec; + +#if CONFIG_ERROR_CONCEALMENT + EXPECT_EQ(VPX_CODEC_OK, vpx_codec_dec_init(&dec, &vpx_codec_vp8_dx_algo, NULL, + VPX_CODEC_USE_ERROR_CONCEALMENT)); +#else + EXPECT_EQ(VPX_CODEC_INCAPABLE, + vpx_codec_dec_init(&dec, &vpx_codec_vp8_dx_algo, NULL, + VPX_CODEC_USE_ERROR_CONCEALMENT)); +#endif // CONFIG_ERROR_CONCEALMENT +} +#endif // CONFIG_VP8_DECODER + +#if CONFIG_VP9_DECODER +// Test VP9 codec controls after a decode error to ensure the code doesn't +// misbehave. +void TestVp9Controls(vpx_codec_ctx_t *dec) { + static const int kControls[] = { + VP8D_GET_LAST_REF_UPDATES, + VP8D_GET_FRAME_CORRUPTED, + VP9D_GET_DISPLAY_SIZE, + VP9D_GET_FRAME_SIZE + }; + int val[2]; + + for (int i = 0; i < NELEMENTS(kControls); ++i) { + const vpx_codec_err_t res = vpx_codec_control_(dec, kControls[i], val); + switch (kControls[i]) { + case VP8D_GET_FRAME_CORRUPTED: + EXPECT_EQ(VPX_CODEC_ERROR, res) << kControls[i]; + break; + default: + EXPECT_EQ(VPX_CODEC_OK, res) << kControls[i]; + break; + } + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, + vpx_codec_control_(dec, kControls[i], NULL)); + } + + vp9_ref_frame_t ref; + ref.idx = 0; + EXPECT_EQ(VPX_CODEC_ERROR, vpx_codec_control(dec, VP9_GET_REFERENCE, &ref)); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, + vpx_codec_control(dec, VP9_GET_REFERENCE, NULL)); + + vpx_ref_frame_t ref_copy; + const int width = 352; + const int height = 288; + ASSERT_TRUE( + vpx_img_alloc(&ref_copy.img, VPX_IMG_FMT_I420, width, height, 1) != NULL); + ref_copy.frame_type = VP8_LAST_FRAME; + EXPECT_EQ(VPX_CODEC_ERROR, + vpx_codec_control(dec, VP8_COPY_REFERENCE, &ref_copy)); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, + vpx_codec_control(dec, VP8_COPY_REFERENCE, NULL)); + vpx_img_free(&ref_copy.img); +} + +TEST(DecodeAPI, Vp9InvalidDecode) { + const vpx_codec_iface_t *const codec = &vpx_codec_vp9_dx_algo; + const char filename[] = + "invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf"; + libvpx_test::IVFVideoSource video(filename); + video.Init(); + video.Begin(); + ASSERT_TRUE(!HasFailure()); + + vpx_codec_ctx_t dec; + EXPECT_EQ(VPX_CODEC_OK, vpx_codec_dec_init(&dec, codec, NULL, 0)); + const uint32_t frame_size = static_cast<uint32_t>(video.frame_size()); +#if CONFIG_VP9_HIGHBITDEPTH + EXPECT_EQ(VPX_CODEC_MEM_ERROR, + vpx_codec_decode(&dec, video.cxdata(), frame_size, NULL, 0)); +#else + EXPECT_EQ(VPX_CODEC_UNSUP_BITSTREAM, + vpx_codec_decode(&dec, video.cxdata(), frame_size, NULL, 0)); +#endif + vpx_codec_iter_t iter = NULL; + EXPECT_EQ(NULL, vpx_codec_get_frame(&dec, &iter)); + + TestVp9Controls(&dec); + EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&dec)); +} +#endif // CONFIG_VP9_DECODER + +} // namespace
diff --git a/src/third_party/libvpx/test/decode_perf_test.cc b/src/third_party/libvpx/test/decode_perf_test.cc new file mode 100644 index 0000000..c24d517 --- /dev/null +++ b/src/third_party/libvpx/test/decode_perf_test.cc
@@ -0,0 +1,273 @@ +/* + * Copyright (c) 2013 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <string> +#include "test/codec_factory.h" +#include "test/decode_test_driver.h" +#include "test/encode_test_driver.h" +#include "test/i420_video_source.h" +#include "test/ivf_video_source.h" +#include "test/md5_helper.h" +#include "test/util.h" +#include "test/webm_video_source.h" +#include "vpx_ports/vpx_timer.h" +#include "./ivfenc.h" +#include "./vpx_version.h" + +using std::tr1::make_tuple; + +namespace { + +#define VIDEO_NAME 0 +#define THREADS 1 + +const int kMaxPsnr = 100; +const double kUsecsInSec = 1000000.0; +const char kNewEncodeOutputFile[] = "new_encode.ivf"; + +/* + DecodePerfTest takes a tuple of filename + number of threads to decode with + */ +typedef std::tr1::tuple<const char *, unsigned> DecodePerfParam; + +const DecodePerfParam kVP9DecodePerfVectors[] = { + make_tuple("vp90-2-bbb_426x240_tile_1x1_180kbps.webm", 1), + make_tuple("vp90-2-bbb_640x360_tile_1x2_337kbps.webm", 2), + make_tuple("vp90-2-bbb_854x480_tile_1x2_651kbps.webm", 2), + make_tuple("vp90-2-bbb_1280x720_tile_1x4_1310kbps.webm", 4), + make_tuple("vp90-2-bbb_1920x1080_tile_1x1_2581kbps.webm", 1), + make_tuple("vp90-2-bbb_1920x1080_tile_1x4_2586kbps.webm", 4), + make_tuple("vp90-2-bbb_1920x1080_tile_1x4_fpm_2304kbps.webm", 4), + make_tuple("vp90-2-sintel_426x182_tile_1x1_171kbps.webm", 1), + make_tuple("vp90-2-sintel_640x272_tile_1x2_318kbps.webm", 2), + make_tuple("vp90-2-sintel_854x364_tile_1x2_621kbps.webm", 2), + make_tuple("vp90-2-sintel_1280x546_tile_1x4_1257kbps.webm", 4), + make_tuple("vp90-2-sintel_1920x818_tile_1x4_fpm_2279kbps.webm", 4), + make_tuple("vp90-2-tos_426x178_tile_1x1_181kbps.webm", 1), + make_tuple("vp90-2-tos_640x266_tile_1x2_336kbps.webm", 2), + make_tuple("vp90-2-tos_854x356_tile_1x2_656kbps.webm", 2), + make_tuple("vp90-2-tos_854x356_tile_1x2_fpm_546kbps.webm", 2), + make_tuple("vp90-2-tos_1280x534_tile_1x4_1306kbps.webm", 4), + make_tuple("vp90-2-tos_1280x534_tile_1x4_fpm_952kbps.webm", 4), + make_tuple("vp90-2-tos_1920x800_tile_1x4_fpm_2335kbps.webm", 4), +}; + +/* + In order to reflect real world performance as much as possible, Perf tests + *DO NOT* do any correctness checks. Please run them alongside correctness + tests to ensure proper codec integrity. Furthermore, in this test we + deliberately limit the amount of system calls we make to avoid OS + preemption. + + TODO(joshualitt) create a more detailed perf measurement test to collect + power/temp/min max frame decode times/etc + */ + +class DecodePerfTest : public ::testing::TestWithParam<DecodePerfParam> { +}; + +TEST_P(DecodePerfTest, PerfTest) { + const char *const video_name = GET_PARAM(VIDEO_NAME); + const unsigned threads = GET_PARAM(THREADS); + + libvpx_test::WebMVideoSource video(video_name); + video.Init(); + + vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t(); + cfg.threads = threads; + libvpx_test::VP9Decoder decoder(cfg, 0); + + vpx_usec_timer t; + vpx_usec_timer_start(&t); + + for (video.Begin(); video.cxdata() != NULL; video.Next()) { + decoder.DecodeFrame(video.cxdata(), video.frame_size()); + } + + vpx_usec_timer_mark(&t); + const double elapsed_secs = double(vpx_usec_timer_elapsed(&t)) + / kUsecsInSec; + const unsigned frames = video.frame_number(); + const double fps = double(frames) / elapsed_secs; + + printf("{\n"); + printf("\t\"type\" : \"decode_perf_test\",\n"); + printf("\t\"version\" : \"%s\",\n", VERSION_STRING_NOSP); + printf("\t\"videoName\" : \"%s\",\n", video_name); + printf("\t\"threadCount\" : %u,\n", threads); + printf("\t\"decodeTimeSecs\" : %f,\n", elapsed_secs); + printf("\t\"totalFrames\" : %u,\n", frames); + printf("\t\"framesPerSecond\" : %f\n", fps); + printf("}\n"); +} + +INSTANTIATE_TEST_CASE_P(VP9, DecodePerfTest, + ::testing::ValuesIn(kVP9DecodePerfVectors)); + +class VP9NewEncodeDecodePerfTest : + public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> { + protected: + VP9NewEncodeDecodePerfTest() + : EncoderTest(GET_PARAM(0)), + encoding_mode_(GET_PARAM(1)), + speed_(0), + outfile_(0), + out_frames_(0) { + } + + virtual ~VP9NewEncodeDecodePerfTest() {} + + virtual void SetUp() { + InitializeConfig(); + SetMode(encoding_mode_); + + cfg_.g_lag_in_frames = 25; + cfg_.rc_min_quantizer = 2; + cfg_.rc_max_quantizer = 56; + cfg_.rc_dropframe_thresh = 0; + cfg_.rc_undershoot_pct = 50; + cfg_.rc_overshoot_pct = 50; + cfg_.rc_buf_sz = 1000; + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 600; + cfg_.rc_resize_allowed = 0; + cfg_.rc_end_usage = VPX_VBR; + } + + virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, + ::libvpx_test::Encoder *encoder) { + if (video->frame() == 1) { + encoder->Control(VP8E_SET_CPUUSED, speed_); + encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING, 1); + encoder->Control(VP9E_SET_TILE_COLUMNS, 2); + } + } + + virtual void BeginPassHook(unsigned int /*pass*/) { + const std::string data_path = getenv("LIBVPX_TEST_DATA_PATH"); + const std::string path_to_source = data_path + "/" + kNewEncodeOutputFile; + outfile_ = fopen(path_to_source.c_str(), "wb"); + ASSERT_TRUE(outfile_ != NULL); + } + + virtual void EndPassHook() { + if (outfile_ != NULL) { + if (!fseek(outfile_, 0, SEEK_SET)) + ivf_write_file_header(outfile_, &cfg_, VP9_FOURCC, out_frames_); + fclose(outfile_); + outfile_ = NULL; + } + } + + virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) { + ++out_frames_; + + // Write initial file header if first frame. + if (pkt->data.frame.pts == 0) + ivf_write_file_header(outfile_, &cfg_, VP9_FOURCC, out_frames_); + + // Write frame header and data. + ivf_write_frame_header(outfile_, out_frames_, pkt->data.frame.sz); + ASSERT_EQ(fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile_), + pkt->data.frame.sz); + } + + virtual bool DoDecode() { return false; } + + void set_speed(unsigned int speed) { + speed_ = speed; + } + + private: + libvpx_test::TestMode encoding_mode_; + uint32_t speed_; + FILE *outfile_; + uint32_t out_frames_; +}; + +struct EncodePerfTestVideo { + EncodePerfTestVideo(const char *name_, uint32_t width_, uint32_t height_, + uint32_t bitrate_, int frames_) + : name(name_), + width(width_), + height(height_), + bitrate(bitrate_), + frames(frames_) {} + const char *name; + uint32_t width; + uint32_t height; + uint32_t bitrate; + int frames; +}; + +const EncodePerfTestVideo kVP9EncodePerfTestVectors[] = { + EncodePerfTestVideo("niklas_1280_720_30.yuv", 1280, 720, 600, 470), +}; + +TEST_P(VP9NewEncodeDecodePerfTest, PerfTest) { + SetUp(); + + // TODO(JBB): Make this work by going through the set of given files. + const int i = 0; + const vpx_rational timebase = { 33333333, 1000000000 }; + cfg_.g_timebase = timebase; + cfg_.rc_target_bitrate = kVP9EncodePerfTestVectors[i].bitrate; + + init_flags_ = VPX_CODEC_USE_PSNR; + + const char *video_name = kVP9EncodePerfTestVectors[i].name; + libvpx_test::I420VideoSource video( + video_name, + kVP9EncodePerfTestVectors[i].width, + kVP9EncodePerfTestVectors[i].height, + timebase.den, timebase.num, 0, + kVP9EncodePerfTestVectors[i].frames); + set_speed(2); + + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + + const uint32_t threads = 4; + + libvpx_test::IVFVideoSource decode_video(kNewEncodeOutputFile); + decode_video.Init(); + + vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t(); + cfg.threads = threads; + libvpx_test::VP9Decoder decoder(cfg, 0); + + vpx_usec_timer t; + vpx_usec_timer_start(&t); + + for (decode_video.Begin(); decode_video.cxdata() != NULL; + decode_video.Next()) { + decoder.DecodeFrame(decode_video.cxdata(), decode_video.frame_size()); + } + + vpx_usec_timer_mark(&t); + const double elapsed_secs = + static_cast<double>(vpx_usec_timer_elapsed(&t)) / kUsecsInSec; + const unsigned decode_frames = decode_video.frame_number(); + const double fps = static_cast<double>(decode_frames) / elapsed_secs; + + printf("{\n"); + printf("\t\"type\" : \"decode_perf_test\",\n"); + printf("\t\"version\" : \"%s\",\n", VERSION_STRING_NOSP); + printf("\t\"videoName\" : \"%s\",\n", kNewEncodeOutputFile); + printf("\t\"threadCount\" : %u,\n", threads); + printf("\t\"decodeTimeSecs\" : %f,\n", elapsed_secs); + printf("\t\"totalFrames\" : %u,\n", decode_frames); + printf("\t\"framesPerSecond\" : %f\n", fps); + printf("}\n"); +} + +VP9_INSTANTIATE_TEST_CASE( + VP9NewEncodeDecodePerfTest, ::testing::Values(::libvpx_test::kTwoPassGood)); +} // namespace
diff --git a/src/third_party/libvpx/test/decode_test_driver.cc b/src/third_party/libvpx/test/decode_test_driver.cc new file mode 100644 index 0000000..ad861c3 --- /dev/null +++ b/src/third_party/libvpx/test/decode_test_driver.cc
@@ -0,0 +1,123 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "test/codec_factory.h" +#include "test/decode_test_driver.h" +#include "test/register_state_check.h" +#include "test/video_source.h" + +namespace libvpx_test { + +const char kVP8Name[] = "WebM Project VP8"; + +vpx_codec_err_t Decoder::PeekStream(const uint8_t *cxdata, size_t size, + vpx_codec_stream_info_t *stream_info) { + return vpx_codec_peek_stream_info(CodecInterface(), + cxdata, static_cast<unsigned int>(size), + stream_info); +} + +vpx_codec_err_t Decoder::DecodeFrame(const uint8_t *cxdata, size_t size) { + return DecodeFrame(cxdata, size, NULL); +} + +vpx_codec_err_t Decoder::DecodeFrame(const uint8_t *cxdata, size_t size, + void *user_priv) { + vpx_codec_err_t res_dec; + InitOnce(); + API_REGISTER_STATE_CHECK( + res_dec = vpx_codec_decode(&decoder_, + cxdata, static_cast<unsigned int>(size), + user_priv, 0)); + return res_dec; +} + +bool Decoder::IsVP8() const { + const char *codec_name = GetDecoderName(); + return strncmp(kVP8Name, codec_name, sizeof(kVP8Name) - 1) == 0; +} + +void DecoderTest::HandlePeekResult(Decoder *const decoder, + CompressedVideoSource *video, + const vpx_codec_err_t res_peek) { + const bool is_vp8 = decoder->IsVP8(); + if (is_vp8) { + /* Vp8's implementation of PeekStream returns an error if the frame you + * pass it is not a keyframe, so we only expect VPX_CODEC_OK on the first + * frame, which must be a keyframe. */ + if (video->frame_number() == 0) + ASSERT_EQ(VPX_CODEC_OK, res_peek) << "Peek return failed: " + << vpx_codec_err_to_string(res_peek); + } else { + /* The Vp9 implementation of PeekStream returns an error only if the + * data passed to it isn't a valid Vp9 chunk. */ + ASSERT_EQ(VPX_CODEC_OK, res_peek) << "Peek return failed: " + << vpx_codec_err_to_string(res_peek); + } +} + +void DecoderTest::RunLoop(CompressedVideoSource *video, + const vpx_codec_dec_cfg_t &dec_cfg) { + Decoder* const decoder = codec_->CreateDecoder(dec_cfg, flags_, 0); + ASSERT_TRUE(decoder != NULL); + bool end_of_file = false; + + // Decode frames. + for (video->Begin(); !::testing::Test::HasFailure() && !end_of_file; + video->Next()) { + PreDecodeFrameHook(*video, decoder); + + vpx_codec_stream_info_t stream_info; + stream_info.sz = sizeof(stream_info); + + if (video->cxdata() != NULL) { + const vpx_codec_err_t res_peek = decoder->PeekStream(video->cxdata(), + video->frame_size(), + &stream_info); + HandlePeekResult(decoder, video, res_peek); + ASSERT_FALSE(::testing::Test::HasFailure()); + + vpx_codec_err_t res_dec = decoder->DecodeFrame(video->cxdata(), + video->frame_size()); + if (!HandleDecodeResult(res_dec, *video, decoder)) + break; + } else { + // Signal end of the file to the decoder. + const vpx_codec_err_t res_dec = decoder->DecodeFrame(NULL, 0); + ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError(); + end_of_file = true; + } + + DxDataIterator dec_iter = decoder->GetDxData(); + const vpx_image_t *img = NULL; + + // Get decompressed data + while ((img = dec_iter.Next())) + DecompressedFrameHook(*img, video->frame_number()); + } + delete decoder; +} + +void DecoderTest::RunLoop(CompressedVideoSource *video) { + vpx_codec_dec_cfg_t dec_cfg = vpx_codec_dec_cfg_t(); + RunLoop(video, dec_cfg); +} + +void DecoderTest::set_cfg(const vpx_codec_dec_cfg_t &dec_cfg) { + memcpy(&cfg_, &dec_cfg, sizeof(cfg_)); +} + +void DecoderTest::set_flags(const vpx_codec_flags_t flags) { + flags_ = flags; +} + +} // namespace libvpx_test
diff --git a/src/third_party/libvpx/test/decode_test_driver.h b/src/third_party/libvpx/test/decode_test_driver.h new file mode 100644 index 0000000..f566c53 --- /dev/null +++ b/src/third_party/libvpx/test/decode_test_driver.h
@@ -0,0 +1,181 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef TEST_DECODE_TEST_DRIVER_H_ +#define TEST_DECODE_TEST_DRIVER_H_ +#include <cstring> +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "./vpx_config.h" +#include "vpx/vpx_decoder.h" + +namespace libvpx_test { + +class CodecFactory; +class CompressedVideoSource; + +// Provides an object to handle decoding output +class DxDataIterator { + public: + explicit DxDataIterator(vpx_codec_ctx_t *decoder) + : decoder_(decoder), iter_(NULL) {} + + const vpx_image_t *Next() { + return vpx_codec_get_frame(decoder_, &iter_); + } + + private: + vpx_codec_ctx_t *decoder_; + vpx_codec_iter_t iter_; +}; + +// Provides a simplified interface to manage one video decoding. +// Similar to Encoder class, the exact services should be added +// as more tests are added. +class Decoder { + public: + Decoder(vpx_codec_dec_cfg_t cfg, unsigned long deadline) + : cfg_(cfg), flags_(0), deadline_(deadline), init_done_(false) { + memset(&decoder_, 0, sizeof(decoder_)); + } + + Decoder(vpx_codec_dec_cfg_t cfg, const vpx_codec_flags_t flag, + unsigned long deadline) // NOLINT + : cfg_(cfg), flags_(flag), deadline_(deadline), init_done_(false) { + memset(&decoder_, 0, sizeof(decoder_)); + } + + virtual ~Decoder() { + vpx_codec_destroy(&decoder_); + } + + vpx_codec_err_t PeekStream(const uint8_t *cxdata, size_t size, + vpx_codec_stream_info_t *stream_info); + + vpx_codec_err_t DecodeFrame(const uint8_t *cxdata, size_t size); + + vpx_codec_err_t DecodeFrame(const uint8_t *cxdata, size_t size, + void *user_priv); + + DxDataIterator GetDxData() { + return DxDataIterator(&decoder_); + } + + void set_deadline(unsigned long deadline) { + deadline_ = deadline; + } + + void Control(int ctrl_id, int arg) { + Control(ctrl_id, arg, VPX_CODEC_OK); + } + + void Control(int ctrl_id, const void *arg) { + InitOnce(); + const vpx_codec_err_t res = vpx_codec_control_(&decoder_, ctrl_id, arg); + ASSERT_EQ(VPX_CODEC_OK, res) << DecodeError(); + } + + void Control(int ctrl_id, int arg, vpx_codec_err_t expected_value) { + InitOnce(); + const vpx_codec_err_t res = vpx_codec_control_(&decoder_, ctrl_id, arg); + ASSERT_EQ(expected_value, res) << DecodeError(); + } + + const char* DecodeError() { + const char *detail = vpx_codec_error_detail(&decoder_); + return detail ? detail : vpx_codec_error(&decoder_); + } + + // Passes the external frame buffer information to libvpx. + vpx_codec_err_t SetFrameBufferFunctions( + vpx_get_frame_buffer_cb_fn_t cb_get, + vpx_release_frame_buffer_cb_fn_t cb_release, void *user_priv) { + InitOnce(); + return vpx_codec_set_frame_buffer_functions( + &decoder_, cb_get, cb_release, user_priv); + } + + const char* GetDecoderName() const { + return vpx_codec_iface_name(CodecInterface()); + } + + bool IsVP8() const; + + vpx_codec_ctx_t * GetDecoder() { + return &decoder_; + } + + protected: + virtual vpx_codec_iface_t* CodecInterface() const = 0; + + void InitOnce() { + if (!init_done_) { + const vpx_codec_err_t res = vpx_codec_dec_init(&decoder_, + CodecInterface(), + &cfg_, flags_); + ASSERT_EQ(VPX_CODEC_OK, res) << DecodeError(); + init_done_ = true; + } + } + + vpx_codec_ctx_t decoder_; + vpx_codec_dec_cfg_t cfg_; + vpx_codec_flags_t flags_; + unsigned int deadline_; + bool init_done_; +}; + +// Common test functionality for all Decoder tests. +class DecoderTest { + public: + // Main decoding loop + virtual void RunLoop(CompressedVideoSource *video); + virtual void RunLoop(CompressedVideoSource *video, + const vpx_codec_dec_cfg_t &dec_cfg); + + virtual void set_cfg(const vpx_codec_dec_cfg_t &dec_cfg); + virtual void set_flags(const vpx_codec_flags_t flags); + + // Hook to be called before decompressing every frame. + virtual void PreDecodeFrameHook(const CompressedVideoSource& /*video*/, + Decoder* /*decoder*/) {} + + // Hook to be called to handle decode result. Return true to continue. + virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec, + const CompressedVideoSource& /*video*/, + Decoder *decoder) { + EXPECT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError(); + return VPX_CODEC_OK == res_dec; + } + + // Hook to be called on every decompressed frame. + virtual void DecompressedFrameHook(const vpx_image_t& /*img*/, + const unsigned int /*frame_number*/) {} + + // Hook to be called on peek result + virtual void HandlePeekResult(Decoder* const decoder, + CompressedVideoSource *video, + const vpx_codec_err_t res_peek); + + protected: + explicit DecoderTest(const CodecFactory *codec) + : codec_(codec), + cfg_(), + flags_(0) {} + + virtual ~DecoderTest() {} + + const CodecFactory *codec_; + vpx_codec_dec_cfg_t cfg_; + vpx_codec_flags_t flags_; +}; + +} // namespace libvpx_test + +#endif // TEST_DECODE_TEST_DRIVER_H_
diff --git a/src/third_party/libvpx/test/decode_to_md5.sh b/src/third_party/libvpx/test/decode_to_md5.sh new file mode 100755 index 0000000..854b74f --- /dev/null +++ b/src/third_party/libvpx/test/decode_to_md5.sh
@@ -0,0 +1,73 @@ +#!/bin/sh +## +## Copyright (c) 2014 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## +## This file tests the libvpx decode_to_md5 example. To add new tests to this +## file, do the following: +## 1. Write a shell function (this is your test). +## 2. Add the function to decode_to_md5_tests (on a new line). +## +. $(dirname $0)/tools_common.sh + +# Environment check: Make sure input is available: +# $VP8_IVF_FILE and $VP9_IVF_FILE are required. +decode_to_md5_verify_environment() { + if [ ! -e "${VP8_IVF_FILE}" ] || [ ! -e "${VP9_IVF_FILE}" ]; then + echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH." + return 1 + fi +} + +# Runs decode_to_md5 on $1 and captures the md5 sum for the final frame. $2 is +# interpreted as codec name and used solely to name the output file. $3 is the +# expected md5 sum: It must match that of the final frame. +decode_to_md5() { + local decoder="${LIBVPX_BIN_PATH}/decode_to_md5${VPX_TEST_EXE_SUFFIX}" + local input_file="$1" + local codec="$2" + local expected_md5="$3" + local output_file="${VPX_TEST_OUTPUT_DIR}/decode_to_md5_${codec}" + + if [ ! -x "${decoder}" ]; then + elog "${decoder} does not exist or is not executable." + return 1 + fi + + eval "${VPX_TEST_PREFIX}" "${decoder}" "${input_file}" "${output_file}" \ + ${devnull} + + [ -e "${output_file}" ] || return 1 + + local md5_last_frame="$(tail -n1 "${output_file}" | awk '{print $1}')" + local actual_md5="$(echo "${md5_last_frame}" | awk '{print $1}')" + [ "${actual_md5}" = "${expected_md5}" ] || return 1 +} + +decode_to_md5_vp8() { + # expected MD5 sum for the last frame. + local expected_md5="56794d911b02190212bca92f88ad60c6" + + if [ "$(vp8_decode_available)" = "yes" ]; then + decode_to_md5 "${VP8_IVF_FILE}" "vp8" "${expected_md5}" + fi +} + +decode_to_md5_vp9() { + # expected MD5 sum for the last frame. + local expected_md5="2952c0eae93f3dadd1aa84c50d3fd6d2" + + if [ "$(vp9_decode_available)" = "yes" ]; then + decode_to_md5 "${VP9_IVF_FILE}" "vp9" "${expected_md5}" + fi +} + +decode_to_md5_tests="decode_to_md5_vp8 + decode_to_md5_vp9" + +run_tests decode_to_md5_verify_environment "${decode_to_md5_tests}"
diff --git a/src/third_party/libvpx/test/decode_with_drops.sh b/src/third_party/libvpx/test/decode_with_drops.sh new file mode 100755 index 0000000..9b2edb6 --- /dev/null +++ b/src/third_party/libvpx/test/decode_with_drops.sh
@@ -0,0 +1,79 @@ +#!/bin/sh +## +## Copyright (c) 2014 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## +## This file tests the libvpx decode_with_drops example. To add new tests to +## this file, do the following: +## 1. Write a shell function (this is your test). +## 2. Add the function to decode_with_drops_tests (on a new line). +## +. $(dirname $0)/tools_common.sh + +# Environment check: Make sure input is available: +# $VP8_IVF_FILE and $VP9_IVF_FILE are required. +decode_with_drops_verify_environment() { + if [ ! -e "${VP8_IVF_FILE}" ] || [ ! -e "${VP9_IVF_FILE}" ]; then + echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH." + return 1 + fi +} + +# Runs decode_with_drops on $1, $2 is interpreted as codec name and used solely +# to name the output file. $3 is the drop mode, and is passed directly to +# decode_with_drops. +decode_with_drops() { + local decoder="${LIBVPX_BIN_PATH}/decode_with_drops${VPX_TEST_EXE_SUFFIX}" + local input_file="$1" + local codec="$2" + local output_file="${VPX_TEST_OUTPUT_DIR}/decode_with_drops_${codec}" + local drop_mode="$3" + + if [ ! -x "${decoder}" ]; then + elog "${decoder} does not exist or is not executable." + return 1 + fi + + eval "${VPX_TEST_PREFIX}" "${decoder}" "${input_file}" "${output_file}" \ + "${drop_mode}" ${devnull} + + [ -e "${output_file}" ] || return 1 +} + +# Decodes $VP8_IVF_FILE while dropping frames, twice: once in sequence mode, +# and once in pattern mode. +# Note: This test assumes that $VP8_IVF_FILE has exactly 29 frames, and could +# break if the file is modified. +decode_with_drops_vp8() { + if [ "$(vp8_decode_available)" = "yes" ]; then + # Test sequence mode: Drop frames 2-28. + decode_with_drops "${VP8_IVF_FILE}" "vp8" "2-28" + + # Test pattern mode: Drop 3 of every 4 frames. + decode_with_drops "${VP8_IVF_FILE}" "vp8" "3/4" + fi +} + +# Decodes $VP9_IVF_FILE while dropping frames, twice: once in sequence mode, +# and once in pattern mode. +# Note: This test assumes that $VP9_IVF_FILE has exactly 20 frames, and could +# break if the file is modified. +decode_with_drops_vp9() { + if [ "$(vp9_decode_available)" = "yes" ]; then + # Test sequence mode: Drop frames 2-28. + decode_with_drops "${VP9_IVF_FILE}" "vp9" "2-19" + + # Test pattern mode: Drop 3 of every 4 frames. + decode_with_drops "${VP9_IVF_FILE}" "vp9" "3/4" + fi +} + +decode_with_drops_tests="decode_with_drops_vp8 + decode_with_drops_vp9" + +run_tests decode_with_drops_verify_environment "${decode_with_drops_tests}"
diff --git a/src/third_party/libvpx/test/encode_api_test.cc b/src/third_party/libvpx/test/encode_api_test.cc new file mode 100644 index 0000000..a7200e6 --- /dev/null +++ b/src/third_party/libvpx/test/encode_api_test.cc
@@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "./vpx_config.h" +#include "vpx/vp8cx.h" +#include "vpx/vpx_encoder.h" + +namespace { + +#define NELEMENTS(x) static_cast<int>(sizeof(x) / sizeof(x[0])) + +TEST(EncodeAPI, InvalidParams) { + static const vpx_codec_iface_t *kCodecs[] = { +#if CONFIG_VP8_ENCODER + &vpx_codec_vp8_cx_algo, +#endif +#if CONFIG_VP9_ENCODER + &vpx_codec_vp9_cx_algo, +#endif +#if CONFIG_VP10_ENCODER + &vpx_codec_vp10_cx_algo, +#endif + }; + uint8_t buf[1] = {0}; + vpx_image_t img; + vpx_codec_ctx_t enc; + vpx_codec_enc_cfg_t cfg; + + EXPECT_EQ(&img, vpx_img_wrap(&img, VPX_IMG_FMT_I420, 1, 1, 1, buf)); + + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_enc_init(NULL, NULL, NULL, 0)); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_enc_init(&enc, NULL, NULL, 0)); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_encode(NULL, NULL, 0, 0, 0, 0)); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_encode(NULL, &img, 0, 0, 0, 0)); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_destroy(NULL)); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, + vpx_codec_enc_config_default(NULL, NULL, 0)); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, + vpx_codec_enc_config_default(NULL, &cfg, 0)); + EXPECT_TRUE(vpx_codec_error(NULL) != NULL); + + for (int i = 0; i < NELEMENTS(kCodecs); ++i) { + SCOPED_TRACE(vpx_codec_iface_name(kCodecs[i])); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, + vpx_codec_enc_init(NULL, kCodecs[i], NULL, 0)); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, + vpx_codec_enc_init(&enc, kCodecs[i], NULL, 0)); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, + vpx_codec_enc_config_default(kCodecs[i], &cfg, 1)); + + EXPECT_EQ(VPX_CODEC_OK, vpx_codec_enc_config_default(kCodecs[i], &cfg, 0)); + EXPECT_EQ(VPX_CODEC_OK, vpx_codec_enc_init(&enc, kCodecs[i], &cfg, 0)); + EXPECT_EQ(VPX_CODEC_OK, vpx_codec_encode(&enc, NULL, 0, 0, 0, 0)); + + EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&enc)); + } +} + +} // namespace
diff --git a/src/third_party/libvpx/test/encode_perf_test.cc b/src/third_party/libvpx/test/encode_perf_test.cc new file mode 100644 index 0000000..7e9f0d6 --- /dev/null +++ b/src/third_party/libvpx/test/encode_perf_test.cc
@@ -0,0 +1,202 @@ +/* + * Copyright (c) 2014 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include <string> +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "./vpx_config.h" +#include "./vpx_version.h" +#include "test/codec_factory.h" +#include "test/encode_test_driver.h" +#include "test/i420_video_source.h" +#include "test/util.h" +#include "test/y4m_video_source.h" +#include "vpx_ports/vpx_timer.h" + +namespace { + +const int kMaxPsnr = 100; +const double kUsecsInSec = 1000000.0; + +struct EncodePerfTestVideo { + EncodePerfTestVideo(const char *name_, uint32_t width_, uint32_t height_, + uint32_t bitrate_, int frames_) + : name(name_), + width(width_), + height(height_), + bitrate(bitrate_), + frames(frames_) {} + const char *name; + uint32_t width; + uint32_t height; + uint32_t bitrate; + int frames; +}; + +const EncodePerfTestVideo kVP9EncodePerfTestVectors[] = { + EncodePerfTestVideo("desktop_640_360_30.yuv", 640, 360, 200, 2484), + EncodePerfTestVideo("kirland_640_480_30.yuv", 640, 480, 200, 300), + EncodePerfTestVideo("macmarcomoving_640_480_30.yuv", 640, 480, 200, 987), + EncodePerfTestVideo("macmarcostationary_640_480_30.yuv", 640, 480, 200, 718), + EncodePerfTestVideo("niklas_640_480_30.yuv", 640, 480, 200, 471), + EncodePerfTestVideo("tacomanarrows_640_480_30.yuv", 640, 480, 200, 300), + EncodePerfTestVideo("tacomasmallcameramovement_640_480_30.yuv", + 640, 480, 200, 300), + EncodePerfTestVideo("thaloundeskmtg_640_480_30.yuv", 640, 480, 200, 300), + EncodePerfTestVideo("niklas_1280_720_30.yuv", 1280, 720, 600, 470), +}; + +const int kEncodePerfTestSpeeds[] = { 5, 6, 7, 8 }; +const int kEncodePerfTestThreads[] = { 1, 2, 4 }; + +#define NELEMENTS(x) (sizeof((x)) / sizeof((x)[0])) + +class VP9EncodePerfTest + : public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> { + protected: + VP9EncodePerfTest() + : EncoderTest(GET_PARAM(0)), + min_psnr_(kMaxPsnr), + nframes_(0), + encoding_mode_(GET_PARAM(1)), + speed_(0), + threads_(1) {} + + virtual ~VP9EncodePerfTest() {} + + virtual void SetUp() { + InitializeConfig(); + SetMode(encoding_mode_); + + cfg_.g_lag_in_frames = 0; + cfg_.rc_min_quantizer = 2; + cfg_.rc_max_quantizer = 56; + cfg_.rc_dropframe_thresh = 0; + cfg_.rc_undershoot_pct = 50; + cfg_.rc_overshoot_pct = 50; + cfg_.rc_buf_sz = 1000; + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 600; + cfg_.rc_resize_allowed = 0; + cfg_.rc_end_usage = VPX_CBR; + cfg_.g_error_resilient = 1; + cfg_.g_threads = threads_; + } + + virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, + ::libvpx_test::Encoder *encoder) { + if (video->frame() == 0) { + const int log2_tile_columns = 3; + encoder->Control(VP8E_SET_CPUUSED, speed_); + encoder->Control(VP9E_SET_TILE_COLUMNS, log2_tile_columns); + encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING, 1); + encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 0); + } + } + + virtual void BeginPassHook(unsigned int /*pass*/) { + min_psnr_ = kMaxPsnr; + nframes_ = 0; + } + + virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) { + if (pkt->data.psnr.psnr[0] < min_psnr_) { + min_psnr_= pkt->data.psnr.psnr[0]; + } + } + + // for performance reasons don't decode + virtual bool DoDecode() { return 0; } + + double min_psnr() const { + return min_psnr_; + } + + void set_speed(unsigned int speed) { + speed_ = speed; + } + + void set_threads(unsigned int threads) { + threads_ = threads; + } + + private: + double min_psnr_; + unsigned int nframes_; + libvpx_test::TestMode encoding_mode_; + unsigned speed_; + unsigned int threads_; +}; + +TEST_P(VP9EncodePerfTest, PerfTest) { + for (size_t i = 0; i < NELEMENTS(kVP9EncodePerfTestVectors); ++i) { + for (size_t j = 0; j < NELEMENTS(kEncodePerfTestSpeeds); ++j) { + for (size_t k = 0; k < NELEMENTS(kEncodePerfTestThreads); ++k) { + if (kVP9EncodePerfTestVectors[i].width < 512 && + kEncodePerfTestThreads[k] > 1) + continue; + else if (kVP9EncodePerfTestVectors[i].width < 1024 && + kEncodePerfTestThreads[k] > 2) + continue; + + set_threads(kEncodePerfTestThreads[k]); + SetUp(); + + const vpx_rational timebase = { 33333333, 1000000000 }; + cfg_.g_timebase = timebase; + cfg_.rc_target_bitrate = kVP9EncodePerfTestVectors[i].bitrate; + + init_flags_ = VPX_CODEC_USE_PSNR; + + const unsigned frames = kVP9EncodePerfTestVectors[i].frames; + const char *video_name = kVP9EncodePerfTestVectors[i].name; + libvpx_test::I420VideoSource video( + video_name, + kVP9EncodePerfTestVectors[i].width, + kVP9EncodePerfTestVectors[i].height, + timebase.den, timebase.num, 0, + kVP9EncodePerfTestVectors[i].frames); + set_speed(kEncodePerfTestSpeeds[j]); + + vpx_usec_timer t; + vpx_usec_timer_start(&t); + + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + + vpx_usec_timer_mark(&t); + const double elapsed_secs = vpx_usec_timer_elapsed(&t) / kUsecsInSec; + const double fps = frames / elapsed_secs; + const double minimum_psnr = min_psnr(); + std::string display_name(video_name); + if (kEncodePerfTestThreads[k] > 1) { + char thread_count[32]; + snprintf(thread_count, sizeof(thread_count), "_t-%d", + kEncodePerfTestThreads[k]); + display_name += thread_count; + } + + printf("{\n"); + printf("\t\"type\" : \"encode_perf_test\",\n"); + printf("\t\"version\" : \"%s\",\n", VERSION_STRING_NOSP); + printf("\t\"videoName\" : \"%s\",\n", display_name.c_str()); + printf("\t\"encodeTimeSecs\" : %f,\n", elapsed_secs); + printf("\t\"totalFrames\" : %u,\n", frames); + printf("\t\"framesPerSecond\" : %f,\n", fps); + printf("\t\"minPsnr\" : %f,\n", minimum_psnr); + printf("\t\"speed\" : %d,\n", kEncodePerfTestSpeeds[j]); + printf("\t\"threads\" : %d\n", kEncodePerfTestThreads[k]); + printf("}\n"); + } + } + } +} + +VP9_INSTANTIATE_TEST_CASE( + VP9EncodePerfTest, ::testing::Values(::libvpx_test::kRealTime)); +} // namespace
diff --git a/src/third_party/libvpx/test/encode_test_driver.cc b/src/third_party/libvpx/test/encode_test_driver.cc new file mode 100644 index 0000000..128436e --- /dev/null +++ b/src/third_party/libvpx/test/encode_test_driver.cc
@@ -0,0 +1,282 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <string> + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "./vpx_config.h" +#include "test/codec_factory.h" +#include "test/decode_test_driver.h" +#include "test/encode_test_driver.h" +#include "test/register_state_check.h" +#include "test/video_source.h" + +namespace libvpx_test { +void Encoder::InitEncoder(VideoSource *video) { + vpx_codec_err_t res; + const vpx_image_t *img = video->img(); + + if (video->img() && !encoder_.priv) { + cfg_.g_w = img->d_w; + cfg_.g_h = img->d_h; + cfg_.g_timebase = video->timebase(); + cfg_.rc_twopass_stats_in = stats_->buf(); + + res = vpx_codec_enc_init(&encoder_, CodecInterface(), &cfg_, + init_flags_); + ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); + +#if CONFIG_VP9_ENCODER + if (CodecInterface() == &vpx_codec_vp9_cx_algo) { + // Default to 1 tile column for VP9. + const int log2_tile_columns = 0; + res = vpx_codec_control_(&encoder_, VP9E_SET_TILE_COLUMNS, + log2_tile_columns); + ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); + } else +#endif +#if CONFIG_VP10_ENCODER + if (CodecInterface() == &vpx_codec_vp10_cx_algo) { + // Default to 1 tile column for VP10. + const int log2_tile_columns = 0; + res = vpx_codec_control_(&encoder_, VP9E_SET_TILE_COLUMNS, + log2_tile_columns); + ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); + } else +#endif + { +#if CONFIG_VP8_ENCODER + ASSERT_EQ(&vpx_codec_vp8_cx_algo, CodecInterface()) + << "Unknown Codec Interface"; +#endif + } + } +} + +void Encoder::EncodeFrame(VideoSource *video, const unsigned long frame_flags) { + if (video->img()) + EncodeFrameInternal(*video, frame_flags); + else + Flush(); + + // Handle twopass stats + CxDataIterator iter = GetCxData(); + + while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) { + if (pkt->kind != VPX_CODEC_STATS_PKT) + continue; + + stats_->Append(*pkt); + } +} + +void Encoder::EncodeFrameInternal(const VideoSource &video, + const unsigned long frame_flags) { + vpx_codec_err_t res; + const vpx_image_t *img = video.img(); + + // Handle frame resizing + if (cfg_.g_w != img->d_w || cfg_.g_h != img->d_h) { + cfg_.g_w = img->d_w; + cfg_.g_h = img->d_h; + res = vpx_codec_enc_config_set(&encoder_, &cfg_); + ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); + } + + // Encode the frame + API_REGISTER_STATE_CHECK( + res = vpx_codec_encode(&encoder_, img, video.pts(), video.duration(), + frame_flags, deadline_)); + ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); +} + +void Encoder::Flush() { + const vpx_codec_err_t res = vpx_codec_encode(&encoder_, NULL, 0, 0, 0, + deadline_); + if (!encoder_.priv) + ASSERT_EQ(VPX_CODEC_ERROR, res) << EncoderError(); + else + ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); +} + +void EncoderTest::InitializeConfig() { + const vpx_codec_err_t res = codec_->DefaultEncoderConfig(&cfg_, 0); + dec_cfg_ = vpx_codec_dec_cfg_t(); + ASSERT_EQ(VPX_CODEC_OK, res); +} + +void EncoderTest::SetMode(TestMode mode) { + switch (mode) { + case kRealTime: + deadline_ = VPX_DL_REALTIME; + break; + + case kOnePassGood: + case kTwoPassGood: + deadline_ = VPX_DL_GOOD_QUALITY; + break; + + case kOnePassBest: + case kTwoPassBest: + deadline_ = VPX_DL_BEST_QUALITY; + break; + + default: + ASSERT_TRUE(false) << "Unexpected mode " << mode; + } + + if (mode == kTwoPassGood || mode == kTwoPassBest) + passes_ = 2; + else + passes_ = 1; +} +// The function should return "true" most of the time, therefore no early +// break-out is implemented within the match checking process. +static bool compare_img(const vpx_image_t *img1, + const vpx_image_t *img2) { + bool match = (img1->fmt == img2->fmt) && + (img1->cs == img2->cs) && + (img1->d_w == img2->d_w) && + (img1->d_h == img2->d_h); + + const unsigned int width_y = img1->d_w; + const unsigned int height_y = img1->d_h; + unsigned int i; + for (i = 0; i < height_y; ++i) + match = (memcmp(img1->planes[VPX_PLANE_Y] + i * img1->stride[VPX_PLANE_Y], + img2->planes[VPX_PLANE_Y] + i * img2->stride[VPX_PLANE_Y], + width_y) == 0) && match; + const unsigned int width_uv = (img1->d_w + 1) >> 1; + const unsigned int height_uv = (img1->d_h + 1) >> 1; + for (i = 0; i < height_uv; ++i) + match = (memcmp(img1->planes[VPX_PLANE_U] + i * img1->stride[VPX_PLANE_U], + img2->planes[VPX_PLANE_U] + i * img2->stride[VPX_PLANE_U], + width_uv) == 0) && match; + for (i = 0; i < height_uv; ++i) + match = (memcmp(img1->planes[VPX_PLANE_V] + i * img1->stride[VPX_PLANE_V], + img2->planes[VPX_PLANE_V] + i * img2->stride[VPX_PLANE_V], + width_uv) == 0) && match; + return match; +} + +void EncoderTest::MismatchHook(const vpx_image_t* /*img1*/, + const vpx_image_t* /*img2*/) { + ASSERT_TRUE(0) << "Encode/Decode mismatch found"; +} + +void EncoderTest::RunLoop(VideoSource *video) { + vpx_codec_dec_cfg_t dec_cfg = vpx_codec_dec_cfg_t(); + + stats_.Reset(); + + ASSERT_TRUE(passes_ == 1 || passes_ == 2); + for (unsigned int pass = 0; pass < passes_; pass++) { + last_pts_ = 0; + + if (passes_ == 1) + cfg_.g_pass = VPX_RC_ONE_PASS; + else if (pass == 0) + cfg_.g_pass = VPX_RC_FIRST_PASS; + else + cfg_.g_pass = VPX_RC_LAST_PASS; + + BeginPassHook(pass); + Encoder* const encoder = codec_->CreateEncoder(cfg_, deadline_, init_flags_, + &stats_); + ASSERT_TRUE(encoder != NULL); + + video->Begin(); + encoder->InitEncoder(video); + ASSERT_FALSE(::testing::Test::HasFatalFailure()); + + unsigned long dec_init_flags = 0; // NOLINT + // Use fragment decoder if encoder outputs partitions. + // NOTE: fragment decoder and partition encoder are only supported by VP8. + if (init_flags_ & VPX_CODEC_USE_OUTPUT_PARTITION) + dec_init_flags |= VPX_CODEC_USE_INPUT_FRAGMENTS; + Decoder* const decoder = codec_->CreateDecoder(dec_cfg, dec_init_flags, 0); + bool again; + for (again = true; again; video->Next()) { + again = (video->img() != NULL); + + PreEncodeFrameHook(video); + PreEncodeFrameHook(video, encoder); + encoder->EncodeFrame(video, frame_flags_); + + CxDataIterator iter = encoder->GetCxData(); + + bool has_cxdata = false; + bool has_dxdata = false; + while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) { + pkt = MutateEncoderOutputHook(pkt); + again = true; + switch (pkt->kind) { + case VPX_CODEC_CX_FRAME_PKT: + has_cxdata = true; + if (decoder && DoDecode()) { + vpx_codec_err_t res_dec = decoder->DecodeFrame( + (const uint8_t*)pkt->data.frame.buf, pkt->data.frame.sz); + + if (!HandleDecodeResult(res_dec, *video, decoder)) + break; + + has_dxdata = true; + } + ASSERT_GE(pkt->data.frame.pts, last_pts_); + last_pts_ = pkt->data.frame.pts; + FramePktHook(pkt); + break; + + case VPX_CODEC_PSNR_PKT: + PSNRPktHook(pkt); + break; + + default: + break; + } + } + + // Flush the decoder when there are no more fragments. + if ((init_flags_ & VPX_CODEC_USE_OUTPUT_PARTITION) && has_dxdata) { + const vpx_codec_err_t res_dec = decoder->DecodeFrame(NULL, 0); + if (!HandleDecodeResult(res_dec, *video, decoder)) + break; + } + + if (has_dxdata && has_cxdata) { + const vpx_image_t *img_enc = encoder->GetPreviewFrame(); + DxDataIterator dec_iter = decoder->GetDxData(); + const vpx_image_t *img_dec = dec_iter.Next(); + if (img_enc && img_dec) { + const bool res = compare_img(img_enc, img_dec); + if (!res) { // Mismatch + MismatchHook(img_enc, img_dec); + } + } + if (img_dec) + DecompressedFrameHook(*img_dec, video->pts()); + } + if (!Continue()) + break; + } + + EndPassHook(); + + if (decoder) + delete decoder; + delete encoder; + + if (!Continue()) + break; + } +} + +} // namespace libvpx_test
diff --git a/src/third_party/libvpx/test/encode_test_driver.h b/src/third_party/libvpx/test/encode_test_driver.h new file mode 100644 index 0000000..6d0a72f --- /dev/null +++ b/src/third_party/libvpx/test/encode_test_driver.h
@@ -0,0 +1,278 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#ifndef TEST_ENCODE_TEST_DRIVER_H_ +#define TEST_ENCODE_TEST_DRIVER_H_ + +#include <string> +#include <vector> + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "./vpx_config.h" +#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER || CONFIG_VP10_ENCODER +#include "vpx/vp8cx.h" +#endif +#include "vpx/vpx_encoder.h" + +namespace libvpx_test { + +class CodecFactory; +class VideoSource; + +enum TestMode { + kRealTime, + kOnePassGood, + kOnePassBest, + kTwoPassGood, + kTwoPassBest +}; +#define ALL_TEST_MODES ::testing::Values(::libvpx_test::kRealTime, \ + ::libvpx_test::kOnePassGood, \ + ::libvpx_test::kOnePassBest, \ + ::libvpx_test::kTwoPassGood, \ + ::libvpx_test::kTwoPassBest) + +#define ONE_PASS_TEST_MODES ::testing::Values(::libvpx_test::kRealTime, \ + ::libvpx_test::kOnePassGood, \ + ::libvpx_test::kOnePassBest) + +#define TWO_PASS_TEST_MODES ::testing::Values(::libvpx_test::kTwoPassGood, \ + ::libvpx_test::kTwoPassBest) + + +// Provides an object to handle the libvpx get_cx_data() iteration pattern +class CxDataIterator { + public: + explicit CxDataIterator(vpx_codec_ctx_t *encoder) + : encoder_(encoder), iter_(NULL) {} + + const vpx_codec_cx_pkt_t *Next() { + return vpx_codec_get_cx_data(encoder_, &iter_); + } + + private: + vpx_codec_ctx_t *encoder_; + vpx_codec_iter_t iter_; +}; + +// Implements an in-memory store for libvpx twopass statistics +class TwopassStatsStore { + public: + void Append(const vpx_codec_cx_pkt_t &pkt) { + buffer_.append(reinterpret_cast<char *>(pkt.data.twopass_stats.buf), + pkt.data.twopass_stats.sz); + } + + vpx_fixed_buf_t buf() { + const vpx_fixed_buf_t buf = { &buffer_[0], buffer_.size() }; + return buf; + } + + void Reset() { + buffer_.clear(); + } + + protected: + std::string buffer_; +}; + + +// Provides a simplified interface to manage one video encoding pass, given +// a configuration and video source. +// +// TODO(jkoleszar): The exact services it provides and the appropriate +// level of abstraction will be fleshed out as more tests are written. +class Encoder { + public: + Encoder(vpx_codec_enc_cfg_t cfg, unsigned long deadline, + const unsigned long init_flags, TwopassStatsStore *stats) + : cfg_(cfg), deadline_(deadline), init_flags_(init_flags), stats_(stats) { + memset(&encoder_, 0, sizeof(encoder_)); + } + + virtual ~Encoder() { + vpx_codec_destroy(&encoder_); + } + + CxDataIterator GetCxData() { + return CxDataIterator(&encoder_); + } + + void InitEncoder(VideoSource *video); + + const vpx_image_t *GetPreviewFrame() { + return vpx_codec_get_preview_frame(&encoder_); + } + // This is a thin wrapper around vpx_codec_encode(), so refer to + // vpx_encoder.h for its semantics. + void EncodeFrame(VideoSource *video, const unsigned long frame_flags); + + // Convenience wrapper for EncodeFrame() + void EncodeFrame(VideoSource *video) { + EncodeFrame(video, 0); + } + + void Control(int ctrl_id, int arg) { + const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg); + ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); + } + + void Control(int ctrl_id, int *arg) { + const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg); + ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); + } + + void Control(int ctrl_id, struct vpx_scaling_mode *arg) { + const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg); + ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); + } + + void Control(int ctrl_id, struct vpx_svc_layer_id *arg) { + const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg); + ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); + } + + void Control(int ctrl_id, struct vpx_svc_parameters *arg) { + const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg); + ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); + } +#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER || CONFIG_VP10_ENCODER + void Control(int ctrl_id, vpx_active_map_t *arg) { + const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg); + ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); + } +#endif + + void Config(const vpx_codec_enc_cfg_t *cfg) { + const vpx_codec_err_t res = vpx_codec_enc_config_set(&encoder_, cfg); + ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); + cfg_ = *cfg; + } + + void set_deadline(unsigned long deadline) { + deadline_ = deadline; + } + + protected: + virtual vpx_codec_iface_t* CodecInterface() const = 0; + + const char *EncoderError() { + const char *detail = vpx_codec_error_detail(&encoder_); + return detail ? detail : vpx_codec_error(&encoder_); + } + + // Encode an image + void EncodeFrameInternal(const VideoSource &video, + const unsigned long frame_flags); + + // Flush the encoder on EOS + void Flush(); + + vpx_codec_ctx_t encoder_; + vpx_codec_enc_cfg_t cfg_; + unsigned long deadline_; + unsigned long init_flags_; + TwopassStatsStore *stats_; +}; + +// Common test functionality for all Encoder tests. +// +// This class is a mixin which provides the main loop common to all +// encoder tests. It provides hooks which can be overridden by subclasses +// to implement each test's specific behavior, while centralizing the bulk +// of the boilerplate. Note that it doesn't inherit the gtest testing +// classes directly, so that tests can be parameterized differently. +class EncoderTest { + protected: + explicit EncoderTest(const CodecFactory *codec) + : codec_(codec), abort_(false), init_flags_(0), frame_flags_(0), + last_pts_(0) { + // Default to 1 thread. + cfg_.g_threads = 1; + } + + virtual ~EncoderTest() {} + + // Initialize the cfg_ member with the default configuration. + void InitializeConfig(); + + // Map the TestMode enum to the deadline_ and passes_ variables. + void SetMode(TestMode mode); + + // Set encoder flag. + void set_init_flags(unsigned long flag) { // NOLINT(runtime/int) + init_flags_ = flag; + } + + // Main loop + virtual void RunLoop(VideoSource *video); + + // Hook to be called at the beginning of a pass. + virtual void BeginPassHook(unsigned int /*pass*/) {} + + // Hook to be called at the end of a pass. + virtual void EndPassHook() {} + + // Hook to be called before encoding a frame. + virtual void PreEncodeFrameHook(VideoSource* /*video*/) {} + virtual void PreEncodeFrameHook(VideoSource* /*video*/, + Encoder* /*encoder*/) {} + + // Hook to be called on every compressed data packet. + virtual void FramePktHook(const vpx_codec_cx_pkt_t* /*pkt*/) {} + + // Hook to be called on every PSNR packet. + virtual void PSNRPktHook(const vpx_codec_cx_pkt_t* /*pkt*/) {} + + // Hook to determine whether the encode loop should continue. + virtual bool Continue() const { + return !(::testing::Test::HasFatalFailure() || abort_); + } + + const CodecFactory *codec_; + // Hook to determine whether to decode frame after encoding + virtual bool DoDecode() const { return 1; } + + // Hook to handle encode/decode mismatch + virtual void MismatchHook(const vpx_image_t *img1, + const vpx_image_t *img2); + + // Hook to be called on every decompressed frame. + virtual void DecompressedFrameHook(const vpx_image_t& /*img*/, + vpx_codec_pts_t /*pts*/) {} + + // Hook to be called to handle decode result. Return true to continue. + virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec, + const VideoSource& /*video*/, + Decoder *decoder) { + EXPECT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError(); + return VPX_CODEC_OK == res_dec; + } + + // Hook that can modify the encoder's output data + virtual const vpx_codec_cx_pkt_t *MutateEncoderOutputHook( + const vpx_codec_cx_pkt_t *pkt) { + return pkt; + } + + bool abort_; + vpx_codec_enc_cfg_t cfg_; + vpx_codec_dec_cfg_t dec_cfg_; + unsigned int passes_; + unsigned long deadline_; + TwopassStatsStore stats_; + unsigned long init_flags_; + unsigned long frame_flags_; + vpx_codec_pts_t last_pts_; +}; + +} // namespace libvpx_test + +#endif // TEST_ENCODE_TEST_DRIVER_H_
diff --git a/src/third_party/libvpx/test/error_resilience_test.cc b/src/third_party/libvpx/test/error_resilience_test.cc new file mode 100644 index 0000000..cd0dca2 --- /dev/null +++ b/src/third_party/libvpx/test/error_resilience_test.cc
@@ -0,0 +1,602 @@ +/* + * Copyright (c) 2013 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "test/codec_factory.h" +#include "test/encode_test_driver.h" +#include "test/i420_video_source.h" +#include "test/util.h" + +namespace { + +const int kMaxErrorFrames = 12; +const int kMaxDroppableFrames = 12; + +class ErrorResilienceTestLarge : public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, bool> { + protected: + ErrorResilienceTestLarge() + : EncoderTest(GET_PARAM(0)), + svc_support_(GET_PARAM(2)), + psnr_(0.0), + nframes_(0), + mismatch_psnr_(0.0), + mismatch_nframes_(0), + encoding_mode_(GET_PARAM(1)) { + Reset(); + } + + virtual ~ErrorResilienceTestLarge() {} + + void Reset() { + error_nframes_ = 0; + droppable_nframes_ = 0; + pattern_switch_ = 0; + } + + virtual void SetUp() { + InitializeConfig(); + SetMode(encoding_mode_); + } + + virtual void BeginPassHook(unsigned int /*pass*/) { + psnr_ = 0.0; + nframes_ = 0; + mismatch_psnr_ = 0.0; + mismatch_nframes_ = 0; + } + + virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) { + psnr_ += pkt->data.psnr.psnr[0]; + nframes_++; + } + + // + // Frame flags and layer id for temporal layers. + // For two layers, test pattern is: + // 1 3 + // 0 2 ..... + // LAST is updated on base/layer 0, GOLDEN updated on layer 1. + // Non-zero pattern_switch parameter means pattern will switch to + // not using LAST for frame_num >= pattern_switch. + int SetFrameFlags(int frame_num, + int num_temp_layers, + int pattern_switch) { + int frame_flags = 0; + if (num_temp_layers == 2) { + if (frame_num % 2 == 0) { + if (frame_num < pattern_switch || pattern_switch == 0) { + // Layer 0: predict from LAST and ARF, update LAST. + frame_flags = VP8_EFLAG_NO_REF_GF | + VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF; + } else { + // Layer 0: predict from GF and ARF, update GF. + frame_flags = VP8_EFLAG_NO_REF_LAST | + VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_UPD_ARF; + } + } else { + if (frame_num < pattern_switch || pattern_switch == 0) { + // Layer 1: predict from L, GF, and ARF, update GF. + frame_flags = VP8_EFLAG_NO_UPD_ARF | + VP8_EFLAG_NO_UPD_LAST; + } else { + // Layer 1: predict from GF and ARF, update GF. + frame_flags = VP8_EFLAG_NO_REF_LAST | + VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_UPD_ARF; + } + } + } + return frame_flags; + } + + virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video, + ::libvpx_test::Encoder * /*encoder*/) { + frame_flags_ &= ~(VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF); + // For temporal layer case. + if (cfg_.ts_number_layers > 1) { + frame_flags_ = SetFrameFlags(video->frame(), + cfg_.ts_number_layers, + pattern_switch_); + for (unsigned int i = 0; i < droppable_nframes_; ++i) { + if (droppable_frames_[i] == video->frame()) { + std::cout << "Encoding droppable frame: " + << droppable_frames_[i] << "\n"; + } + } + } else { + if (droppable_nframes_ > 0 && + (cfg_.g_pass == VPX_RC_LAST_PASS || cfg_.g_pass == VPX_RC_ONE_PASS)) { + for (unsigned int i = 0; i < droppable_nframes_; ++i) { + if (droppable_frames_[i] == video->frame()) { + std::cout << "Encoding droppable frame: " + << droppable_frames_[i] << "\n"; + frame_flags_ |= (VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF); + return; + } + } + } + } + } + + double GetAveragePsnr() const { + if (nframes_) + return psnr_ / nframes_; + return 0.0; + } + + double GetAverageMismatchPsnr() const { + if (mismatch_nframes_) + return mismatch_psnr_ / mismatch_nframes_; + return 0.0; + } + + virtual bool DoDecode() const { + if (error_nframes_ > 0 && + (cfg_.g_pass == VPX_RC_LAST_PASS || cfg_.g_pass == VPX_RC_ONE_PASS)) { + for (unsigned int i = 0; i < error_nframes_; ++i) { + if (error_frames_[i] == nframes_ - 1) { + std::cout << " Skipping decoding frame: " + << error_frames_[i] << "\n"; + return 0; + } + } + } + return 1; + } + + virtual void MismatchHook(const vpx_image_t *img1, + const vpx_image_t *img2) { + double mismatch_psnr = compute_psnr(img1, img2); + mismatch_psnr_ += mismatch_psnr; + ++mismatch_nframes_; + // std::cout << "Mismatch frame psnr: " << mismatch_psnr << "\n"; + } + + void SetErrorFrames(int num, unsigned int *list) { + if (num > kMaxErrorFrames) + num = kMaxErrorFrames; + else if (num < 0) + num = 0; + error_nframes_ = num; + for (unsigned int i = 0; i < error_nframes_; ++i) + error_frames_[i] = list[i]; + } + + void SetDroppableFrames(int num, unsigned int *list) { + if (num > kMaxDroppableFrames) + num = kMaxDroppableFrames; + else if (num < 0) + num = 0; + droppable_nframes_ = num; + for (unsigned int i = 0; i < droppable_nframes_; ++i) + droppable_frames_[i] = list[i]; + } + + unsigned int GetMismatchFrames() { + return mismatch_nframes_; + } + + void SetPatternSwitch(int frame_switch) { + pattern_switch_ = frame_switch; + } + + bool svc_support_; + + private: + double psnr_; + unsigned int nframes_; + unsigned int error_nframes_; + unsigned int droppable_nframes_; + unsigned int pattern_switch_; + double mismatch_psnr_; + unsigned int mismatch_nframes_; + unsigned int error_frames_[kMaxErrorFrames]; + unsigned int droppable_frames_[kMaxDroppableFrames]; + libvpx_test::TestMode encoding_mode_; +}; + +TEST_P(ErrorResilienceTestLarge, OnVersusOff) { + const vpx_rational timebase = { 33333333, 1000000000 }; + cfg_.g_timebase = timebase; + cfg_.rc_target_bitrate = 2000; + cfg_.g_lag_in_frames = 10; + + init_flags_ = VPX_CODEC_USE_PSNR; + + libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + timebase.den, timebase.num, 0, 30); + + // Error resilient mode OFF. + cfg_.g_error_resilient = 0; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + const double psnr_resilience_off = GetAveragePsnr(); + EXPECT_GT(psnr_resilience_off, 25.0); + + // Error resilient mode ON. + cfg_.g_error_resilient = 1; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + const double psnr_resilience_on = GetAveragePsnr(); + EXPECT_GT(psnr_resilience_on, 25.0); + + // Test that turning on error resilient mode hurts by 10% at most. + if (psnr_resilience_off > 0.0) { + const double psnr_ratio = psnr_resilience_on / psnr_resilience_off; + EXPECT_GE(psnr_ratio, 0.9); + EXPECT_LE(psnr_ratio, 1.1); + } +} + +// Check for successful decoding and no encoder/decoder mismatch +// if we lose (i.e., drop before decoding) a set of droppable +// frames (i.e., frames that don't update any reference buffers). +// Check both isolated and consecutive loss. +TEST_P(ErrorResilienceTestLarge, DropFramesWithoutRecovery) { + const vpx_rational timebase = { 33333333, 1000000000 }; + cfg_.g_timebase = timebase; + cfg_.rc_target_bitrate = 500; + // FIXME(debargha): Fix this to work for any lag. + // Currently this test only works for lag = 0 + cfg_.g_lag_in_frames = 0; + + init_flags_ = VPX_CODEC_USE_PSNR; + + libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + timebase.den, timebase.num, 0, 40); + + // Error resilient mode ON. + cfg_.g_error_resilient = 1; + cfg_.kf_mode = VPX_KF_DISABLED; + + // Set an arbitrary set of error frames same as droppable frames. + // In addition to isolated loss/drop, add a long consecutive series + // (of size 9) of dropped frames. + unsigned int num_droppable_frames = 11; + unsigned int droppable_frame_list[] = {5, 16, 22, 23, 24, 25, 26, 27, 28, + 29, 30}; + SetDroppableFrames(num_droppable_frames, droppable_frame_list); + SetErrorFrames(num_droppable_frames, droppable_frame_list); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + // Test that no mismatches have been found + std::cout << " Mismatch frames: " + << GetMismatchFrames() << "\n"; + EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0); + + // Reset previously set of error/droppable frames. + Reset(); + +#if 0 + // TODO(jkoleszar): This test is disabled for the time being as too + // sensitive. It's not clear how to set a reasonable threshold for + // this behavior. + + // Now set an arbitrary set of error frames that are non-droppable + unsigned int num_error_frames = 3; + unsigned int error_frame_list[] = {3, 10, 20}; + SetErrorFrames(num_error_frames, error_frame_list); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + + // Test that dropping an arbitrary set of inter frames does not hurt too much + // Note the Average Mismatch PSNR is the average of the PSNR between + // decoded frame and encoder's version of the same frame for all frames + // with mismatch. + const double psnr_resilience_mismatch = GetAverageMismatchPsnr(); + std::cout << " Mismatch PSNR: " + << psnr_resilience_mismatch << "\n"; + EXPECT_GT(psnr_resilience_mismatch, 20.0); +#endif +} + +// Check for successful decoding and no encoder/decoder mismatch +// if we lose (i.e., drop before decoding) the enhancement layer frames for a +// two layer temporal pattern. The base layer does not predict from the top +// layer, so successful decoding is expected. +TEST_P(ErrorResilienceTestLarge, 2LayersDropEnhancement) { + // This test doesn't run if SVC is not supported. + if (!svc_support_) + return; + + const vpx_rational timebase = { 33333333, 1000000000 }; + cfg_.g_timebase = timebase; + cfg_.rc_target_bitrate = 500; + cfg_.g_lag_in_frames = 0; + + cfg_.rc_end_usage = VPX_CBR; + // 2 Temporal layers, no spatial layers, CBR mode. + cfg_.ss_number_layers = 1; + cfg_.ts_number_layers = 2; + cfg_.ts_rate_decimator[0] = 2; + cfg_.ts_rate_decimator[1] = 1; + cfg_.ts_periodicity = 2; + cfg_.ts_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100; + cfg_.ts_target_bitrate[1] = cfg_.rc_target_bitrate; + + init_flags_ = VPX_CODEC_USE_PSNR; + + libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + timebase.den, timebase.num, 0, 40); + + // Error resilient mode ON. + cfg_.g_error_resilient = 1; + cfg_.kf_mode = VPX_KF_DISABLED; + SetPatternSwitch(0); + + // The odd frames are the enhancement layer for 2 layer pattern, so set + // those frames as droppable. Drop the last 7 frames. + unsigned int num_droppable_frames = 7; + unsigned int droppable_frame_list[] = {27, 29, 31, 33, 35, 37, 39}; + SetDroppableFrames(num_droppable_frames, droppable_frame_list); + SetErrorFrames(num_droppable_frames, droppable_frame_list); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + // Test that no mismatches have been found + std::cout << " Mismatch frames: " + << GetMismatchFrames() << "\n"; + EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0); + + // Reset previously set of error/droppable frames. + Reset(); +} + +// Check for successful decoding and no encoder/decoder mismatch +// for a two layer temporal pattern, where at some point in the +// sequence, the LAST ref is not used anymore. +TEST_P(ErrorResilienceTestLarge, 2LayersNoRefLast) { + // This test doesn't run if SVC is not supported. + if (!svc_support_) + return; + + const vpx_rational timebase = { 33333333, 1000000000 }; + cfg_.g_timebase = timebase; + cfg_.rc_target_bitrate = 500; + cfg_.g_lag_in_frames = 0; + + cfg_.rc_end_usage = VPX_CBR; + // 2 Temporal layers, no spatial layers, CBR mode. + cfg_.ss_number_layers = 1; + cfg_.ts_number_layers = 2; + cfg_.ts_rate_decimator[0] = 2; + cfg_.ts_rate_decimator[1] = 1; + cfg_.ts_periodicity = 2; + cfg_.ts_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100; + cfg_.ts_target_bitrate[1] = cfg_.rc_target_bitrate; + + init_flags_ = VPX_CODEC_USE_PSNR; + + libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + timebase.den, timebase.num, 0, 100); + + // Error resilient mode ON. + cfg_.g_error_resilient = 1; + cfg_.kf_mode = VPX_KF_DISABLED; + SetPatternSwitch(60); + + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + // Test that no mismatches have been found + std::cout << " Mismatch frames: " + << GetMismatchFrames() << "\n"; + EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0); + + // Reset previously set of error/droppable frames. + Reset(); +} + +class ErrorResilienceTestLargeCodecControls : public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> { + protected: + ErrorResilienceTestLargeCodecControls() + : EncoderTest(GET_PARAM(0)), + encoding_mode_(GET_PARAM(1)) { + Reset(); + } + + virtual ~ErrorResilienceTestLargeCodecControls() {} + + void Reset() { + last_pts_ = 0; + tot_frame_number_ = 0; + // For testing up to 3 layers. + for (int i = 0; i < 3; ++i) { + bits_total_[i] = 0; + } + duration_ = 0.0; + } + + virtual void SetUp() { + InitializeConfig(); + SetMode(encoding_mode_); + } + + // + // Frame flags and layer id for temporal layers. + // + + // For two layers, test pattern is: + // 1 3 + // 0 2 ..... + // For three layers, test pattern is: + // 1 3 5 7 + // 2 6 + // 0 4 .... + // LAST is always update on base/layer 0, GOLDEN is updated on layer 1, + // and ALTREF is updated on top layer for 3 layer pattern. + int SetFrameFlags(int frame_num, int num_temp_layers) { + int frame_flags = 0; + if (num_temp_layers == 2) { + if (frame_num % 2 == 0) { + // Layer 0: predict from L and ARF, update L. + frame_flags = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF; + } else { + // Layer 1: predict from L, G and ARF, and update G. + frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_UPD_ENTROPY; + } + } else if (num_temp_layers == 3) { + if (frame_num % 4 == 0) { + // Layer 0: predict from L, update L. + frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | + VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF; + } else if ((frame_num - 2) % 4 == 0) { + // Layer 1: predict from L, G, update G. + frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_REF_ARF; + } else if ((frame_num - 1) % 2 == 0) { + // Layer 2: predict from L, G, ARF; update ARG. + frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST; + } + } + return frame_flags; + } + + int SetLayerId(int frame_num, int num_temp_layers) { + int layer_id = 0; + if (num_temp_layers == 2) { + if (frame_num % 2 == 0) { + layer_id = 0; + } else { + layer_id = 1; + } + } else if (num_temp_layers == 3) { + if (frame_num % 4 == 0) { + layer_id = 0; + } else if ((frame_num - 2) % 4 == 0) { + layer_id = 1; + } else if ((frame_num - 1) % 2 == 0) { + layer_id = 2; + } + } + return layer_id; + } + + virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video, + libvpx_test::Encoder *encoder) { + if (cfg_.ts_number_layers > 1) { + int layer_id = SetLayerId(video->frame(), cfg_.ts_number_layers); + int frame_flags = SetFrameFlags(video->frame(), cfg_.ts_number_layers); + if (video->frame() > 0) { + encoder->Control(VP8E_SET_TEMPORAL_LAYER_ID, layer_id); + encoder->Control(VP8E_SET_FRAME_FLAGS, frame_flags); + } + const vpx_rational_t tb = video->timebase(); + timebase_ = static_cast<double>(tb.num) / tb.den; + duration_ = 0; + return; + } + } + + virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) { + // Time since last timestamp = duration. + vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_; + if (duration > 1) { + // Update counter for total number of frames (#frames input to encoder). + // Needed for setting the proper layer_id below. + tot_frame_number_ += static_cast<int>(duration - 1); + } + int layer = SetLayerId(tot_frame_number_, cfg_.ts_number_layers); + const size_t frame_size_in_bits = pkt->data.frame.sz * 8; + // Update the total encoded bits. For temporal layers, update the cumulative + // encoded bits per layer. + for (int i = layer; i < static_cast<int>(cfg_.ts_number_layers); ++i) { + bits_total_[i] += frame_size_in_bits; + } + // Update the most recent pts. + last_pts_ = pkt->data.frame.pts; + ++tot_frame_number_; + } + + virtual void EndPassHook(void) { + duration_ = (last_pts_ + 1) * timebase_; + if (cfg_.ts_number_layers > 1) { + for (int layer = 0; layer < static_cast<int>(cfg_.ts_number_layers); + ++layer) { + if (bits_total_[layer]) { + // Effective file datarate: + effective_datarate_[layer] = (bits_total_[layer] / 1000.0) / duration_; + } + } + } + } + + double effective_datarate_[3]; + private: + libvpx_test::TestMode encoding_mode_; + vpx_codec_pts_t last_pts_; + double timebase_; + int64_t bits_total_[3]; + double duration_; + int tot_frame_number_; + }; + +// Check two codec controls used for: +// (1) for setting temporal layer id, and (2) for settings encoder flags. +// This test invokes those controls for each frame, and verifies encoder/decoder +// mismatch and basic rate control response. +// TODO(marpan): Maybe move this test to datarate_test.cc. +TEST_P(ErrorResilienceTestLargeCodecControls, CodecControl3TemporalLayers) { + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_dropframe_thresh = 1; + cfg_.rc_min_quantizer = 2; + cfg_.rc_max_quantizer = 56; + cfg_.rc_end_usage = VPX_CBR; + cfg_.rc_dropframe_thresh = 1; + cfg_.g_lag_in_frames = 0; + cfg_.kf_mode = VPX_KF_DISABLED; + cfg_.g_error_resilient = 1; + + // 3 Temporal layers. Framerate decimation (4, 2, 1). + cfg_.ts_number_layers = 3; + cfg_.ts_rate_decimator[0] = 4; + cfg_.ts_rate_decimator[1] = 2; + cfg_.ts_rate_decimator[2] = 1; + cfg_.ts_periodicity = 4; + cfg_.ts_layer_id[0] = 0; + cfg_.ts_layer_id[1] = 2; + cfg_.ts_layer_id[2] = 1; + cfg_.ts_layer_id[3] = 2; + + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 200); + for (int i = 200; i <= 800; i += 200) { + cfg_.rc_target_bitrate = i; + Reset(); + // 40-20-40 bitrate allocation for 3 temporal layers. + cfg_.ts_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100; + cfg_.ts_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100; + cfg_.ts_target_bitrate[2] = cfg_.rc_target_bitrate; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) { + ASSERT_GE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 0.75) + << " The datarate for the file is lower than target by too much, " + "for layer: " << j; + ASSERT_LE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 1.25) + << " The datarate for the file is greater than target by too much, " + "for layer: " << j; + } + } +} + +VP8_INSTANTIATE_TEST_CASE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES, + ::testing::Values(true)); +VP8_INSTANTIATE_TEST_CASE(ErrorResilienceTestLargeCodecControls, + ONE_PASS_TEST_MODES); +VP9_INSTANTIATE_TEST_CASE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES, + ::testing::Values(true)); +// SVC-related tests don't run for VP10 since SVC is not supported. +VP10_INSTANTIATE_TEST_CASE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES, + ::testing::Values(false)); +} // namespace
diff --git a/src/third_party/libvpx/test/examples.sh b/src/third_party/libvpx/test/examples.sh new file mode 100755 index 0000000..39f7e39 --- /dev/null +++ b/src/third_party/libvpx/test/examples.sh
@@ -0,0 +1,29 @@ +#!/bin/sh +## +## Copyright (c) 2014 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## +## This file runs all of the tests for the libvpx examples. +## +. $(dirname $0)/tools_common.sh + +example_tests=$(ls $(dirname $0)/*.sh) + +# List of script names to exclude. +exclude_list="examples tools_common" + +# Filter out the scripts in $exclude_list. +for word in ${exclude_list}; do + example_tests=$(filter_strings "${example_tests}" "${word}" exclude) +done + +for test in ${example_tests}; do + # Source each test script so that exporting variables can be avoided. + VPX_TEST_NAME="$(basename ${test%.*})" + . "${test}" +done
diff --git a/src/third_party/libvpx/test/external_frame_buffer_test.cc b/src/third_party/libvpx/test/external_frame_buffer_test.cc new file mode 100644 index 0000000..2570f44 --- /dev/null +++ b/src/third_party/libvpx/test/external_frame_buffer_test.cc
@@ -0,0 +1,493 @@ +/* + * Copyright (c) 2014 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <string> + +#include "./vpx_config.h" +#include "test/codec_factory.h" +#include "test/decode_test_driver.h" +#include "test/ivf_video_source.h" +#include "test/md5_helper.h" +#include "test/test_vectors.h" +#include "test/util.h" +#if CONFIG_WEBM_IO +#include "test/webm_video_source.h" +#endif + +namespace { + +const int kVideoNameParam = 1; + +struct ExternalFrameBuffer { + uint8_t *data; + size_t size; + int in_use; +}; + +// Class to manipulate a list of external frame buffers. +class ExternalFrameBufferList { + public: + ExternalFrameBufferList() + : num_buffers_(0), + ext_fb_list_(NULL) {} + + virtual ~ExternalFrameBufferList() { + for (int i = 0; i < num_buffers_; ++i) { + delete [] ext_fb_list_[i].data; + } + delete [] ext_fb_list_; + } + + // Creates the list to hold the external buffers. Returns true on success. + bool CreateBufferList(int num_buffers) { + if (num_buffers < 0) + return false; + + num_buffers_ = num_buffers; + ext_fb_list_ = new ExternalFrameBuffer[num_buffers_]; + EXPECT_TRUE(ext_fb_list_ != NULL); + memset(ext_fb_list_, 0, sizeof(ext_fb_list_[0]) * num_buffers_); + return true; + } + + // Searches the frame buffer list for a free frame buffer. Makes sure + // that the frame buffer is at least |min_size| in bytes. Marks that the + // frame buffer is in use by libvpx. Finally sets |fb| to point to the + // external frame buffer. Returns < 0 on an error. + int GetFreeFrameBuffer(size_t min_size, vpx_codec_frame_buffer_t *fb) { + EXPECT_TRUE(fb != NULL); + const int idx = FindFreeBufferIndex(); + if (idx == num_buffers_) + return -1; + + if (ext_fb_list_[idx].size < min_size) { + delete [] ext_fb_list_[idx].data; + ext_fb_list_[idx].data = new uint8_t[min_size]; + memset(ext_fb_list_[idx].data, 0, min_size); + ext_fb_list_[idx].size = min_size; + } + + SetFrameBuffer(idx, fb); + return 0; + } + + // Test function that will not allocate any data for the frame buffer. + // Returns < 0 on an error. + int GetZeroFrameBuffer(size_t min_size, vpx_codec_frame_buffer_t *fb) { + EXPECT_TRUE(fb != NULL); + const int idx = FindFreeBufferIndex(); + if (idx == num_buffers_) + return -1; + + if (ext_fb_list_[idx].size < min_size) { + delete [] ext_fb_list_[idx].data; + ext_fb_list_[idx].data = NULL; + ext_fb_list_[idx].size = min_size; + } + + SetFrameBuffer(idx, fb); + return 0; + } + + // Marks the external frame buffer that |fb| is pointing to as free. + // Returns < 0 on an error. + int ReturnFrameBuffer(vpx_codec_frame_buffer_t *fb) { + if (fb == NULL) { + EXPECT_TRUE(fb != NULL); + return -1; + } + ExternalFrameBuffer *const ext_fb = + reinterpret_cast<ExternalFrameBuffer*>(fb->priv); + if (ext_fb == NULL) { + EXPECT_TRUE(ext_fb != NULL); + return -1; + } + EXPECT_EQ(1, ext_fb->in_use); + ext_fb->in_use = 0; + return 0; + } + + // Checks that the ximage data is contained within the external frame buffer + // private data passed back in the ximage. + void CheckXImageFrameBuffer(const vpx_image_t *img) { + if (img->fb_priv != NULL) { + const struct ExternalFrameBuffer *const ext_fb = + reinterpret_cast<ExternalFrameBuffer*>(img->fb_priv); + + ASSERT_TRUE(img->planes[0] >= ext_fb->data && + img->planes[0] < (ext_fb->data + ext_fb->size)); + } + } + + private: + // Returns the index of the first free frame buffer. Returns |num_buffers_| + // if there are no free frame buffers. + int FindFreeBufferIndex() { + int i; + // Find a free frame buffer. + for (i = 0; i < num_buffers_; ++i) { + if (!ext_fb_list_[i].in_use) + break; + } + return i; + } + + // Sets |fb| to an external frame buffer. idx is the index into the frame + // buffer list. + void SetFrameBuffer(int idx, vpx_codec_frame_buffer_t *fb) { + ASSERT_TRUE(fb != NULL); + fb->data = ext_fb_list_[idx].data; + fb->size = ext_fb_list_[idx].size; + ASSERT_EQ(0, ext_fb_list_[idx].in_use); + ext_fb_list_[idx].in_use = 1; + fb->priv = &ext_fb_list_[idx]; + } + + int num_buffers_; + ExternalFrameBuffer *ext_fb_list_; +}; + +#if CONFIG_WEBM_IO + +// Callback used by libvpx to request the application to return a frame +// buffer of at least |min_size| in bytes. +int get_vp9_frame_buffer(void *user_priv, size_t min_size, + vpx_codec_frame_buffer_t *fb) { + ExternalFrameBufferList *const fb_list = + reinterpret_cast<ExternalFrameBufferList*>(user_priv); + return fb_list->GetFreeFrameBuffer(min_size, fb); +} + +// Callback used by libvpx to tell the application that |fb| is not needed +// anymore. +int release_vp9_frame_buffer(void *user_priv, + vpx_codec_frame_buffer_t *fb) { + ExternalFrameBufferList *const fb_list = + reinterpret_cast<ExternalFrameBufferList*>(user_priv); + return fb_list->ReturnFrameBuffer(fb); +} + +// Callback will not allocate data for frame buffer. +int get_vp9_zero_frame_buffer(void *user_priv, size_t min_size, + vpx_codec_frame_buffer_t *fb) { + ExternalFrameBufferList *const fb_list = + reinterpret_cast<ExternalFrameBufferList*>(user_priv); + return fb_list->GetZeroFrameBuffer(min_size, fb); +} + +// Callback will allocate one less byte than |min_size|. +int get_vp9_one_less_byte_frame_buffer(void *user_priv, size_t min_size, + vpx_codec_frame_buffer_t *fb) { + ExternalFrameBufferList *const fb_list = + reinterpret_cast<ExternalFrameBufferList*>(user_priv); + return fb_list->GetFreeFrameBuffer(min_size - 1, fb); +} + +// Callback will not release the external frame buffer. +int do_not_release_vp9_frame_buffer(void *user_priv, + vpx_codec_frame_buffer_t *fb) { + (void)user_priv; + (void)fb; + return 0; +} + +#endif // CONFIG_WEBM_IO + +// Class for testing passing in external frame buffers to libvpx. +class ExternalFrameBufferMD5Test + : public ::libvpx_test::DecoderTest, + public ::libvpx_test::CodecTestWithParam<const char*> { + protected: + ExternalFrameBufferMD5Test() + : DecoderTest(GET_PARAM(::libvpx_test::kCodecFactoryParam)), + md5_file_(NULL), + num_buffers_(0) {} + + virtual ~ExternalFrameBufferMD5Test() { + if (md5_file_ != NULL) + fclose(md5_file_); + } + + virtual void PreDecodeFrameHook( + const libvpx_test::CompressedVideoSource &video, + libvpx_test::Decoder *decoder) { + if (num_buffers_ > 0 && video.frame_number() == 0) { + // Have libvpx use frame buffers we create. + ASSERT_TRUE(fb_list_.CreateBufferList(num_buffers_)); + ASSERT_EQ(VPX_CODEC_OK, + decoder->SetFrameBufferFunctions( + GetVP9FrameBuffer, ReleaseVP9FrameBuffer, this)); + } + } + + void OpenMD5File(const std::string &md5_file_name_) { + md5_file_ = libvpx_test::OpenTestDataFile(md5_file_name_); + ASSERT_TRUE(md5_file_ != NULL) << "Md5 file open failed. Filename: " + << md5_file_name_; + } + + virtual void DecompressedFrameHook(const vpx_image_t &img, + const unsigned int frame_number) { + ASSERT_TRUE(md5_file_ != NULL); + char expected_md5[33]; + char junk[128]; + + // Read correct md5 checksums. + const int res = fscanf(md5_file_, "%s %s", expected_md5, junk); + ASSERT_NE(EOF, res) << "Read md5 data failed"; + expected_md5[32] = '\0'; + + ::libvpx_test::MD5 md5_res; + md5_res.Add(&img); + const char *const actual_md5 = md5_res.Get(); + + // Check md5 match. + ASSERT_STREQ(expected_md5, actual_md5) + << "Md5 checksums don't match: frame number = " << frame_number; + } + + // Callback to get a free external frame buffer. Return value < 0 is an + // error. + static int GetVP9FrameBuffer(void *user_priv, size_t min_size, + vpx_codec_frame_buffer_t *fb) { + ExternalFrameBufferMD5Test *const md5Test = + reinterpret_cast<ExternalFrameBufferMD5Test*>(user_priv); + return md5Test->fb_list_.GetFreeFrameBuffer(min_size, fb); + } + + // Callback to release an external frame buffer. Return value < 0 is an + // error. + static int ReleaseVP9FrameBuffer(void *user_priv, + vpx_codec_frame_buffer_t *fb) { + ExternalFrameBufferMD5Test *const md5Test = + reinterpret_cast<ExternalFrameBufferMD5Test*>(user_priv); + return md5Test->fb_list_.ReturnFrameBuffer(fb); + } + + void set_num_buffers(int num_buffers) { num_buffers_ = num_buffers; } + int num_buffers() const { return num_buffers_; } + + private: + FILE *md5_file_; + int num_buffers_; + ExternalFrameBufferList fb_list_; +}; + +#if CONFIG_WEBM_IO +const char kVP9TestFile[] = "vp90-2-02-size-lf-1920x1080.webm"; + +// Class for testing passing in external frame buffers to libvpx. +class ExternalFrameBufferTest : public ::testing::Test { + protected: + ExternalFrameBufferTest() + : video_(NULL), + decoder_(NULL), + num_buffers_(0) {} + + virtual void SetUp() { + video_ = new libvpx_test::WebMVideoSource(kVP9TestFile); + ASSERT_TRUE(video_ != NULL); + video_->Init(); + video_->Begin(); + + vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t(); + decoder_ = new libvpx_test::VP9Decoder(cfg, 0); + ASSERT_TRUE(decoder_ != NULL); + } + + virtual void TearDown() { + delete decoder_; + delete video_; + } + + // Passes the external frame buffer information to libvpx. + vpx_codec_err_t SetFrameBufferFunctions( + int num_buffers, + vpx_get_frame_buffer_cb_fn_t cb_get, + vpx_release_frame_buffer_cb_fn_t cb_release) { + if (num_buffers > 0) { + num_buffers_ = num_buffers; + EXPECT_TRUE(fb_list_.CreateBufferList(num_buffers_)); + } + + return decoder_->SetFrameBufferFunctions(cb_get, cb_release, &fb_list_); + } + + vpx_codec_err_t DecodeOneFrame() { + const vpx_codec_err_t res = + decoder_->DecodeFrame(video_->cxdata(), video_->frame_size()); + CheckDecodedFrames(); + if (res == VPX_CODEC_OK) + video_->Next(); + return res; + } + + vpx_codec_err_t DecodeRemainingFrames() { + for (; video_->cxdata() != NULL; video_->Next()) { + const vpx_codec_err_t res = + decoder_->DecodeFrame(video_->cxdata(), video_->frame_size()); + if (res != VPX_CODEC_OK) + return res; + CheckDecodedFrames(); + } + return VPX_CODEC_OK; + } + + private: + void CheckDecodedFrames() { + libvpx_test::DxDataIterator dec_iter = decoder_->GetDxData(); + const vpx_image_t *img = NULL; + + // Get decompressed data + while ((img = dec_iter.Next()) != NULL) { + fb_list_.CheckXImageFrameBuffer(img); + } + } + + libvpx_test::WebMVideoSource *video_; + libvpx_test::VP9Decoder *decoder_; + int num_buffers_; + ExternalFrameBufferList fb_list_; +}; +#endif // CONFIG_WEBM_IO + +// This test runs through the set of test vectors, and decodes them. +// Libvpx will call into the application to allocate a frame buffer when +// needed. The md5 checksums are computed for each frame in the video file. +// If md5 checksums match the correct md5 data, then the test is passed. +// Otherwise, the test failed. +TEST_P(ExternalFrameBufferMD5Test, ExtFBMD5Match) { + const std::string filename = GET_PARAM(kVideoNameParam); + libvpx_test::CompressedVideoSource *video = NULL; + + // Number of buffers equals #VP9_MAXIMUM_REF_BUFFERS + + // #VPX_MAXIMUM_WORK_BUFFERS + four jitter buffers. + const int jitter_buffers = 4; + const int num_buffers = + VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS + jitter_buffers; + set_num_buffers(num_buffers); + +#if CONFIG_VP8_DECODER + // Tell compiler we are not using kVP8TestVectors. + (void)libvpx_test::kVP8TestVectors; +#endif + + // Open compressed video file. + if (filename.substr(filename.length() - 3, 3) == "ivf") { + video = new libvpx_test::IVFVideoSource(filename); + } else { +#if CONFIG_WEBM_IO + video = new libvpx_test::WebMVideoSource(filename); +#else + fprintf(stderr, "WebM IO is disabled, skipping test vector %s\n", + filename.c_str()); + return; +#endif + } + ASSERT_TRUE(video != NULL); + video->Init(); + + // Construct md5 file name. + const std::string md5_filename = filename + ".md5"; + OpenMD5File(md5_filename); + + // Decode frame, and check the md5 matching. + ASSERT_NO_FATAL_FAILURE(RunLoop(video)); + delete video; +} + +#if CONFIG_WEBM_IO +TEST_F(ExternalFrameBufferTest, MinFrameBuffers) { + // Minimum number of external frame buffers for VP9 is + // #VP9_MAXIMUM_REF_BUFFERS + #VPX_MAXIMUM_WORK_BUFFERS. + const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS; + ASSERT_EQ(VPX_CODEC_OK, + SetFrameBufferFunctions( + num_buffers, get_vp9_frame_buffer, release_vp9_frame_buffer)); + ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames()); +} + +TEST_F(ExternalFrameBufferTest, EightJitterBuffers) { + // Number of buffers equals #VP9_MAXIMUM_REF_BUFFERS + + // #VPX_MAXIMUM_WORK_BUFFERS + eight jitter buffers. + const int jitter_buffers = 8; + const int num_buffers = + VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS + jitter_buffers; + ASSERT_EQ(VPX_CODEC_OK, + SetFrameBufferFunctions( + num_buffers, get_vp9_frame_buffer, release_vp9_frame_buffer)); + ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames()); +} + +TEST_F(ExternalFrameBufferTest, NotEnoughBuffers) { + // Minimum number of external frame buffers for VP9 is + // #VP9_MAXIMUM_REF_BUFFERS + #VPX_MAXIMUM_WORK_BUFFERS. Most files will + // only use 5 frame buffers at one time. + const int num_buffers = 2; + ASSERT_EQ(VPX_CODEC_OK, + SetFrameBufferFunctions( + num_buffers, get_vp9_frame_buffer, release_vp9_frame_buffer)); + ASSERT_EQ(VPX_CODEC_OK, DecodeOneFrame()); + ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeRemainingFrames()); +} + +TEST_F(ExternalFrameBufferTest, NoRelease) { + const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS; + ASSERT_EQ(VPX_CODEC_OK, + SetFrameBufferFunctions(num_buffers, get_vp9_frame_buffer, + do_not_release_vp9_frame_buffer)); + ASSERT_EQ(VPX_CODEC_OK, DecodeOneFrame()); + ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeRemainingFrames()); +} + +TEST_F(ExternalFrameBufferTest, NullRealloc) { + const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS; + ASSERT_EQ(VPX_CODEC_OK, + SetFrameBufferFunctions(num_buffers, get_vp9_zero_frame_buffer, + release_vp9_frame_buffer)); + ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeOneFrame()); +} + +TEST_F(ExternalFrameBufferTest, ReallocOneLessByte) { + const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS; + ASSERT_EQ(VPX_CODEC_OK, + SetFrameBufferFunctions( + num_buffers, get_vp9_one_less_byte_frame_buffer, + release_vp9_frame_buffer)); + ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeOneFrame()); +} + +TEST_F(ExternalFrameBufferTest, NullGetFunction) { + const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS; + ASSERT_EQ(VPX_CODEC_INVALID_PARAM, + SetFrameBufferFunctions(num_buffers, NULL, + release_vp9_frame_buffer)); +} + +TEST_F(ExternalFrameBufferTest, NullReleaseFunction) { + const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS; + ASSERT_EQ(VPX_CODEC_INVALID_PARAM, + SetFrameBufferFunctions(num_buffers, get_vp9_frame_buffer, NULL)); +} + +TEST_F(ExternalFrameBufferTest, SetAfterDecode) { + const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS; + ASSERT_EQ(VPX_CODEC_OK, DecodeOneFrame()); + ASSERT_EQ(VPX_CODEC_ERROR, + SetFrameBufferFunctions( + num_buffers, get_vp9_frame_buffer, release_vp9_frame_buffer)); +} +#endif // CONFIG_WEBM_IO + +VP9_INSTANTIATE_TEST_CASE(ExternalFrameBufferMD5Test, + ::testing::ValuesIn(libvpx_test::kVP9TestVectors, + libvpx_test::kVP9TestVectors + + libvpx_test::kNumVP9TestVectors)); +} // namespace
diff --git a/src/third_party/libvpx/test/fdct4x4_test.cc b/src/third_party/libvpx/test/fdct4x4_test.cc new file mode 100644 index 0000000..735cccf --- /dev/null +++ b/src/third_party/libvpx/test/fdct4x4_test.cc
@@ -0,0 +1,546 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <math.h> +#include <stdlib.h> +#include <string.h> + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "./vp9_rtcd.h" +#include "./vpx_dsp_rtcd.h" +#include "test/acm_random.h" +#include "test/clear_system_state.h" +#include "test/register_state_check.h" +#include "test/util.h" +#include "vp9/common/vp9_entropy.h" +#include "vpx/vpx_codec.h" +#include "vpx/vpx_integer.h" +#include "vpx_ports/mem.h" + +using libvpx_test::ACMRandom; + +namespace { +const int kNumCoeffs = 16; +typedef void (*FdctFunc)(const int16_t *in, tran_low_t *out, int stride); +typedef void (*IdctFunc)(const tran_low_t *in, uint8_t *out, int stride); +typedef void (*FhtFunc)(const int16_t *in, tran_low_t *out, int stride, + int tx_type); +typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride, + int tx_type); + +typedef std::tr1::tuple<FdctFunc, IdctFunc, int, vpx_bit_depth_t> Dct4x4Param; +typedef std::tr1::tuple<FhtFunc, IhtFunc, int, vpx_bit_depth_t> Ht4x4Param; + +void fdct4x4_ref(const int16_t *in, tran_low_t *out, int stride, + int /*tx_type*/) { + vpx_fdct4x4_c(in, out, stride); +} + +void fht4x4_ref(const int16_t *in, tran_low_t *out, int stride, int tx_type) { + vp9_fht4x4_c(in, out, stride, tx_type); +} + +void fwht4x4_ref(const int16_t *in, tran_low_t *out, int stride, + int /*tx_type*/) { + vp9_fwht4x4_c(in, out, stride); +} + +#if CONFIG_VP9_HIGHBITDEPTH +void idct4x4_10(const tran_low_t *in, uint8_t *out, int stride) { + vpx_highbd_idct4x4_16_add_c(in, out, stride, 10); +} + +void idct4x4_12(const tran_low_t *in, uint8_t *out, int stride) { + vpx_highbd_idct4x4_16_add_c(in, out, stride, 12); +} + +void iht4x4_10(const tran_low_t *in, uint8_t *out, int stride, int tx_type) { + vp9_highbd_iht4x4_16_add_c(in, out, stride, tx_type, 10); +} + +void iht4x4_12(const tran_low_t *in, uint8_t *out, int stride, int tx_type) { + vp9_highbd_iht4x4_16_add_c(in, out, stride, tx_type, 12); +} + +void iwht4x4_10(const tran_low_t *in, uint8_t *out, int stride) { + vpx_highbd_iwht4x4_16_add_c(in, out, stride, 10); +} + +void iwht4x4_12(const tran_low_t *in, uint8_t *out, int stride) { + vpx_highbd_iwht4x4_16_add_c(in, out, stride, 12); +} + +#if HAVE_SSE2 +void idct4x4_10_sse2(const tran_low_t *in, uint8_t *out, int stride) { + vpx_highbd_idct4x4_16_add_sse2(in, out, stride, 10); +} + +void idct4x4_12_sse2(const tran_low_t *in, uint8_t *out, int stride) { + vpx_highbd_idct4x4_16_add_sse2(in, out, stride, 12); +} +#endif // HAVE_SSE2 +#endif // CONFIG_VP9_HIGHBITDEPTH + +class Trans4x4TestBase { + public: + virtual ~Trans4x4TestBase() {} + + protected: + virtual void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) = 0; + + virtual void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) = 0; + + void RunAccuracyCheck(int limit) { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + uint32_t max_error = 0; + int64_t total_error = 0; + const int count_test_block = 10000; + for (int i = 0; i < count_test_block; ++i) { + DECLARE_ALIGNED(16, int16_t, test_input_block[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, test_temp_block[kNumCoeffs]); + DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]); + DECLARE_ALIGNED(16, uint8_t, src[kNumCoeffs]); +#if CONFIG_VP9_HIGHBITDEPTH + DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]); + DECLARE_ALIGNED(16, uint16_t, src16[kNumCoeffs]); +#endif + + // Initialize a test block with input range [-255, 255]. + for (int j = 0; j < kNumCoeffs; ++j) { + if (bit_depth_ == VPX_BITS_8) { + src[j] = rnd.Rand8(); + dst[j] = rnd.Rand8(); + test_input_block[j] = src[j] - dst[j]; +#if CONFIG_VP9_HIGHBITDEPTH + } else { + src16[j] = rnd.Rand16() & mask_; + dst16[j] = rnd.Rand16() & mask_; + test_input_block[j] = src16[j] - dst16[j]; +#endif + } + } + + ASM_REGISTER_STATE_CHECK(RunFwdTxfm(test_input_block, + test_temp_block, pitch_)); + if (bit_depth_ == VPX_BITS_8) { + ASM_REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block, dst, pitch_)); +#if CONFIG_VP9_HIGHBITDEPTH + } else { + ASM_REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block, + CONVERT_TO_BYTEPTR(dst16), pitch_)); +#endif + } + + for (int j = 0; j < kNumCoeffs; ++j) { +#if CONFIG_VP9_HIGHBITDEPTH + const int diff = + bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j]; +#else + ASSERT_EQ(VPX_BITS_8, bit_depth_); + const int diff = dst[j] - src[j]; +#endif + const uint32_t error = diff * diff; + if (max_error < error) + max_error = error; + total_error += error; + } + } + + EXPECT_GE(static_cast<uint32_t>(limit), max_error) + << "Error: 4x4 FHT/IHT has an individual round trip error > " + << limit; + + EXPECT_GE(count_test_block * limit, total_error) + << "Error: 4x4 FHT/IHT has average round trip error > " << limit + << " per block"; + } + + void RunCoeffCheck() { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + const int count_test_block = 5000; + DECLARE_ALIGNED(16, int16_t, input_block[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, output_block[kNumCoeffs]); + + for (int i = 0; i < count_test_block; ++i) { + // Initialize a test block with input range [-mask_, mask_]. + for (int j = 0; j < kNumCoeffs; ++j) + input_block[j] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_); + + fwd_txfm_ref(input_block, output_ref_block, pitch_, tx_type_); + ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_block, output_block, pitch_)); + + // The minimum quant value is 4. + for (int j = 0; j < kNumCoeffs; ++j) + EXPECT_EQ(output_block[j], output_ref_block[j]); + } + } + + void RunMemCheck() { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + const int count_test_block = 5000; + DECLARE_ALIGNED(16, int16_t, input_extreme_block[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, output_block[kNumCoeffs]); + + for (int i = 0; i < count_test_block; ++i) { + // Initialize a test block with input range [-mask_, mask_]. + for (int j = 0; j < kNumCoeffs; ++j) { + input_extreme_block[j] = rnd.Rand8() % 2 ? mask_ : -mask_; + } + if (i == 0) { + for (int j = 0; j < kNumCoeffs; ++j) + input_extreme_block[j] = mask_; + } else if (i == 1) { + for (int j = 0; j < kNumCoeffs; ++j) + input_extreme_block[j] = -mask_; + } + + fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_); + ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_extreme_block, + output_block, pitch_)); + + // The minimum quant value is 4. + for (int j = 0; j < kNumCoeffs; ++j) { + EXPECT_EQ(output_block[j], output_ref_block[j]); + EXPECT_GE(4 * DCT_MAX_VALUE << (bit_depth_ - 8), abs(output_block[j])) + << "Error: 4x4 FDCT has coefficient larger than 4*DCT_MAX_VALUE"; + } + } + } + + void RunInvAccuracyCheck(int limit) { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + const int count_test_block = 1000; + DECLARE_ALIGNED(16, int16_t, in[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, coeff[kNumCoeffs]); + DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]); + DECLARE_ALIGNED(16, uint8_t, src[kNumCoeffs]); +#if CONFIG_VP9_HIGHBITDEPTH + DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]); + DECLARE_ALIGNED(16, uint16_t, src16[kNumCoeffs]); +#endif + + for (int i = 0; i < count_test_block; ++i) { + // Initialize a test block with input range [-mask_, mask_]. + for (int j = 0; j < kNumCoeffs; ++j) { + if (bit_depth_ == VPX_BITS_8) { + src[j] = rnd.Rand8(); + dst[j] = rnd.Rand8(); + in[j] = src[j] - dst[j]; +#if CONFIG_VP9_HIGHBITDEPTH + } else { + src16[j] = rnd.Rand16() & mask_; + dst16[j] = rnd.Rand16() & mask_; + in[j] = src16[j] - dst16[j]; +#endif + } + } + + fwd_txfm_ref(in, coeff, pitch_, tx_type_); + + if (bit_depth_ == VPX_BITS_8) { + ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_)); +#if CONFIG_VP9_HIGHBITDEPTH + } else { + ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16), + pitch_)); +#endif + } + + for (int j = 0; j < kNumCoeffs; ++j) { +#if CONFIG_VP9_HIGHBITDEPTH + const int diff = + bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j]; +#else + const int diff = dst[j] - src[j]; +#endif + const uint32_t error = diff * diff; + EXPECT_GE(static_cast<uint32_t>(limit), error) + << "Error: 4x4 IDCT has error " << error + << " at index " << j; + } + } + } + + int pitch_; + int tx_type_; + FhtFunc fwd_txfm_ref; + vpx_bit_depth_t bit_depth_; + int mask_; +}; + +class Trans4x4DCT + : public Trans4x4TestBase, + public ::testing::TestWithParam<Dct4x4Param> { + public: + virtual ~Trans4x4DCT() {} + + virtual void SetUp() { + fwd_txfm_ = GET_PARAM(0); + inv_txfm_ = GET_PARAM(1); + tx_type_ = GET_PARAM(2); + pitch_ = 4; + fwd_txfm_ref = fdct4x4_ref; + bit_depth_ = GET_PARAM(3); + mask_ = (1 << bit_depth_) - 1; + } + virtual void TearDown() { libvpx_test::ClearSystemState(); } + + protected: + void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) { + fwd_txfm_(in, out, stride); + } + void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) { + inv_txfm_(out, dst, stride); + } + + FdctFunc fwd_txfm_; + IdctFunc inv_txfm_; +}; + +TEST_P(Trans4x4DCT, AccuracyCheck) { + RunAccuracyCheck(1); +} + +TEST_P(Trans4x4DCT, CoeffCheck) { + RunCoeffCheck(); +} + +TEST_P(Trans4x4DCT, MemCheck) { + RunMemCheck(); +} + +TEST_P(Trans4x4DCT, InvAccuracyCheck) { + RunInvAccuracyCheck(1); +} + +class Trans4x4HT + : public Trans4x4TestBase, + public ::testing::TestWithParam<Ht4x4Param> { + public: + virtual ~Trans4x4HT() {} + + virtual void SetUp() { + fwd_txfm_ = GET_PARAM(0); + inv_txfm_ = GET_PARAM(1); + tx_type_ = GET_PARAM(2); + pitch_ = 4; + fwd_txfm_ref = fht4x4_ref; + bit_depth_ = GET_PARAM(3); + mask_ = (1 << bit_depth_) - 1; + } + virtual void TearDown() { libvpx_test::ClearSystemState(); } + + protected: + void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) { + fwd_txfm_(in, out, stride, tx_type_); + } + + void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) { + inv_txfm_(out, dst, stride, tx_type_); + } + + FhtFunc fwd_txfm_; + IhtFunc inv_txfm_; +}; + +TEST_P(Trans4x4HT, AccuracyCheck) { + RunAccuracyCheck(1); +} + +TEST_P(Trans4x4HT, CoeffCheck) { + RunCoeffCheck(); +} + +TEST_P(Trans4x4HT, MemCheck) { + RunMemCheck(); +} + +TEST_P(Trans4x4HT, InvAccuracyCheck) { + RunInvAccuracyCheck(1); +} + +class Trans4x4WHT + : public Trans4x4TestBase, + public ::testing::TestWithParam<Dct4x4Param> { + public: + virtual ~Trans4x4WHT() {} + + virtual void SetUp() { + fwd_txfm_ = GET_PARAM(0); + inv_txfm_ = GET_PARAM(1); + tx_type_ = GET_PARAM(2); + pitch_ = 4; + fwd_txfm_ref = fwht4x4_ref; + bit_depth_ = GET_PARAM(3); + mask_ = (1 << bit_depth_) - 1; + } + virtual void TearDown() { libvpx_test::ClearSystemState(); } + + protected: + void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) { + fwd_txfm_(in, out, stride); + } + void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) { + inv_txfm_(out, dst, stride); + } + + FdctFunc fwd_txfm_; + IdctFunc inv_txfm_; +}; + +TEST_P(Trans4x4WHT, AccuracyCheck) { + RunAccuracyCheck(0); +} + +TEST_P(Trans4x4WHT, CoeffCheck) { + RunCoeffCheck(); +} + +TEST_P(Trans4x4WHT, MemCheck) { + RunMemCheck(); +} + +TEST_P(Trans4x4WHT, InvAccuracyCheck) { + RunInvAccuracyCheck(0); +} +using std::tr1::make_tuple; + +#if CONFIG_VP9_HIGHBITDEPTH +INSTANTIATE_TEST_CASE_P( + C, Trans4x4DCT, + ::testing::Values( + make_tuple(&vpx_highbd_fdct4x4_c, &idct4x4_10, 0, VPX_BITS_10), + make_tuple(&vpx_highbd_fdct4x4_c, &idct4x4_12, 0, VPX_BITS_12), + make_tuple(&vpx_fdct4x4_c, &vpx_idct4x4_16_add_c, 0, VPX_BITS_8))); +#else +INSTANTIATE_TEST_CASE_P( + C, Trans4x4DCT, + ::testing::Values( + make_tuple(&vpx_fdct4x4_c, &vpx_idct4x4_16_add_c, 0, VPX_BITS_8))); +#endif // CONFIG_VP9_HIGHBITDEPTH + +#if CONFIG_VP9_HIGHBITDEPTH +INSTANTIATE_TEST_CASE_P( + C, Trans4x4HT, + ::testing::Values( + make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_10, 0, VPX_BITS_10), + make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_10, 1, VPX_BITS_10), + make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_10, 2, VPX_BITS_10), + make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_10, 3, VPX_BITS_10), + make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_12, 0, VPX_BITS_12), + make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_12, 1, VPX_BITS_12), + make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_12, 2, VPX_BITS_12), + make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_12, 3, VPX_BITS_12), + make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 0, VPX_BITS_8), + make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 1, VPX_BITS_8), + make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 2, VPX_BITS_8), + make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 3, VPX_BITS_8))); +#else +INSTANTIATE_TEST_CASE_P( + C, Trans4x4HT, + ::testing::Values( + make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 0, VPX_BITS_8), + make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 1, VPX_BITS_8), + make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 2, VPX_BITS_8), + make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 3, VPX_BITS_8))); +#endif // CONFIG_VP9_HIGHBITDEPTH + +#if CONFIG_VP9_HIGHBITDEPTH +INSTANTIATE_TEST_CASE_P( + C, Trans4x4WHT, + ::testing::Values( + make_tuple(&vp9_highbd_fwht4x4_c, &iwht4x4_10, 0, VPX_BITS_10), + make_tuple(&vp9_highbd_fwht4x4_c, &iwht4x4_12, 0, VPX_BITS_12), + make_tuple(&vp9_fwht4x4_c, &vpx_iwht4x4_16_add_c, 0, VPX_BITS_8))); +#else +INSTANTIATE_TEST_CASE_P( + C, Trans4x4WHT, + ::testing::Values( + make_tuple(&vp9_fwht4x4_c, &vpx_iwht4x4_16_add_c, 0, VPX_BITS_8))); +#endif // CONFIG_VP9_HIGHBITDEPTH + +#if HAVE_NEON_ASM && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + NEON, Trans4x4DCT, + ::testing::Values( + make_tuple(&vpx_fdct4x4_c, + &vpx_idct4x4_16_add_neon, 0, VPX_BITS_8))); +#endif // HAVE_NEON_ASM && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE + +#if HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + NEON, Trans4x4HT, + ::testing::Values( + make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_neon, 0, VPX_BITS_8), + make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_neon, 1, VPX_BITS_8), + make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_neon, 2, VPX_BITS_8), + make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_neon, 3, VPX_BITS_8))); +#endif // HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE + +#if CONFIG_USE_X86INC && HAVE_SSE2 && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + SSE2, Trans4x4WHT, + ::testing::Values( + make_tuple(&vp9_fwht4x4_sse2, &vpx_iwht4x4_16_add_c, 0, VPX_BITS_8), + make_tuple(&vp9_fwht4x4_c, &vpx_iwht4x4_16_add_sse2, 0, VPX_BITS_8))); +#endif + +#if HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + SSE2, Trans4x4DCT, + ::testing::Values( + make_tuple(&vpx_fdct4x4_sse2, + &vpx_idct4x4_16_add_sse2, 0, VPX_BITS_8))); +INSTANTIATE_TEST_CASE_P( + SSE2, Trans4x4HT, + ::testing::Values( + make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_sse2, 0, VPX_BITS_8), + make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_sse2, 1, VPX_BITS_8), + make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_sse2, 2, VPX_BITS_8), + make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_sse2, 3, VPX_BITS_8))); +#endif // HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE + +#if HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + SSE2, Trans4x4DCT, + ::testing::Values( + make_tuple(&vpx_highbd_fdct4x4_c, &idct4x4_10_sse2, 0, VPX_BITS_10), + make_tuple(&vpx_highbd_fdct4x4_sse2, &idct4x4_10_sse2, 0, VPX_BITS_10), + make_tuple(&vpx_highbd_fdct4x4_c, &idct4x4_12_sse2, 0, VPX_BITS_12), + make_tuple(&vpx_highbd_fdct4x4_sse2, &idct4x4_12_sse2, 0, VPX_BITS_12), + make_tuple(&vpx_fdct4x4_sse2, &vpx_idct4x4_16_add_c, 0, + VPX_BITS_8))); + +INSTANTIATE_TEST_CASE_P( + SSE2, Trans4x4HT, + ::testing::Values( + make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_c, 0, VPX_BITS_8), + make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_c, 1, VPX_BITS_8), + make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_c, 2, VPX_BITS_8), + make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_c, 3, VPX_BITS_8))); +#endif // HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE + +#if HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + MSA, Trans4x4DCT, + ::testing::Values( + make_tuple(&vpx_fdct4x4_msa, &vpx_idct4x4_16_add_msa, 0, VPX_BITS_8))); +INSTANTIATE_TEST_CASE_P( + MSA, Trans4x4HT, + ::testing::Values( + make_tuple(&vp9_fht4x4_msa, &vp9_iht4x4_16_add_msa, 0, VPX_BITS_8), + make_tuple(&vp9_fht4x4_msa, &vp9_iht4x4_16_add_msa, 1, VPX_BITS_8), + make_tuple(&vp9_fht4x4_msa, &vp9_iht4x4_16_add_msa, 2, VPX_BITS_8), + make_tuple(&vp9_fht4x4_msa, &vp9_iht4x4_16_add_msa, 3, VPX_BITS_8))); +#endif // HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +} // namespace
diff --git a/src/third_party/libvpx/test/fdct8x8_test.cc b/src/third_party/libvpx/test/fdct8x8_test.cc new file mode 100644 index 0000000..29f2158 --- /dev/null +++ b/src/third_party/libvpx/test/fdct8x8_test.cc
@@ -0,0 +1,791 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <math.h> +#include <stdlib.h> +#include <string.h> + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "./vp9_rtcd.h" +#include "./vpx_dsp_rtcd.h" +#include "test/acm_random.h" +#include "test/clear_system_state.h" +#include "test/register_state_check.h" +#include "test/util.h" +#include "vp9/common/vp9_entropy.h" +#include "vp9/common/vp9_scan.h" +#include "vpx/vpx_codec.h" +#include "vpx/vpx_integer.h" +#include "vpx_ports/mem.h" + +using libvpx_test::ACMRandom; + +namespace { + +const int kNumCoeffs = 64; +const double kPi = 3.141592653589793238462643383279502884; + +const int kSignBiasMaxDiff255 = 1500; +const int kSignBiasMaxDiff15 = 10000; + +typedef void (*FdctFunc)(const int16_t *in, tran_low_t *out, int stride); +typedef void (*IdctFunc)(const tran_low_t *in, uint8_t *out, int stride); +typedef void (*FhtFunc)(const int16_t *in, tran_low_t *out, int stride, + int tx_type); +typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride, + int tx_type); + +typedef std::tr1::tuple<FdctFunc, IdctFunc, int, vpx_bit_depth_t> Dct8x8Param; +typedef std::tr1::tuple<FhtFunc, IhtFunc, int, vpx_bit_depth_t> Ht8x8Param; +typedef std::tr1::tuple<IdctFunc, IdctFunc, int, vpx_bit_depth_t> Idct8x8Param; + +void reference_8x8_dct_1d(const double in[8], double out[8]) { + const double kInvSqrt2 = 0.707106781186547524400844362104; + for (int k = 0; k < 8; k++) { + out[k] = 0.0; + for (int n = 0; n < 8; n++) + out[k] += in[n] * cos(kPi * (2 * n + 1) * k / 16.0); + if (k == 0) + out[k] = out[k] * kInvSqrt2; + } +} + +void reference_8x8_dct_2d(const int16_t input[kNumCoeffs], + double output[kNumCoeffs]) { + // First transform columns + for (int i = 0; i < 8; ++i) { + double temp_in[8], temp_out[8]; + for (int j = 0; j < 8; ++j) + temp_in[j] = input[j*8 + i]; + reference_8x8_dct_1d(temp_in, temp_out); + for (int j = 0; j < 8; ++j) + output[j * 8 + i] = temp_out[j]; + } + // Then transform rows + for (int i = 0; i < 8; ++i) { + double temp_in[8], temp_out[8]; + for (int j = 0; j < 8; ++j) + temp_in[j] = output[j + i*8]; + reference_8x8_dct_1d(temp_in, temp_out); + // Scale by some magic number + for (int j = 0; j < 8; ++j) + output[j + i * 8] = temp_out[j] * 2; + } +} + + +void fdct8x8_ref(const int16_t *in, tran_low_t *out, int stride, + int /*tx_type*/) { + vpx_fdct8x8_c(in, out, stride); +} + +void fht8x8_ref(const int16_t *in, tran_low_t *out, int stride, int tx_type) { + vp9_fht8x8_c(in, out, stride, tx_type); +} + +#if CONFIG_VP9_HIGHBITDEPTH +void idct8x8_10(const tran_low_t *in, uint8_t *out, int stride) { + vpx_highbd_idct8x8_64_add_c(in, out, stride, 10); +} + +void idct8x8_12(const tran_low_t *in, uint8_t *out, int stride) { + vpx_highbd_idct8x8_64_add_c(in, out, stride, 12); +} + +void iht8x8_10(const tran_low_t *in, uint8_t *out, int stride, int tx_type) { + vp9_highbd_iht8x8_64_add_c(in, out, stride, tx_type, 10); +} + +void iht8x8_12(const tran_low_t *in, uint8_t *out, int stride, int tx_type) { + vp9_highbd_iht8x8_64_add_c(in, out, stride, tx_type, 12); +} + +#if HAVE_SSE2 + +void idct8x8_10_add_10_c(const tran_low_t *in, uint8_t *out, int stride) { + vpx_highbd_idct8x8_10_add_c(in, out, stride, 10); +} + +void idct8x8_10_add_12_c(const tran_low_t *in, uint8_t *out, int stride) { + vpx_highbd_idct8x8_10_add_c(in, out, stride, 12); +} + +void idct8x8_10_add_10_sse2(const tran_low_t *in, uint8_t *out, int stride) { + vpx_highbd_idct8x8_10_add_sse2(in, out, stride, 10); +} + +void idct8x8_10_add_12_sse2(const tran_low_t *in, uint8_t *out, int stride) { + vpx_highbd_idct8x8_10_add_sse2(in, out, stride, 12); +} + +void idct8x8_64_add_10_sse2(const tran_low_t *in, uint8_t *out, int stride) { + vpx_highbd_idct8x8_64_add_sse2(in, out, stride, 10); +} + +void idct8x8_64_add_12_sse2(const tran_low_t *in, uint8_t *out, int stride) { + vpx_highbd_idct8x8_64_add_sse2(in, out, stride, 12); +} +#endif // HAVE_SSE2 +#endif // CONFIG_VP9_HIGHBITDEPTH + +class FwdTrans8x8TestBase { + public: + virtual ~FwdTrans8x8TestBase() {} + + protected: + virtual void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) = 0; + virtual void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) = 0; + + void RunSignBiasCheck() { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + DECLARE_ALIGNED(16, int16_t, test_input_block[64]); + DECLARE_ALIGNED(16, tran_low_t, test_output_block[64]); + int count_sign_block[64][2]; + const int count_test_block = 100000; + + memset(count_sign_block, 0, sizeof(count_sign_block)); + + for (int i = 0; i < count_test_block; ++i) { + // Initialize a test block with input range [-255, 255]. + for (int j = 0; j < 64; ++j) + test_input_block[j] = ((rnd.Rand16() >> (16 - bit_depth_)) & mask_) - + ((rnd.Rand16() >> (16 - bit_depth_)) & mask_); + ASM_REGISTER_STATE_CHECK( + RunFwdTxfm(test_input_block, test_output_block, pitch_)); + + for (int j = 0; j < 64; ++j) { + if (test_output_block[j] < 0) + ++count_sign_block[j][0]; + else if (test_output_block[j] > 0) + ++count_sign_block[j][1]; + } + } + + for (int j = 0; j < 64; ++j) { + const int diff = abs(count_sign_block[j][0] - count_sign_block[j][1]); + const int max_diff = kSignBiasMaxDiff255; + EXPECT_LT(diff, max_diff << (bit_depth_ - 8)) + << "Error: 8x8 FDCT/FHT has a sign bias > " + << 1. * max_diff / count_test_block * 100 << "%" + << " for input range [-255, 255] at index " << j + << " count0: " << count_sign_block[j][0] + << " count1: " << count_sign_block[j][1] + << " diff: " << diff; + } + + memset(count_sign_block, 0, sizeof(count_sign_block)); + + for (int i = 0; i < count_test_block; ++i) { + // Initialize a test block with input range [-mask_ / 16, mask_ / 16]. + for (int j = 0; j < 64; ++j) + test_input_block[j] = ((rnd.Rand16() & mask_) >> 4) - + ((rnd.Rand16() & mask_) >> 4); + ASM_REGISTER_STATE_CHECK( + RunFwdTxfm(test_input_block, test_output_block, pitch_)); + + for (int j = 0; j < 64; ++j) { + if (test_output_block[j] < 0) + ++count_sign_block[j][0]; + else if (test_output_block[j] > 0) + ++count_sign_block[j][1]; + } + } + + for (int j = 0; j < 64; ++j) { + const int diff = abs(count_sign_block[j][0] - count_sign_block[j][1]); + const int max_diff = kSignBiasMaxDiff15; + EXPECT_LT(diff, max_diff << (bit_depth_ - 8)) + << "Error: 8x8 FDCT/FHT has a sign bias > " + << 1. * max_diff / count_test_block * 100 << "%" + << " for input range [-15, 15] at index " << j + << " count0: " << count_sign_block[j][0] + << " count1: " << count_sign_block[j][1] + << " diff: " << diff; + } + } + + void RunRoundTripErrorCheck() { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + int max_error = 0; + int total_error = 0; + const int count_test_block = 100000; + DECLARE_ALIGNED(16, int16_t, test_input_block[64]); + DECLARE_ALIGNED(16, tran_low_t, test_temp_block[64]); + DECLARE_ALIGNED(16, uint8_t, dst[64]); + DECLARE_ALIGNED(16, uint8_t, src[64]); +#if CONFIG_VP9_HIGHBITDEPTH + DECLARE_ALIGNED(16, uint16_t, dst16[64]); + DECLARE_ALIGNED(16, uint16_t, src16[64]); +#endif + + for (int i = 0; i < count_test_block; ++i) { + // Initialize a test block with input range [-mask_, mask_]. + for (int j = 0; j < 64; ++j) { + if (bit_depth_ == VPX_BITS_8) { + src[j] = rnd.Rand8(); + dst[j] = rnd.Rand8(); + test_input_block[j] = src[j] - dst[j]; +#if CONFIG_VP9_HIGHBITDEPTH + } else { + src16[j] = rnd.Rand16() & mask_; + dst16[j] = rnd.Rand16() & mask_; + test_input_block[j] = src16[j] - dst16[j]; +#endif + } + } + + ASM_REGISTER_STATE_CHECK( + RunFwdTxfm(test_input_block, test_temp_block, pitch_)); + for (int j = 0; j < 64; ++j) { + if (test_temp_block[j] > 0) { + test_temp_block[j] += 2; + test_temp_block[j] /= 4; + test_temp_block[j] *= 4; + } else { + test_temp_block[j] -= 2; + test_temp_block[j] /= 4; + test_temp_block[j] *= 4; + } + } + if (bit_depth_ == VPX_BITS_8) { + ASM_REGISTER_STATE_CHECK( + RunInvTxfm(test_temp_block, dst, pitch_)); +#if CONFIG_VP9_HIGHBITDEPTH + } else { + ASM_REGISTER_STATE_CHECK( + RunInvTxfm(test_temp_block, CONVERT_TO_BYTEPTR(dst16), pitch_)); +#endif + } + + for (int j = 0; j < 64; ++j) { +#if CONFIG_VP9_HIGHBITDEPTH + const int diff = + bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j]; +#else + const int diff = dst[j] - src[j]; +#endif + const int error = diff * diff; + if (max_error < error) + max_error = error; + total_error += error; + } + } + + EXPECT_GE(1 << 2 * (bit_depth_ - 8), max_error) + << "Error: 8x8 FDCT/IDCT or FHT/IHT has an individual" + << " roundtrip error > 1"; + + EXPECT_GE((count_test_block << 2 * (bit_depth_ - 8))/5, total_error) + << "Error: 8x8 FDCT/IDCT or FHT/IHT has average roundtrip " + << "error > 1/5 per block"; + } + + void RunExtremalCheck() { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + int max_error = 0; + int total_error = 0; + int total_coeff_error = 0; + const int count_test_block = 100000; + DECLARE_ALIGNED(16, int16_t, test_input_block[64]); + DECLARE_ALIGNED(16, tran_low_t, test_temp_block[64]); + DECLARE_ALIGNED(16, tran_low_t, ref_temp_block[64]); + DECLARE_ALIGNED(16, uint8_t, dst[64]); + DECLARE_ALIGNED(16, uint8_t, src[64]); +#if CONFIG_VP9_HIGHBITDEPTH + DECLARE_ALIGNED(16, uint16_t, dst16[64]); + DECLARE_ALIGNED(16, uint16_t, src16[64]); +#endif + + for (int i = 0; i < count_test_block; ++i) { + // Initialize a test block with input range [-mask_, mask_]. + for (int j = 0; j < 64; ++j) { + if (bit_depth_ == VPX_BITS_8) { + if (i == 0) { + src[j] = 255; + dst[j] = 0; + } else if (i == 1) { + src[j] = 0; + dst[j] = 255; + } else { + src[j] = rnd.Rand8() % 2 ? 255 : 0; + dst[j] = rnd.Rand8() % 2 ? 255 : 0; + } + test_input_block[j] = src[j] - dst[j]; +#if CONFIG_VP9_HIGHBITDEPTH + } else { + if (i == 0) { + src16[j] = mask_; + dst16[j] = 0; + } else if (i == 1) { + src16[j] = 0; + dst16[j] = mask_; + } else { + src16[j] = rnd.Rand8() % 2 ? mask_ : 0; + dst16[j] = rnd.Rand8() % 2 ? mask_ : 0; + } + test_input_block[j] = src16[j] - dst16[j]; +#endif + } + } + + ASM_REGISTER_STATE_CHECK( + RunFwdTxfm(test_input_block, test_temp_block, pitch_)); + ASM_REGISTER_STATE_CHECK( + fwd_txfm_ref(test_input_block, ref_temp_block, pitch_, tx_type_)); + if (bit_depth_ == VPX_BITS_8) { + ASM_REGISTER_STATE_CHECK( + RunInvTxfm(test_temp_block, dst, pitch_)); +#if CONFIG_VP9_HIGHBITDEPTH + } else { + ASM_REGISTER_STATE_CHECK( + RunInvTxfm(test_temp_block, CONVERT_TO_BYTEPTR(dst16), pitch_)); +#endif + } + + for (int j = 0; j < 64; ++j) { +#if CONFIG_VP9_HIGHBITDEPTH + const int diff = + bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j]; +#else + const int diff = dst[j] - src[j]; +#endif + const int error = diff * diff; + if (max_error < error) + max_error = error; + total_error += error; + + const int coeff_diff = test_temp_block[j] - ref_temp_block[j]; + total_coeff_error += abs(coeff_diff); + } + + EXPECT_GE(1 << 2 * (bit_depth_ - 8), max_error) + << "Error: Extremal 8x8 FDCT/IDCT or FHT/IHT has" + << "an individual roundtrip error > 1"; + + EXPECT_GE((count_test_block << 2 * (bit_depth_ - 8))/5, total_error) + << "Error: Extremal 8x8 FDCT/IDCT or FHT/IHT has average" + << " roundtrip error > 1/5 per block"; + + EXPECT_EQ(0, total_coeff_error) + << "Error: Extremal 8x8 FDCT/FHT has" + << "overflow issues in the intermediate steps > 1"; + } + } + + void RunInvAccuracyCheck() { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + const int count_test_block = 1000; + DECLARE_ALIGNED(16, int16_t, in[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, coeff[kNumCoeffs]); + DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]); + DECLARE_ALIGNED(16, uint8_t, src[kNumCoeffs]); +#if CONFIG_VP9_HIGHBITDEPTH + DECLARE_ALIGNED(16, uint16_t, src16[kNumCoeffs]); + DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]); +#endif + + for (int i = 0; i < count_test_block; ++i) { + double out_r[kNumCoeffs]; + + // Initialize a test block with input range [-255, 255]. + for (int j = 0; j < kNumCoeffs; ++j) { + if (bit_depth_ == VPX_BITS_8) { + src[j] = rnd.Rand8() % 2 ? 255 : 0; + dst[j] = src[j] > 0 ? 0 : 255; + in[j] = src[j] - dst[j]; +#if CONFIG_VP9_HIGHBITDEPTH + } else { + src16[j] = rnd.Rand8() % 2 ? mask_ : 0; + dst16[j] = src16[j] > 0 ? 0 : mask_; + in[j] = src16[j] - dst16[j]; +#endif + } + } + + reference_8x8_dct_2d(in, out_r); + for (int j = 0; j < kNumCoeffs; ++j) + coeff[j] = static_cast<tran_low_t>(round(out_r[j])); + + if (bit_depth_ == VPX_BITS_8) { + ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_)); +#if CONFIG_VP9_HIGHBITDEPTH + } else { + ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16), + pitch_)); +#endif + } + + for (int j = 0; j < kNumCoeffs; ++j) { +#if CONFIG_VP9_HIGHBITDEPTH + const int diff = + bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j]; +#else + const int diff = dst[j] - src[j]; +#endif + const uint32_t error = diff * diff; + EXPECT_GE(1u << 2 * (bit_depth_ - 8), error) + << "Error: 8x8 IDCT has error " << error + << " at index " << j; + } + } + } + + void RunFwdAccuracyCheck() { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + const int count_test_block = 1000; + DECLARE_ALIGNED(16, int16_t, in[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, coeff_r[kNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, coeff[kNumCoeffs]); + + for (int i = 0; i < count_test_block; ++i) { + double out_r[kNumCoeffs]; + + // Initialize a test block with input range [-mask_, mask_]. + for (int j = 0; j < kNumCoeffs; ++j) + in[j] = rnd.Rand8() % 2 == 0 ? mask_ : -mask_; + + RunFwdTxfm(in, coeff, pitch_); + reference_8x8_dct_2d(in, out_r); + for (int j = 0; j < kNumCoeffs; ++j) + coeff_r[j] = static_cast<tran_low_t>(round(out_r[j])); + + for (int j = 0; j < kNumCoeffs; ++j) { + const int32_t diff = coeff[j] - coeff_r[j]; + const uint32_t error = diff * diff; + EXPECT_GE(9u << 2 * (bit_depth_ - 8), error) + << "Error: 8x8 DCT has error " << error + << " at index " << j; + } + } + } + +void CompareInvReference(IdctFunc ref_txfm, int thresh) { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + const int count_test_block = 10000; + const int eob = 12; + DECLARE_ALIGNED(16, tran_low_t, coeff[kNumCoeffs]); + DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]); + DECLARE_ALIGNED(16, uint8_t, ref[kNumCoeffs]); +#if CONFIG_VP9_HIGHBITDEPTH + DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]); + DECLARE_ALIGNED(16, uint16_t, ref16[kNumCoeffs]); +#endif + const int16_t *scan = vp9_default_scan_orders[TX_8X8].scan; + + for (int i = 0; i < count_test_block; ++i) { + for (int j = 0; j < kNumCoeffs; ++j) { + if (j < eob) { + // Random values less than the threshold, either positive or negative + coeff[scan[j]] = rnd(thresh) * (1-2*(i%2)); + } else { + coeff[scan[j]] = 0; + } + if (bit_depth_ == VPX_BITS_8) { + dst[j] = 0; + ref[j] = 0; +#if CONFIG_VP9_HIGHBITDEPTH + } else { + dst16[j] = 0; + ref16[j] = 0; +#endif + } + } + if (bit_depth_ == VPX_BITS_8) { + ref_txfm(coeff, ref, pitch_); + ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_)); +#if CONFIG_VP9_HIGHBITDEPTH + } else { + ref_txfm(coeff, CONVERT_TO_BYTEPTR(ref16), pitch_); + ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16), + pitch_)); +#endif + } + + for (int j = 0; j < kNumCoeffs; ++j) { +#if CONFIG_VP9_HIGHBITDEPTH + const int diff = + bit_depth_ == VPX_BITS_8 ? dst[j] - ref[j] : dst16[j] - ref16[j]; +#else + const int diff = dst[j] - ref[j]; +#endif + const uint32_t error = diff * diff; + EXPECT_EQ(0u, error) + << "Error: 8x8 IDCT has error " << error + << " at index " << j; + } + } + } + int pitch_; + int tx_type_; + FhtFunc fwd_txfm_ref; + vpx_bit_depth_t bit_depth_; + int mask_; +}; + +class FwdTrans8x8DCT + : public FwdTrans8x8TestBase, + public ::testing::TestWithParam<Dct8x8Param> { + public: + virtual ~FwdTrans8x8DCT() {} + + virtual void SetUp() { + fwd_txfm_ = GET_PARAM(0); + inv_txfm_ = GET_PARAM(1); + tx_type_ = GET_PARAM(2); + pitch_ = 8; + fwd_txfm_ref = fdct8x8_ref; + bit_depth_ = GET_PARAM(3); + mask_ = (1 << bit_depth_) - 1; + } + + virtual void TearDown() { libvpx_test::ClearSystemState(); } + + protected: + void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) { + fwd_txfm_(in, out, stride); + } + void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) { + inv_txfm_(out, dst, stride); + } + + FdctFunc fwd_txfm_; + IdctFunc inv_txfm_; +}; + +TEST_P(FwdTrans8x8DCT, SignBiasCheck) { + RunSignBiasCheck(); +} + +TEST_P(FwdTrans8x8DCT, RoundTripErrorCheck) { + RunRoundTripErrorCheck(); +} + +TEST_P(FwdTrans8x8DCT, ExtremalCheck) { + RunExtremalCheck(); +} + +TEST_P(FwdTrans8x8DCT, FwdAccuracyCheck) { + RunFwdAccuracyCheck(); +} + +TEST_P(FwdTrans8x8DCT, InvAccuracyCheck) { + RunInvAccuracyCheck(); +} + +class FwdTrans8x8HT + : public FwdTrans8x8TestBase, + public ::testing::TestWithParam<Ht8x8Param> { + public: + virtual ~FwdTrans8x8HT() {} + + virtual void SetUp() { + fwd_txfm_ = GET_PARAM(0); + inv_txfm_ = GET_PARAM(1); + tx_type_ = GET_PARAM(2); + pitch_ = 8; + fwd_txfm_ref = fht8x8_ref; + bit_depth_ = GET_PARAM(3); + mask_ = (1 << bit_depth_) - 1; + } + + virtual void TearDown() { libvpx_test::ClearSystemState(); } + + protected: + void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) { + fwd_txfm_(in, out, stride, tx_type_); + } + void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) { + inv_txfm_(out, dst, stride, tx_type_); + } + + FhtFunc fwd_txfm_; + IhtFunc inv_txfm_; +}; + +TEST_P(FwdTrans8x8HT, SignBiasCheck) { + RunSignBiasCheck(); +} + +TEST_P(FwdTrans8x8HT, RoundTripErrorCheck) { + RunRoundTripErrorCheck(); +} + +TEST_P(FwdTrans8x8HT, ExtremalCheck) { + RunExtremalCheck(); +} + +class InvTrans8x8DCT + : public FwdTrans8x8TestBase, + public ::testing::TestWithParam<Idct8x8Param> { + public: + virtual ~InvTrans8x8DCT() {} + + virtual void SetUp() { + ref_txfm_ = GET_PARAM(0); + inv_txfm_ = GET_PARAM(1); + thresh_ = GET_PARAM(2); + pitch_ = 8; + bit_depth_ = GET_PARAM(3); + mask_ = (1 << bit_depth_) - 1; + } + + virtual void TearDown() { libvpx_test::ClearSystemState(); } + + protected: + void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) { + inv_txfm_(out, dst, stride); + } + void RunFwdTxfm(int16_t * /*out*/, tran_low_t * /*dst*/, int /*stride*/) {} + + IdctFunc ref_txfm_; + IdctFunc inv_txfm_; + int thresh_; +}; + +TEST_P(InvTrans8x8DCT, CompareReference) { + CompareInvReference(ref_txfm_, thresh_); +} + +using std::tr1::make_tuple; + +#if CONFIG_VP9_HIGHBITDEPTH +INSTANTIATE_TEST_CASE_P( + C, FwdTrans8x8DCT, + ::testing::Values( + make_tuple(&vpx_fdct8x8_c, &vpx_idct8x8_64_add_c, 0, VPX_BITS_8), + make_tuple(&vpx_highbd_fdct8x8_c, &idct8x8_10, 0, VPX_BITS_10), + make_tuple(&vpx_highbd_fdct8x8_c, &idct8x8_12, 0, VPX_BITS_12))); +#else +INSTANTIATE_TEST_CASE_P( + C, FwdTrans8x8DCT, + ::testing::Values( + make_tuple(&vpx_fdct8x8_c, &vpx_idct8x8_64_add_c, 0, VPX_BITS_8))); +#endif // CONFIG_VP9_HIGHBITDEPTH + +#if CONFIG_VP9_HIGHBITDEPTH +INSTANTIATE_TEST_CASE_P( + C, FwdTrans8x8HT, + ::testing::Values( + make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 0, VPX_BITS_8), + make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_10, 0, VPX_BITS_10), + make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_10, 1, VPX_BITS_10), + make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_10, 2, VPX_BITS_10), + make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_10, 3, VPX_BITS_10), + make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_12, 0, VPX_BITS_12), + make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_12, 1, VPX_BITS_12), + make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_12, 2, VPX_BITS_12), + make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_12, 3, VPX_BITS_12), + make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 1, VPX_BITS_8), + make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 2, VPX_BITS_8), + make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 3, VPX_BITS_8))); +#else +INSTANTIATE_TEST_CASE_P( + C, FwdTrans8x8HT, + ::testing::Values( + make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 0, VPX_BITS_8), + make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 1, VPX_BITS_8), + make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 2, VPX_BITS_8), + make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 3, VPX_BITS_8))); +#endif // CONFIG_VP9_HIGHBITDEPTH + +#if HAVE_NEON_ASM && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + NEON, FwdTrans8x8DCT, + ::testing::Values( + make_tuple(&vpx_fdct8x8_neon, &vpx_idct8x8_64_add_neon, 0, + VPX_BITS_8))); +#endif // HAVE_NEON_ASM && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE + +#if HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + NEON, FwdTrans8x8HT, + ::testing::Values( + make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_neon, 0, VPX_BITS_8), + make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_neon, 1, VPX_BITS_8), + make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_neon, 2, VPX_BITS_8), + make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_neon, 3, VPX_BITS_8))); +#endif // HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE + +#if HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + SSE2, FwdTrans8x8DCT, + ::testing::Values( + make_tuple(&vpx_fdct8x8_sse2, &vpx_idct8x8_64_add_sse2, 0, + VPX_BITS_8))); +INSTANTIATE_TEST_CASE_P( + SSE2, FwdTrans8x8HT, + ::testing::Values( + make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_sse2, 0, VPX_BITS_8), + make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_sse2, 1, VPX_BITS_8), + make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_sse2, 2, VPX_BITS_8), + make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_sse2, 3, VPX_BITS_8))); +#endif // HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE + +#if HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + SSE2, FwdTrans8x8DCT, + ::testing::Values( + make_tuple(&vpx_fdct8x8_sse2, &vpx_idct8x8_64_add_c, 0, VPX_BITS_8), + make_tuple(&vpx_highbd_fdct8x8_c, + &idct8x8_64_add_10_sse2, 12, VPX_BITS_10), + make_tuple(&vpx_highbd_fdct8x8_sse2, + &idct8x8_64_add_10_sse2, 12, VPX_BITS_10), + make_tuple(&vpx_highbd_fdct8x8_c, + &idct8x8_64_add_12_sse2, 12, VPX_BITS_12), + make_tuple(&vpx_highbd_fdct8x8_sse2, + &idct8x8_64_add_12_sse2, 12, VPX_BITS_12))); + +INSTANTIATE_TEST_CASE_P( + SSE2, FwdTrans8x8HT, + ::testing::Values( + make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_c, 0, VPX_BITS_8), + make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_c, 1, VPX_BITS_8), + make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_c, 2, VPX_BITS_8), + make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_c, 3, VPX_BITS_8))); + +// Optimizations take effect at a threshold of 6201, so we use a value close to +// that to test both branches. +INSTANTIATE_TEST_CASE_P( + SSE2, InvTrans8x8DCT, + ::testing::Values( + make_tuple(&idct8x8_10_add_10_c, + &idct8x8_10_add_10_sse2, 6225, VPX_BITS_10), + make_tuple(&idct8x8_10, + &idct8x8_64_add_10_sse2, 6225, VPX_BITS_10), + make_tuple(&idct8x8_10_add_12_c, + &idct8x8_10_add_12_sse2, 6225, VPX_BITS_12), + make_tuple(&idct8x8_12, + &idct8x8_64_add_12_sse2, 6225, VPX_BITS_12))); +#endif // HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE + +#if HAVE_SSSE3 && CONFIG_USE_X86INC && ARCH_X86_64 && \ + !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + SSSE3, FwdTrans8x8DCT, + ::testing::Values( + make_tuple(&vpx_fdct8x8_ssse3, &vpx_idct8x8_64_add_ssse3, 0, + VPX_BITS_8))); +#endif + +#if HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + MSA, FwdTrans8x8DCT, + ::testing::Values( + make_tuple(&vpx_fdct8x8_msa, &vpx_idct8x8_64_add_msa, 0, VPX_BITS_8))); +INSTANTIATE_TEST_CASE_P( + MSA, FwdTrans8x8HT, + ::testing::Values( + make_tuple(&vp9_fht8x8_msa, &vp9_iht8x8_64_add_msa, 0, VPX_BITS_8), + make_tuple(&vp9_fht8x8_msa, &vp9_iht8x8_64_add_msa, 1, VPX_BITS_8), + make_tuple(&vp9_fht8x8_msa, &vp9_iht8x8_64_add_msa, 2, VPX_BITS_8), + make_tuple(&vp9_fht8x8_msa, &vp9_iht8x8_64_add_msa, 3, VPX_BITS_8))); +#endif // HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +} // namespace
diff --git a/src/third_party/libvpx/test/frame_size_tests.cc b/src/third_party/libvpx/test/frame_size_tests.cc new file mode 100644 index 0000000..d39c8f6 --- /dev/null +++ b/src/third_party/libvpx/test/frame_size_tests.cc
@@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "test/codec_factory.h" +#include "test/video_source.h" + +namespace { + +class VP9FrameSizeTestsLarge + : public ::libvpx_test::EncoderTest, + public ::testing::Test { + protected: + VP9FrameSizeTestsLarge() : EncoderTest(&::libvpx_test::kVP9), + expected_res_(VPX_CODEC_OK) {} + virtual ~VP9FrameSizeTestsLarge() {} + + virtual void SetUp() { + InitializeConfig(); + SetMode(::libvpx_test::kRealTime); + } + + virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec, + const libvpx_test::VideoSource& /*video*/, + libvpx_test::Decoder *decoder) { + EXPECT_EQ(expected_res_, res_dec) << decoder->DecodeError(); + return !::testing::Test::HasFailure(); + } + + virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, + ::libvpx_test::Encoder *encoder) { + if (video->frame() == 1) { + encoder->Control(VP8E_SET_CPUUSED, 7); + encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1); + encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7); + encoder->Control(VP8E_SET_ARNR_STRENGTH, 5); + encoder->Control(VP8E_SET_ARNR_TYPE, 3); + } + } + + int expected_res_; +}; + +TEST_F(VP9FrameSizeTestsLarge, TestInvalidSizes) { + ::libvpx_test::RandomVideoSource video; + +#if CONFIG_SIZE_LIMIT + video.SetSize(DECODE_WIDTH_LIMIT + 16, DECODE_HEIGHT_LIMIT + 16); + video.set_limit(2); + expected_res_ = VPX_CODEC_CORRUPT_FRAME; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); +#endif +} + +TEST_F(VP9FrameSizeTestsLarge, ValidSizes) { + ::libvpx_test::RandomVideoSource video; + +#if CONFIG_SIZE_LIMIT + video.SetSize(DECODE_WIDTH_LIMIT, DECODE_HEIGHT_LIMIT); + video.set_limit(2); + expected_res_ = VPX_CODEC_OK; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); +#else + // This test produces a pretty large single frame allocation, (roughly + // 25 megabits). The encoder allocates a good number of these frames + // one for each lag in frames (for 2 pass), and then one for each possible + // reference buffer (8) - we can end up with up to 30 buffers of roughly this + // size or almost 1 gig of memory. + // In total the allocations will exceed 2GiB which may cause a failure with + // mingw + wine, use a smaller size in that case. +#if defined(_WIN32) && !defined(_WIN64) || defined(__OS2__) + video.SetSize(4096, 3072); +#else + video.SetSize(4096, 4096); +#endif + video.set_limit(2); + expected_res_ = VPX_CODEC_OK; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); +#endif +} + +TEST_F(VP9FrameSizeTestsLarge, OneByOneVideo) { + ::libvpx_test::RandomVideoSource video; + + video.SetSize(1, 1); + video.set_limit(2); + expected_res_ = VPX_CODEC_OK; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); +} +} // namespace
diff --git a/src/third_party/libvpx/test/hadamard_test.cc b/src/third_party/libvpx/test/hadamard_test.cc new file mode 100644 index 0000000..7a5bd5b --- /dev/null +++ b/src/third_party/libvpx/test/hadamard_test.cc
@@ -0,0 +1,220 @@ +/* + * Copyright (c) 2016 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <algorithm> + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "./vpx_dsp_rtcd.h" + +#include "test/acm_random.h" +#include "test/register_state_check.h" + +namespace { + +using ::libvpx_test::ACMRandom; + +typedef void (*HadamardFunc)(const int16_t *a, int a_stride, int16_t *b); + +void hadamard_loop(const int16_t *a, int a_stride, int16_t *out) { + int16_t b[8]; + for (int i = 0; i < 8; i += 2) { + b[i + 0] = a[i * a_stride] + a[(i + 1) * a_stride]; + b[i + 1] = a[i * a_stride] - a[(i + 1) * a_stride]; + } + int16_t c[8]; + for (int i = 0; i < 8; i += 4) { + c[i + 0] = b[i + 0] + b[i + 2]; + c[i + 1] = b[i + 1] + b[i + 3]; + c[i + 2] = b[i + 0] - b[i + 2]; + c[i + 3] = b[i + 1] - b[i + 3]; + } + out[0] = c[0] + c[4]; + out[7] = c[1] + c[5]; + out[3] = c[2] + c[6]; + out[4] = c[3] + c[7]; + out[2] = c[0] - c[4]; + out[6] = c[1] - c[5]; + out[1] = c[2] - c[6]; + out[5] = c[3] - c[7]; +} + +void reference_hadamard8x8(const int16_t *a, int a_stride, int16_t *b) { + int16_t buf[64]; + for (int i = 0; i < 8; ++i) { + hadamard_loop(a + i, a_stride, buf + i * 8); + } + + for (int i = 0; i < 8; ++i) { + hadamard_loop(buf + i, 8, b + i * 8); + } +} + +void reference_hadamard16x16(const int16_t *a, int a_stride, int16_t *b) { + /* The source is a 16x16 block. The destination is rearranged to 8x32. + * Input is 9 bit. */ + reference_hadamard8x8(a + 0 + 0 * a_stride, a_stride, b + 0); + reference_hadamard8x8(a + 8 + 0 * a_stride, a_stride, b + 64); + reference_hadamard8x8(a + 0 + 8 * a_stride, a_stride, b + 128); + reference_hadamard8x8(a + 8 + 8 * a_stride, a_stride, b + 192); + + /* Overlay the 8x8 blocks and combine. */ + for (int i = 0; i < 64; ++i) { + /* 8x8 steps the range up to 15 bits. */ + const int16_t a0 = b[0]; + const int16_t a1 = b[64]; + const int16_t a2 = b[128]; + const int16_t a3 = b[192]; + + /* Prevent the result from escaping int16_t. */ + const int16_t b0 = (a0 + a1) >> 1; + const int16_t b1 = (a0 - a1) >> 1; + const int16_t b2 = (a2 + a3) >> 1; + const int16_t b3 = (a2 - a3) >> 1; + + /* Store a 16 bit value. */ + b[ 0] = b0 + b2; + b[ 64] = b1 + b3; + b[128] = b0 - b2; + b[192] = b1 - b3; + + ++b; + } +} + +class HadamardTestBase : public ::testing::TestWithParam<HadamardFunc> { + public: + virtual void SetUp() { + h_func_ = GetParam(); + rnd_.Reset(ACMRandom::DeterministicSeed()); + } + + protected: + HadamardFunc h_func_; + ACMRandom rnd_; +}; + +class Hadamard8x8Test : public HadamardTestBase {}; + +TEST_P(Hadamard8x8Test, CompareReferenceRandom) { + DECLARE_ALIGNED(16, int16_t, a[64]); + DECLARE_ALIGNED(16, int16_t, b[64]); + int16_t b_ref[64]; + for (int i = 0; i < 64; ++i) { + a[i] = rnd_.Rand9Signed(); + } + memset(b, 0, sizeof(b)); + memset(b_ref, 0, sizeof(b_ref)); + + reference_hadamard8x8(a, 8, b_ref); + ASM_REGISTER_STATE_CHECK(h_func_(a, 8, b)); + + // The order of the output is not important. Sort before checking. + std::sort(b, b + 64); + std::sort(b_ref, b_ref + 64); + EXPECT_EQ(0, memcmp(b, b_ref, sizeof(b))); +} + +TEST_P(Hadamard8x8Test, VaryStride) { + DECLARE_ALIGNED(16, int16_t, a[64 * 8]); + DECLARE_ALIGNED(16, int16_t, b[64]); + int16_t b_ref[64]; + for (int i = 0; i < 64 * 8; ++i) { + a[i] = rnd_.Rand9Signed(); + } + + for (int i = 8; i < 64; i += 8) { + memset(b, 0, sizeof(b)); + memset(b_ref, 0, sizeof(b_ref)); + + reference_hadamard8x8(a, i, b_ref); + ASM_REGISTER_STATE_CHECK(h_func_(a, i, b)); + + // The order of the output is not important. Sort before checking. + std::sort(b, b + 64); + std::sort(b_ref, b_ref + 64); + EXPECT_EQ(0, memcmp(b, b_ref, sizeof(b))); + } +} + +INSTANTIATE_TEST_CASE_P(C, Hadamard8x8Test, + ::testing::Values(&vpx_hadamard_8x8_c)); + +#if HAVE_SSE2 +INSTANTIATE_TEST_CASE_P(SSE2, Hadamard8x8Test, + ::testing::Values(&vpx_hadamard_8x8_sse2)); +#endif // HAVE_SSE2 + +#if HAVE_SSSE3 && CONFIG_USE_X86INC && ARCH_X86_64 +INSTANTIATE_TEST_CASE_P(SSSE3, Hadamard8x8Test, + ::testing::Values(&vpx_hadamard_8x8_ssse3)); +#endif // HAVE_SSSE3 && CONFIG_USE_X86INC && ARCH_X86_64 + +#if HAVE_NEON +INSTANTIATE_TEST_CASE_P(NEON, Hadamard8x8Test, + ::testing::Values(&vpx_hadamard_8x8_neon)); +#endif // HAVE_NEON + +class Hadamard16x16Test : public HadamardTestBase {}; + +TEST_P(Hadamard16x16Test, CompareReferenceRandom) { + DECLARE_ALIGNED(16, int16_t, a[16 * 16]); + DECLARE_ALIGNED(16, int16_t, b[16 * 16]); + int16_t b_ref[16 * 16]; + for (int i = 0; i < 16 * 16; ++i) { + a[i] = rnd_.Rand9Signed(); + } + memset(b, 0, sizeof(b)); + memset(b_ref, 0, sizeof(b_ref)); + + reference_hadamard16x16(a, 16, b_ref); + ASM_REGISTER_STATE_CHECK(h_func_(a, 16, b)); + + // The order of the output is not important. Sort before checking. + std::sort(b, b + 16 * 16); + std::sort(b_ref, b_ref + 16 * 16); + EXPECT_EQ(0, memcmp(b, b_ref, sizeof(b))); +} + +TEST_P(Hadamard16x16Test, VaryStride) { + DECLARE_ALIGNED(16, int16_t, a[16 * 16 * 8]); + DECLARE_ALIGNED(16, int16_t, b[16 * 16]); + int16_t b_ref[16 * 16]; + for (int i = 0; i < 16 * 16 * 8; ++i) { + a[i] = rnd_.Rand9Signed(); + } + + for (int i = 8; i < 64; i += 8) { + memset(b, 0, sizeof(b)); + memset(b_ref, 0, sizeof(b_ref)); + + reference_hadamard16x16(a, i, b_ref); + ASM_REGISTER_STATE_CHECK(h_func_(a, i, b)); + + // The order of the output is not important. Sort before checking. + std::sort(b, b + 16 * 16); + std::sort(b_ref, b_ref + 16 * 16); + EXPECT_EQ(0, memcmp(b, b_ref, sizeof(b))); + } +} + +INSTANTIATE_TEST_CASE_P(C, Hadamard16x16Test, + ::testing::Values(&vpx_hadamard_16x16_c)); + +#if HAVE_SSE2 +INSTANTIATE_TEST_CASE_P(SSE2, Hadamard16x16Test, + ::testing::Values(&vpx_hadamard_16x16_sse2)); +#endif // HAVE_SSE2 + +#if HAVE_NEON +INSTANTIATE_TEST_CASE_P(NEON, Hadamard16x16Test, + ::testing::Values(&vpx_hadamard_16x16_neon)); +#endif // HAVE_NEON +} // namespace
diff --git a/src/third_party/libvpx/test/i420_video_source.h b/src/third_party/libvpx/test/i420_video_source.h new file mode 100644 index 0000000..0a18480 --- /dev/null +++ b/src/third_party/libvpx/test/i420_video_source.h
@@ -0,0 +1,36 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#ifndef TEST_I420_VIDEO_SOURCE_H_ +#define TEST_I420_VIDEO_SOURCE_H_ +#include <cstdio> +#include <cstdlib> +#include <string> + +#include "test/yuv_video_source.h" + +namespace libvpx_test { + +// This class extends VideoSource to allow parsing of raw yv12 +// so that we can do actual file encodes. +class I420VideoSource : public YUVVideoSource { + public: + I420VideoSource(const std::string &file_name, + unsigned int width, unsigned int height, + int rate_numerator, int rate_denominator, + unsigned int start, int limit) + : YUVVideoSource(file_name, VPX_IMG_FMT_I420, + width, height, + rate_numerator, rate_denominator, + start, limit) {} +}; + +} // namespace libvpx_test + +#endif // TEST_I420_VIDEO_SOURCE_H_
diff --git a/src/third_party/libvpx/test/idct8x8_test.cc b/src/third_party/libvpx/test/idct8x8_test.cc new file mode 100644 index 0000000..7f9d751 --- /dev/null +++ b/src/third_party/libvpx/test/idct8x8_test.cc
@@ -0,0 +1,101 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <math.h> +#include <stdlib.h> +#include <string.h> + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "./vpx_dsp_rtcd.h" +#include "test/acm_random.h" +#include "vpx/vpx_integer.h" + +using libvpx_test::ACMRandom; + +namespace { + +#ifdef _MSC_VER +static int round(double x) { + if (x < 0) + return static_cast<int>(ceil(x - 0.5)); + else + return static_cast<int>(floor(x + 0.5)); +} +#endif + +void reference_dct_1d(double input[8], double output[8]) { + const double kPi = 3.141592653589793238462643383279502884; + const double kInvSqrt2 = 0.707106781186547524400844362104; + for (int k = 0; k < 8; k++) { + output[k] = 0.0; + for (int n = 0; n < 8; n++) + output[k] += input[n]*cos(kPi*(2*n+1)*k/16.0); + if (k == 0) + output[k] = output[k]*kInvSqrt2; + } +} + +void reference_dct_2d(int16_t input[64], double output[64]) { + // First transform columns + for (int i = 0; i < 8; ++i) { + double temp_in[8], temp_out[8]; + for (int j = 0; j < 8; ++j) + temp_in[j] = input[j*8 + i]; + reference_dct_1d(temp_in, temp_out); + for (int j = 0; j < 8; ++j) + output[j*8 + i] = temp_out[j]; + } + // Then transform rows + for (int i = 0; i < 8; ++i) { + double temp_in[8], temp_out[8]; + for (int j = 0; j < 8; ++j) + temp_in[j] = output[j + i*8]; + reference_dct_1d(temp_in, temp_out); + for (int j = 0; j < 8; ++j) + output[j + i*8] = temp_out[j]; + } + // Scale by some magic number + for (int i = 0; i < 64; ++i) + output[i] *= 2; +} + +TEST(VP9Idct8x8Test, AccuracyCheck) { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + const int count_test_block = 10000; + for (int i = 0; i < count_test_block; ++i) { + int16_t input[64]; + tran_low_t coeff[64]; + double output_r[64]; + uint8_t dst[64], src[64]; + + for (int j = 0; j < 64; ++j) { + src[j] = rnd.Rand8(); + dst[j] = rnd.Rand8(); + } + // Initialize a test block with input range [-255, 255]. + for (int j = 0; j < 64; ++j) + input[j] = src[j] - dst[j]; + + reference_dct_2d(input, output_r); + for (int j = 0; j < 64; ++j) + coeff[j] = round(output_r[j]); + vpx_idct8x8_64_add_c(coeff, dst, 8); + for (int j = 0; j < 64; ++j) { + const int diff = dst[j] - src[j]; + const int error = diff * diff; + EXPECT_GE(1, error) + << "Error: 8x8 FDCT/IDCT has error " << error + << " at index " << j; + } + } +} + +} // namespace
diff --git a/src/third_party/libvpx/test/idct_test.cc b/src/third_party/libvpx/test/idct_test.cc new file mode 100644 index 0000000..39db3e4 --- /dev/null +++ b/src/third_party/libvpx/test/idct_test.cc
@@ -0,0 +1,121 @@ +/* + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "./vpx_config.h" +#include "./vp8_rtcd.h" + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "test/clear_system_state.h" +#include "test/register_state_check.h" +#include "vpx/vpx_integer.h" + +typedef void (*IdctFunc)(int16_t *input, unsigned char *pred_ptr, + int pred_stride, unsigned char *dst_ptr, + int dst_stride); +namespace { +class IDCTTest : public ::testing::TestWithParam<IdctFunc> { + protected: + virtual void SetUp() { + int i; + + UUT = GetParam(); + memset(input, 0, sizeof(input)); + /* Set up guard blocks */ + for (i = 0; i < 256; i++) output[i] = ((i & 0xF) < 4 && (i < 64)) ? 0 : -1; + } + + virtual void TearDown() { libvpx_test::ClearSystemState(); } + + IdctFunc UUT; + int16_t input[16]; + unsigned char output[256]; + unsigned char predict[256]; +}; + +TEST_P(IDCTTest, TestGuardBlocks) { + int i; + + for (i = 0; i < 256; i++) + if ((i & 0xF) < 4 && i < 64) + EXPECT_EQ(0, output[i]) << i; + else + EXPECT_EQ(255, output[i]); +} + +TEST_P(IDCTTest, TestAllZeros) { + int i; + + ASM_REGISTER_STATE_CHECK(UUT(input, output, 16, output, 16)); + + for (i = 0; i < 256; i++) + if ((i & 0xF) < 4 && i < 64) + EXPECT_EQ(0, output[i]) << "i==" << i; + else + EXPECT_EQ(255, output[i]) << "i==" << i; +} + +TEST_P(IDCTTest, TestAllOnes) { + int i; + + input[0] = 4; + ASM_REGISTER_STATE_CHECK(UUT(input, output, 16, output, 16)); + + for (i = 0; i < 256; i++) + if ((i & 0xF) < 4 && i < 64) + EXPECT_EQ(1, output[i]) << "i==" << i; + else + EXPECT_EQ(255, output[i]) << "i==" << i; +} + +TEST_P(IDCTTest, TestAddOne) { + int i; + + for (i = 0; i < 256; i++) predict[i] = i; + input[0] = 4; + ASM_REGISTER_STATE_CHECK(UUT(input, predict, 16, output, 16)); + + for (i = 0; i < 256; i++) + if ((i & 0xF) < 4 && i < 64) + EXPECT_EQ(i + 1, output[i]) << "i==" << i; + else + EXPECT_EQ(255, output[i]) << "i==" << i; +} + +TEST_P(IDCTTest, TestWithData) { + int i; + + for (i = 0; i < 16; i++) input[i] = i; + + ASM_REGISTER_STATE_CHECK(UUT(input, output, 16, output, 16)); + + for (i = 0; i < 256; i++) + if ((i & 0xF) > 3 || i > 63) + EXPECT_EQ(255, output[i]) << "i==" << i; + else if (i == 0) + EXPECT_EQ(11, output[i]) << "i==" << i; + else if (i == 34) + EXPECT_EQ(1, output[i]) << "i==" << i; + else if (i == 2 || i == 17 || i == 32) + EXPECT_EQ(3, output[i]) << "i==" << i; + else + EXPECT_EQ(0, output[i]) << "i==" << i; +} + +INSTANTIATE_TEST_CASE_P(C, IDCTTest, ::testing::Values(vp8_short_idct4x4llm_c)); +#if HAVE_MMX +INSTANTIATE_TEST_CASE_P(MMX, IDCTTest, + ::testing::Values(vp8_short_idct4x4llm_mmx)); +#endif +#if HAVE_MSA +INSTANTIATE_TEST_CASE_P(MSA, IDCTTest, + ::testing::Values(vp8_short_idct4x4llm_msa)); +#endif +}
diff --git a/src/third_party/libvpx/test/invalid_file_test.cc b/src/third_party/libvpx/test/invalid_file_test.cc new file mode 100644 index 0000000..f4241eb --- /dev/null +++ b/src/third_party/libvpx/test/invalid_file_test.cc
@@ -0,0 +1,182 @@ +/* + * Copyright (c) 2014 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <cstdio> +#include <cstdlib> +#include <string> +#include <vector> +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "./vpx_config.h" +#include "test/codec_factory.h" +#include "test/decode_test_driver.h" +#include "test/ivf_video_source.h" +#include "test/util.h" +#if CONFIG_WEBM_IO +#include "test/webm_video_source.h" +#endif +#include "vpx_mem/vpx_mem.h" + +namespace { + +struct DecodeParam { + int threads; + const char *filename; +}; + +std::ostream &operator<<(std::ostream &os, const DecodeParam &dp) { + return os << "threads: " << dp.threads << " file: " << dp.filename; +} + +class InvalidFileTest + : public ::libvpx_test::DecoderTest, + public ::libvpx_test::CodecTestWithParam<DecodeParam> { + protected: + InvalidFileTest() : DecoderTest(GET_PARAM(0)), res_file_(NULL) {} + + virtual ~InvalidFileTest() { + if (res_file_ != NULL) + fclose(res_file_); + } + + void OpenResFile(const std::string &res_file_name_) { + res_file_ = libvpx_test::OpenTestDataFile(res_file_name_); + ASSERT_TRUE(res_file_ != NULL) << "Result file open failed. Filename: " + << res_file_name_; + } + + virtual bool HandleDecodeResult( + const vpx_codec_err_t res_dec, + const libvpx_test::CompressedVideoSource &video, + libvpx_test::Decoder *decoder) { + EXPECT_TRUE(res_file_ != NULL); + int expected_res_dec; + + // Read integer result. + const int res = fscanf(res_file_, "%d", &expected_res_dec); + EXPECT_NE(res, EOF) << "Read result data failed"; + + // Check results match. + const DecodeParam input = GET_PARAM(1); + if (input.threads > 1) { + // The serial decode check is too strict for tile-threaded decoding as + // there is no guarantee on the decode order nor which specific error + // will take precedence. Currently a tile-level error is not forwarded so + // the frame will simply be marked corrupt. + EXPECT_TRUE(res_dec == expected_res_dec || + res_dec == VPX_CODEC_CORRUPT_FRAME) + << "Results don't match: frame number = " << video.frame_number() + << ". (" << decoder->DecodeError() << "). Expected: " + << expected_res_dec << " or " << VPX_CODEC_CORRUPT_FRAME; + } else { + EXPECT_EQ(expected_res_dec, res_dec) + << "Results don't match: frame number = " << video.frame_number() + << ". (" << decoder->DecodeError() << ")"; + } + + return !HasFailure(); + } + + void RunTest() { + const DecodeParam input = GET_PARAM(1); + libvpx_test::CompressedVideoSource *video = NULL; + vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t(); + cfg.threads = input.threads; + const std::string filename = input.filename; + + // Open compressed video file. + if (filename.substr(filename.length() - 3, 3) == "ivf") { + video = new libvpx_test::IVFVideoSource(filename); + } else if (filename.substr(filename.length() - 4, 4) == "webm") { +#if CONFIG_WEBM_IO + video = new libvpx_test::WebMVideoSource(filename); +#else + fprintf(stderr, "WebM IO is disabled, skipping test vector %s\n", + filename.c_str()); + return; +#endif + } + video->Init(); + + // Construct result file name. The file holds a list of expected integer + // results, one for each decoded frame. Any result that doesn't match + // the files list will cause a test failure. + const std::string res_filename = filename + ".res"; + OpenResFile(res_filename); + + // Decode frame, and check the md5 matching. + ASSERT_NO_FATAL_FAILURE(RunLoop(video, cfg)); + delete video; + } + + private: + FILE *res_file_; +}; + +TEST_P(InvalidFileTest, ReturnCode) { + RunTest(); +} + +const DecodeParam kVP9InvalidFileTests[] = { + {1, "invalid-vp90-02-v2.webm"}, +#if CONFIG_VP9_HIGHBITDEPTH + {1, "invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf"}, +#endif + {1, "invalid-vp90-03-v3.webm"}, + {1, "invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf"}, + {1, "invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf"}, + {1, "invalid-vp90-2-12-droppable_1.ivf.s3676_r01-05_b6-.ivf"}, + {1, "invalid-vp90-2-05-resize.ivf.s59293_r01-05_b6-.ivf"}, + {1, "invalid-vp90-2-09-subpixel-00.ivf.s20492_r01-05_b6-.v2.ivf"}, + {1, "invalid-vp91-2-mixedrefcsp-444to420.ivf"}, + {1, "invalid-vp90-2-12-droppable_1.ivf.s73804_r01-05_b6-.ivf"}, + {1, "invalid-vp90-2-03-size-224x196.webm.ivf.s44156_r01-05_b6-.ivf"}, + {1, "invalid-vp90-2-03-size-202x210.webm.ivf.s113306_r01-05_b6-.ivf"}, +}; + +VP9_INSTANTIATE_TEST_CASE(InvalidFileTest, + ::testing::ValuesIn(kVP9InvalidFileTests)); + +// This class will include test vectors that are expected to fail +// peek. However they are still expected to have no fatal failures. +class InvalidFileInvalidPeekTest : public InvalidFileTest { + protected: + InvalidFileInvalidPeekTest() : InvalidFileTest() {} + virtual void HandlePeekResult(libvpx_test::Decoder *const /*decoder*/, + libvpx_test::CompressedVideoSource* /*video*/, + const vpx_codec_err_t /*res_peek*/) {} +}; + +TEST_P(InvalidFileInvalidPeekTest, ReturnCode) { + RunTest(); +} + +const DecodeParam kVP9InvalidFileInvalidPeekTests[] = { + {1, "invalid-vp90-01-v3.webm"}, +}; + +VP9_INSTANTIATE_TEST_CASE(InvalidFileInvalidPeekTest, + ::testing::ValuesIn(kVP9InvalidFileInvalidPeekTests)); + +const DecodeParam kMultiThreadedVP9InvalidFileTests[] = { + {4, "invalid-vp90-2-08-tile_1x4_frame_parallel_all_key.webm"}, + {4, "invalid-" + "vp90-2-08-tile_1x2_frame_parallel.webm.ivf.s47039_r01-05_b6-.ivf"}, + {4, "invalid-vp90-2-08-tile_1x8_frame_parallel.webm.ivf.s288_r01-05_b6-.ivf"}, + {2, "invalid-vp90-2-09-aq2.webm.ivf.s3984_r01-05_b6-.v2.ivf"}, + {4, "invalid-vp90-2-09-subpixel-00.ivf.s19552_r01-05_b6-.v2.ivf"}, +}; + +INSTANTIATE_TEST_CASE_P( + VP9MultiThreaded, InvalidFileTest, + ::testing::Combine( + ::testing::Values( + static_cast<const libvpx_test::CodecFactory*>(&libvpx_test::kVP9)), + ::testing::ValuesIn(kMultiThreadedVP9InvalidFileTests))); +} // namespace
diff --git a/src/third_party/libvpx/test/ivf_video_source.h b/src/third_party/libvpx/test/ivf_video_source.h new file mode 100644 index 0000000..824a39d --- /dev/null +++ b/src/third_party/libvpx/test/ivf_video_source.h
@@ -0,0 +1,111 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#ifndef TEST_IVF_VIDEO_SOURCE_H_ +#define TEST_IVF_VIDEO_SOURCE_H_ +#include <cstdio> +#include <cstdlib> +#include <new> +#include <string> +#include "test/video_source.h" + +namespace libvpx_test { +const unsigned int kCodeBufferSize = 256 * 1024; +const unsigned int kIvfFileHdrSize = 32; +const unsigned int kIvfFrameHdrSize = 12; + +static unsigned int MemGetLe32(const uint8_t *mem) { + return (mem[3] << 24) | (mem[2] << 16) | (mem[1] << 8) | (mem[0]); +} + +// This class extends VideoSource to allow parsing of ivf files, +// so that we can do actual file decodes. +class IVFVideoSource : public CompressedVideoSource { + public: + explicit IVFVideoSource(const std::string &file_name) + : file_name_(file_name), + input_file_(NULL), + compressed_frame_buf_(NULL), + frame_sz_(0), + frame_(0), + end_of_file_(false) { + } + + virtual ~IVFVideoSource() { + delete[] compressed_frame_buf_; + + if (input_file_) + fclose(input_file_); + } + + virtual void Init() { + // Allocate a buffer for read in the compressed video frame. + compressed_frame_buf_ = new uint8_t[libvpx_test::kCodeBufferSize]; + ASSERT_TRUE(compressed_frame_buf_ != NULL) + << "Allocate frame buffer failed"; + } + + virtual void Begin() { + input_file_ = OpenTestDataFile(file_name_); + ASSERT_TRUE(input_file_ != NULL) << "Input file open failed. Filename: " + << file_name_; + + // Read file header + uint8_t file_hdr[kIvfFileHdrSize]; + ASSERT_EQ(kIvfFileHdrSize, fread(file_hdr, 1, kIvfFileHdrSize, input_file_)) + << "File header read failed."; + // Check file header + ASSERT_TRUE(file_hdr[0] == 'D' && file_hdr[1] == 'K' && file_hdr[2] == 'I' + && file_hdr[3] == 'F') << "Input is not an IVF file."; + + FillFrame(); + } + + virtual void Next() { + ++frame_; + FillFrame(); + } + + void FillFrame() { + ASSERT_TRUE(input_file_ != NULL); + uint8_t frame_hdr[kIvfFrameHdrSize]; + // Check frame header and read a frame from input_file. + if (fread(frame_hdr, 1, kIvfFrameHdrSize, input_file_) + != kIvfFrameHdrSize) { + end_of_file_ = true; + } else { + end_of_file_ = false; + + frame_sz_ = MemGetLe32(frame_hdr); + ASSERT_LE(frame_sz_, kCodeBufferSize) + << "Frame is too big for allocated code buffer"; + ASSERT_EQ(frame_sz_, + fread(compressed_frame_buf_, 1, frame_sz_, input_file_)) + << "Failed to read complete frame"; + } + } + + virtual const uint8_t *cxdata() const { + return end_of_file_ ? NULL : compressed_frame_buf_; + } + virtual size_t frame_size() const { return frame_sz_; } + virtual unsigned int frame_number() const { return frame_; } + + protected: + std::string file_name_; + FILE *input_file_; + uint8_t *compressed_frame_buf_; + size_t frame_sz_; + unsigned int frame_; + bool end_of_file_; +}; + +} // namespace libvpx_test + +#endif // TEST_IVF_VIDEO_SOURCE_H_
diff --git a/src/third_party/libvpx/test/keyframe_test.cc b/src/third_party/libvpx/test/keyframe_test.cc new file mode 100644 index 0000000..d8b21a1 --- /dev/null +++ b/src/third_party/libvpx/test/keyframe_test.cc
@@ -0,0 +1,145 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include <climits> +#include <vector> +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "test/codec_factory.h" +#include "test/encode_test_driver.h" +#include "test/i420_video_source.h" +#include "test/util.h" + +namespace { + +class KeyframeTest : public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> { + protected: + KeyframeTest() : EncoderTest(GET_PARAM(0)) {} + virtual ~KeyframeTest() {} + + virtual void SetUp() { + InitializeConfig(); + SetMode(GET_PARAM(1)); + kf_count_ = 0; + kf_count_max_ = INT_MAX; + kf_do_force_kf_ = false; + set_cpu_used_ = 0; + } + + virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, + ::libvpx_test::Encoder *encoder) { + if (kf_do_force_kf_) + frame_flags_ = (video->frame() % 3) ? 0 : VPX_EFLAG_FORCE_KF; + if (set_cpu_used_ && video->frame() == 1) + encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_); + } + + virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) { + if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) { + kf_pts_list_.push_back(pkt->data.frame.pts); + kf_count_++; + abort_ |= kf_count_ > kf_count_max_; + } + } + + bool kf_do_force_kf_; + int kf_count_; + int kf_count_max_; + std::vector<vpx_codec_pts_t> kf_pts_list_; + int set_cpu_used_; +}; + +TEST_P(KeyframeTest, TestRandomVideoSource) { + // Validate that encoding the RandomVideoSource produces multiple keyframes. + // This validates the results of the TestDisableKeyframes test. + kf_count_max_ = 2; // early exit successful tests. + + ::libvpx_test::RandomVideoSource video; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + + // In realtime mode - auto placed keyframes are exceedingly rare, don't + // bother with this check if(GetParam() > 0) + if (GET_PARAM(1) > 0) + EXPECT_GT(kf_count_, 1); +} + +TEST_P(KeyframeTest, TestDisableKeyframes) { + cfg_.kf_mode = VPX_KF_DISABLED; + kf_count_max_ = 1; // early exit failed tests. + + ::libvpx_test::RandomVideoSource video; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + + EXPECT_EQ(1, kf_count_); +} + +TEST_P(KeyframeTest, TestForceKeyframe) { + cfg_.kf_mode = VPX_KF_DISABLED; + kf_do_force_kf_ = true; + + ::libvpx_test::DummyVideoSource video; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + + // verify that every third frame is a keyframe. + for (std::vector<vpx_codec_pts_t>::const_iterator iter = kf_pts_list_.begin(); + iter != kf_pts_list_.end(); ++iter) { + ASSERT_EQ(0, *iter % 3) << "Unexpected keyframe at frame " << *iter; + } +} + +TEST_P(KeyframeTest, TestKeyframeMaxDistance) { + cfg_.kf_max_dist = 25; + + ::libvpx_test::DummyVideoSource video; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + + // verify that keyframe interval matches kf_max_dist + for (std::vector<vpx_codec_pts_t>::const_iterator iter = kf_pts_list_.begin(); + iter != kf_pts_list_.end(); ++iter) { + ASSERT_EQ(0, *iter % 25) << "Unexpected keyframe at frame " << *iter; + } +} + +TEST_P(KeyframeTest, TestAutoKeyframe) { + cfg_.kf_mode = VPX_KF_AUTO; + kf_do_force_kf_ = false; + + // Force a deterministic speed step in Real Time mode, as the faster modes + // may not produce a keyframe like we expect. This is necessary when running + // on very slow environments (like Valgrind). The step -11 was determined + // experimentally as the fastest mode that still throws the keyframe. + if (deadline_ == VPX_DL_REALTIME) + set_cpu_used_ = -11; + + // This clip has a cut scene every 30 frames -> Frame 0, 30, 60, 90, 120. + // I check only the first 40 frames to make sure there's a keyframe at frame + // 0 and 30. + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 40); + + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + + // In realtime mode - auto placed keyframes are exceedingly rare, don't + // bother with this check + if (GET_PARAM(1) > 0) + EXPECT_EQ(2u, kf_pts_list_.size()) << " Not the right number of keyframes "; + + // Verify that keyframes match the file keyframes in the file. + for (std::vector<vpx_codec_pts_t>::const_iterator iter = kf_pts_list_.begin(); + iter != kf_pts_list_.end(); ++iter) { + if (deadline_ == VPX_DL_REALTIME && *iter > 0) + EXPECT_EQ(0, (*iter - 1) % 30) << "Unexpected keyframe at frame " + << *iter; + else + EXPECT_EQ(0, *iter % 30) << "Unexpected keyframe at frame " << *iter; + } +} + +VP8_INSTANTIATE_TEST_CASE(KeyframeTest, ALL_TEST_MODES); +} // namespace
diff --git a/src/third_party/libvpx/test/level_test.cc b/src/third_party/libvpx/test/level_test.cc new file mode 100644 index 0000000..62d0247 --- /dev/null +++ b/src/third_party/libvpx/test/level_test.cc
@@ -0,0 +1,119 @@ +/* + * Copyright (c) 2016 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "test/codec_factory.h" +#include "test/encode_test_driver.h" +#include "test/i420_video_source.h" +#include "test/util.h" + +namespace { +class LevelTest + : public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> { + protected: + LevelTest() + : EncoderTest(GET_PARAM(0)), + encoding_mode_(GET_PARAM(1)), + cpu_used_(GET_PARAM(2)), + min_gf_internal_(24), + target_level_(0), + level_(0) {} + virtual ~LevelTest() {} + + virtual void SetUp() { + InitializeConfig(); + SetMode(encoding_mode_); + if (encoding_mode_ != ::libvpx_test::kRealTime) { + cfg_.g_lag_in_frames = 25; + cfg_.rc_end_usage = VPX_VBR; + } else { + cfg_.g_lag_in_frames = 0; + cfg_.rc_end_usage = VPX_CBR; + } + cfg_.rc_2pass_vbr_minsection_pct = 5; + cfg_.rc_2pass_vbr_maxsection_pct = 2000; + cfg_.rc_target_bitrate = 400; + cfg_.rc_max_quantizer = 63; + cfg_.rc_min_quantizer = 0; + } + + virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, + ::libvpx_test::Encoder *encoder) { + if (video->frame() == 0) { + encoder->Control(VP8E_SET_CPUUSED, cpu_used_); + encoder->Control(VP9E_SET_TARGET_LEVEL, target_level_); + encoder->Control(VP9E_SET_MIN_GF_INTERVAL, min_gf_internal_); + if (encoding_mode_ != ::libvpx_test::kRealTime) { + encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1); + encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7); + encoder->Control(VP8E_SET_ARNR_STRENGTH, 5); + encoder->Control(VP8E_SET_ARNR_TYPE, 3); + } + } + encoder->Control(VP9E_GET_LEVEL, &level_); + ASSERT_LE(level_, 51); + ASSERT_GE(level_, 0); + } + + ::libvpx_test::TestMode encoding_mode_; + int cpu_used_; + int min_gf_internal_; + int target_level_; + int level_; +}; + +// Test for keeping level stats only +TEST_P(LevelTest, TestTargetLevel0) { + ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0, + 40); + target_level_ = 0; + min_gf_internal_ = 4; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_EQ(11, level_); + + cfg_.rc_target_bitrate = 1600; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_EQ(20, level_); +} + +// Test for level control being turned off +TEST_P(LevelTest, TestTargetLevel255) { + ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0, + 30); + target_level_ = 255; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); +} + +TEST_P(LevelTest, TestTargetLevelApi) { + ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0, 1); + static const vpx_codec_iface_t *codec = &vpx_codec_vp9_cx_algo; + vpx_codec_ctx_t enc; + vpx_codec_enc_cfg_t cfg; + EXPECT_EQ(VPX_CODEC_OK, vpx_codec_enc_config_default(codec, &cfg, 0)); + EXPECT_EQ(VPX_CODEC_OK, vpx_codec_enc_init(&enc, codec, &cfg, 0)); + for (int level = 0; level <= 256; ++level) { + if (level == 10 || level == 11 || level == 20 || level == 21 || + level == 30 || level == 31 || level == 40 || level == 41 || + level == 50 || level == 51 || level == 52 || level == 60 || + level == 61 || level == 62 || level == 0 || level == 255) + EXPECT_EQ(VPX_CODEC_OK, + vpx_codec_control(&enc, VP9E_SET_TARGET_LEVEL, level)); + else + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, + vpx_codec_control(&enc, VP9E_SET_TARGET_LEVEL, level)); + } + EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&enc)); +} + +VP9_INSTANTIATE_TEST_CASE(LevelTest, + ::testing::Values(::libvpx_test::kTwoPassGood, + ::libvpx_test::kOnePassGood), + ::testing::Range(0, 9)); +} // namespace
diff --git a/src/third_party/libvpx/test/lpf_8_test.cc b/src/third_party/libvpx/test/lpf_8_test.cc new file mode 100644 index 0000000..94646e4 --- /dev/null +++ b/src/third_party/libvpx/test/lpf_8_test.cc
@@ -0,0 +1,672 @@ +/* + * Copyright (c) 2014 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <cmath> +#include <cstdlib> +#include <string> + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "./vpx_config.h" +#include "./vpx_dsp_rtcd.h" +#include "test/acm_random.h" +#include "test/clear_system_state.h" +#include "test/register_state_check.h" +#include "test/util.h" +#include "vp9/common/vp9_entropy.h" +#include "vp9/common/vp9_loopfilter.h" +#include "vpx/vpx_integer.h" + +using libvpx_test::ACMRandom; + +namespace { +// Horizontally and Vertically need 32x32: 8 Coeffs preceeding filtered section +// 16 Coefs within filtered section +// 8 Coeffs following filtered section +const int kNumCoeffs = 1024; + +const int number_of_iterations = 10000; + +#if CONFIG_VP9_HIGHBITDEPTH +typedef void (*loop_op_t)(uint16_t *s, int p, const uint8_t *blimit, + const uint8_t *limit, const uint8_t *thresh, + int bd); +typedef void (*dual_loop_op_t)(uint16_t *s, int p, const uint8_t *blimit0, + const uint8_t *limit0, const uint8_t *thresh0, + const uint8_t *blimit1, const uint8_t *limit1, + const uint8_t *thresh1, int bd); +#else +typedef void (*loop_op_t)(uint8_t *s, int p, const uint8_t *blimit, + const uint8_t *limit, const uint8_t *thresh); +typedef void (*dual_loop_op_t)(uint8_t *s, int p, const uint8_t *blimit0, + const uint8_t *limit0, const uint8_t *thresh0, + const uint8_t *blimit1, const uint8_t *limit1, + const uint8_t *thresh1); +#endif // CONFIG_VP9_HIGHBITDEPTH + +typedef std::tr1::tuple<loop_op_t, loop_op_t, int> loop8_param_t; +typedef std::tr1::tuple<dual_loop_op_t, dual_loop_op_t, int> dualloop8_param_t; + +class Loop8Test6Param : public ::testing::TestWithParam<loop8_param_t> { + public: + virtual ~Loop8Test6Param() {} + virtual void SetUp() { + loopfilter_op_ = GET_PARAM(0); + ref_loopfilter_op_ = GET_PARAM(1); + bit_depth_ = GET_PARAM(2); + mask_ = (1 << bit_depth_) - 1; + } + + virtual void TearDown() { libvpx_test::ClearSystemState(); } + + protected: + int bit_depth_; + int mask_; + loop_op_t loopfilter_op_; + loop_op_t ref_loopfilter_op_; +}; + +class Loop8Test9Param : public ::testing::TestWithParam<dualloop8_param_t> { + public: + virtual ~Loop8Test9Param() {} + virtual void SetUp() { + loopfilter_op_ = GET_PARAM(0); + ref_loopfilter_op_ = GET_PARAM(1); + bit_depth_ = GET_PARAM(2); + mask_ = (1 << bit_depth_) - 1; + } + + virtual void TearDown() { libvpx_test::ClearSystemState(); } + + protected: + int bit_depth_; + int mask_; + dual_loop_op_t loopfilter_op_; + dual_loop_op_t ref_loopfilter_op_; +}; + +TEST_P(Loop8Test6Param, OperationCheck) { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + const int count_test_block = number_of_iterations; +#if CONFIG_VP9_HIGHBITDEPTH + int32_t bd = bit_depth_; + DECLARE_ALIGNED(16, uint16_t, s[kNumCoeffs]); + DECLARE_ALIGNED(16, uint16_t, ref_s[kNumCoeffs]); +#else + DECLARE_ALIGNED(8, uint8_t, s[kNumCoeffs]); + DECLARE_ALIGNED(8, uint8_t, ref_s[kNumCoeffs]); +#endif // CONFIG_VP9_HIGHBITDEPTH + int err_count_total = 0; + int first_failure = -1; + for (int i = 0; i < count_test_block; ++i) { + int err_count = 0; + uint8_t tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4)); + DECLARE_ALIGNED(16, const uint8_t, blimit[16]) = { + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp + }; + tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER)); + DECLARE_ALIGNED(16, const uint8_t, limit[16]) = { + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp + }; + tmp = rnd.Rand8(); + DECLARE_ALIGNED(16, const uint8_t, thresh[16]) = { + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp + }; + int32_t p = kNumCoeffs/32; + + uint16_t tmp_s[kNumCoeffs]; + int j = 0; + while (j < kNumCoeffs) { + uint8_t val = rnd.Rand8(); + if (val & 0x80) { // 50% chance to choose a new value. + tmp_s[j] = rnd.Rand16(); + j++; + } else { // 50% chance to repeat previous value in row X times + int k = 0; + while (k++ < ((val & 0x1f) + 1) && j < kNumCoeffs) { + if (j < 1) { + tmp_s[j] = rnd.Rand16(); + } else if (val & 0x20) { // Increment by an value within the limit + tmp_s[j] = (tmp_s[j - 1] + (*limit - 1)); + } else { // Decrement by an value within the limit + tmp_s[j] = (tmp_s[j - 1] - (*limit - 1)); + } + j++; + } + } + } + for (j = 0; j < kNumCoeffs; j++) { + if (i % 2) { + s[j] = tmp_s[j] & mask_; + } else { + s[j] = tmp_s[p * (j % p) + j / p] & mask_; + } + ref_s[j] = s[j]; + } +#if CONFIG_VP9_HIGHBITDEPTH + ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit, limit, thresh, bd); + ASM_REGISTER_STATE_CHECK( + loopfilter_op_(s + 8 + p * 8, p, blimit, limit, thresh, bd)); +#else + ref_loopfilter_op_(ref_s+8+p*8, p, blimit, limit, thresh); + ASM_REGISTER_STATE_CHECK( + loopfilter_op_(s + 8 + p * 8, p, blimit, limit, thresh)); +#endif // CONFIG_VP9_HIGHBITDEPTH + + for (int j = 0; j < kNumCoeffs; ++j) { + err_count += ref_s[j] != s[j]; + } + if (err_count && !err_count_total) { + first_failure = i; + } + err_count_total += err_count; + } + EXPECT_EQ(0, err_count_total) + << "Error: Loop8Test6Param, C output doesn't match SSE2 " + "loopfilter output. " + << "First failed at test case " << first_failure; +} + +TEST_P(Loop8Test6Param, ValueCheck) { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + const int count_test_block = number_of_iterations; +#if CONFIG_VP9_HIGHBITDEPTH + const int32_t bd = bit_depth_; + DECLARE_ALIGNED(16, uint16_t, s[kNumCoeffs]); + DECLARE_ALIGNED(16, uint16_t, ref_s[kNumCoeffs]); +#else + DECLARE_ALIGNED(8, uint8_t, s[kNumCoeffs]); + DECLARE_ALIGNED(8, uint8_t, ref_s[kNumCoeffs]); +#endif // CONFIG_VP9_HIGHBITDEPTH + int err_count_total = 0; + int first_failure = -1; + + // NOTE: The code in vp9_loopfilter.c:update_sharpness computes mblim as a + // function of sharpness_lvl and the loopfilter lvl as: + // block_inside_limit = lvl >> ((sharpness_lvl > 0) + (sharpness_lvl > 4)); + // ... + // memset(lfi->lfthr[lvl].mblim, (2 * (lvl + 2) + block_inside_limit), + // SIMD_WIDTH); + // This means that the largest value for mblim will occur when sharpness_lvl + // is equal to 0, and lvl is equal to its greatest value (MAX_LOOP_FILTER). + // In this case block_inside_limit will be equal to MAX_LOOP_FILTER and + // therefore mblim will be equal to (2 * (lvl + 2) + block_inside_limit) = + // 2 * (MAX_LOOP_FILTER + 2) + MAX_LOOP_FILTER = 3 * MAX_LOOP_FILTER + 4 + + for (int i = 0; i < count_test_block; ++i) { + int err_count = 0; + uint8_t tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4)); + DECLARE_ALIGNED(16, const uint8_t, blimit[16]) = { + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp + }; + tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER)); + DECLARE_ALIGNED(16, const uint8_t, limit[16]) = { + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp + }; + tmp = rnd.Rand8(); + DECLARE_ALIGNED(16, const uint8_t, thresh[16]) = { + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp + }; + int32_t p = kNumCoeffs / 32; + for (int j = 0; j < kNumCoeffs; ++j) { + s[j] = rnd.Rand16() & mask_; + ref_s[j] = s[j]; + } +#if CONFIG_VP9_HIGHBITDEPTH + ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit, limit, thresh, bd); + ASM_REGISTER_STATE_CHECK( + loopfilter_op_(s + 8 + p * 8, p, blimit, limit, thresh, bd)); +#else + ref_loopfilter_op_(ref_s+8+p*8, p, blimit, limit, thresh); + ASM_REGISTER_STATE_CHECK( + loopfilter_op_(s + 8 + p * 8, p, blimit, limit, thresh)); +#endif // CONFIG_VP9_HIGHBITDEPTH + for (int j = 0; j < kNumCoeffs; ++j) { + err_count += ref_s[j] != s[j]; + } + if (err_count && !err_count_total) { + first_failure = i; + } + err_count_total += err_count; + } + EXPECT_EQ(0, err_count_total) + << "Error: Loop8Test6Param, C output doesn't match SSE2 " + "loopfilter output. " + << "First failed at test case " << first_failure; +} + +TEST_P(Loop8Test9Param, OperationCheck) { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + const int count_test_block = number_of_iterations; +#if CONFIG_VP9_HIGHBITDEPTH + const int32_t bd = bit_depth_; + DECLARE_ALIGNED(16, uint16_t, s[kNumCoeffs]); + DECLARE_ALIGNED(16, uint16_t, ref_s[kNumCoeffs]); +#else + DECLARE_ALIGNED(8, uint8_t, s[kNumCoeffs]); + DECLARE_ALIGNED(8, uint8_t, ref_s[kNumCoeffs]); +#endif // CONFIG_VP9_HIGHBITDEPTH + int err_count_total = 0; + int first_failure = -1; + for (int i = 0; i < count_test_block; ++i) { + int err_count = 0; + uint8_t tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4)); + DECLARE_ALIGNED(16, const uint8_t, blimit0[16]) = { + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp + }; + tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER)); + DECLARE_ALIGNED(16, const uint8_t, limit0[16]) = { + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp + }; + tmp = rnd.Rand8(); + DECLARE_ALIGNED(16, const uint8_t, thresh0[16]) = { + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp + }; + tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4)); + DECLARE_ALIGNED(16, const uint8_t, blimit1[16]) = { + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp + }; + tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER)); + DECLARE_ALIGNED(16, const uint8_t, limit1[16]) = { + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp + }; + tmp = rnd.Rand8(); + DECLARE_ALIGNED(16, const uint8_t, thresh1[16]) = { + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp + }; + int32_t p = kNumCoeffs / 32; + uint16_t tmp_s[kNumCoeffs]; + int j = 0; + const uint8_t limit = *limit0 < *limit1 ? *limit0 : *limit1; + while (j < kNumCoeffs) { + uint8_t val = rnd.Rand8(); + if (val & 0x80) { // 50% chance to choose a new value. + tmp_s[j] = rnd.Rand16(); + j++; + } else { // 50% chance to repeat previous value in row X times. + int k = 0; + while (k++ < ((val & 0x1f) + 1) && j < kNumCoeffs) { + if (j < 1) { + tmp_s[j] = rnd.Rand16(); + } else if (val & 0x20) { // Increment by a value within the limit. + tmp_s[j] = (tmp_s[j - 1] + (limit - 1)); + } else { // Decrement by an value within the limit. + tmp_s[j] = (tmp_s[j - 1] - (limit - 1)); + } + j++; + } + } + } + for (j = 0; j < kNumCoeffs; j++) { + if (i % 2) { + s[j] = tmp_s[j] & mask_; + } else { + s[j] = tmp_s[p * (j % p) + j / p] & mask_; + } + ref_s[j] = s[j]; + } +#if CONFIG_VP9_HIGHBITDEPTH + ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit0, limit0, thresh0, + blimit1, limit1, thresh1, bd); + ASM_REGISTER_STATE_CHECK( + loopfilter_op_(s + 8 + p * 8, p, blimit0, limit0, thresh0, + blimit1, limit1, thresh1, bd)); +#else + ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit0, limit0, thresh0, + blimit1, limit1, thresh1); + ASM_REGISTER_STATE_CHECK( + loopfilter_op_(s + 8 + p * 8, p, blimit0, limit0, thresh0, + blimit1, limit1, thresh1)); +#endif // CONFIG_VP9_HIGHBITDEPTH + for (int j = 0; j < kNumCoeffs; ++j) { + err_count += ref_s[j] != s[j]; + } + if (err_count && !err_count_total) { + first_failure = i; + } + err_count_total += err_count; + } + EXPECT_EQ(0, err_count_total) + << "Error: Loop8Test9Param, C output doesn't match SSE2 " + "loopfilter output. " + << "First failed at test case " << first_failure; +} + +TEST_P(Loop8Test9Param, ValueCheck) { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + const int count_test_block = number_of_iterations; +#if CONFIG_VP9_HIGHBITDEPTH + DECLARE_ALIGNED(16, uint16_t, s[kNumCoeffs]); + DECLARE_ALIGNED(16, uint16_t, ref_s[kNumCoeffs]); +#else + DECLARE_ALIGNED(8, uint8_t, s[kNumCoeffs]); + DECLARE_ALIGNED(8, uint8_t, ref_s[kNumCoeffs]); +#endif // CONFIG_VP9_HIGHBITDEPTH + int err_count_total = 0; + int first_failure = -1; + for (int i = 0; i < count_test_block; ++i) { + int err_count = 0; + uint8_t tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4)); + DECLARE_ALIGNED(16, const uint8_t, blimit0[16]) = { + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp + }; + tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER)); + DECLARE_ALIGNED(16, const uint8_t, limit0[16]) = { + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp + }; + tmp = rnd.Rand8(); + DECLARE_ALIGNED(16, const uint8_t, thresh0[16]) = { + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp + }; + tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4)); + DECLARE_ALIGNED(16, const uint8_t, blimit1[16]) = { + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp + }; + tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER)); + DECLARE_ALIGNED(16, const uint8_t, limit1[16]) = { + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp + }; + tmp = rnd.Rand8(); + DECLARE_ALIGNED(16, const uint8_t, thresh1[16]) = { + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, + tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp + }; + int32_t p = kNumCoeffs / 32; // TODO(pdlf) can we have non-square here? + for (int j = 0; j < kNumCoeffs; ++j) { + s[j] = rnd.Rand16() & mask_; + ref_s[j] = s[j]; + } +#if CONFIG_VP9_HIGHBITDEPTH + const int32_t bd = bit_depth_; + ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit0, limit0, thresh0, + blimit1, limit1, thresh1, bd); + ASM_REGISTER_STATE_CHECK( + loopfilter_op_(s + 8 + p * 8, p, blimit0, limit0, + thresh0, blimit1, limit1, thresh1, bd)); +#else + ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit0, limit0, thresh0, + blimit1, limit1, thresh1); + ASM_REGISTER_STATE_CHECK( + loopfilter_op_(s + 8 + p * 8, p, blimit0, limit0, thresh0, + blimit1, limit1, thresh1)); +#endif // CONFIG_VP9_HIGHBITDEPTH + for (int j = 0; j < kNumCoeffs; ++j) { + err_count += ref_s[j] != s[j]; + } + if (err_count && !err_count_total) { + first_failure = i; + } + err_count_total += err_count; + } + EXPECT_EQ(0, err_count_total) + << "Error: Loop8Test9Param, C output doesn't match SSE2" + "loopfilter output. " + << "First failed at test case " << first_failure; +} + +using std::tr1::make_tuple; + +#if HAVE_SSE2 +#if CONFIG_VP9_HIGHBITDEPTH +INSTANTIATE_TEST_CASE_P( + SSE2, Loop8Test6Param, + ::testing::Values( + make_tuple(&vpx_highbd_lpf_horizontal_4_sse2, + &vpx_highbd_lpf_horizontal_4_c, 8), + make_tuple(&vpx_highbd_lpf_vertical_4_sse2, + &vpx_highbd_lpf_vertical_4_c, 8), + make_tuple(&vpx_highbd_lpf_horizontal_8_sse2, + &vpx_highbd_lpf_horizontal_8_c, 8), + make_tuple(&vpx_highbd_lpf_horizontal_edge_8_sse2, + &vpx_highbd_lpf_horizontal_edge_8_c, 8), + make_tuple(&vpx_highbd_lpf_horizontal_edge_16_sse2, + &vpx_highbd_lpf_horizontal_edge_16_c, 8), + make_tuple(&vpx_highbd_lpf_vertical_8_sse2, + &vpx_highbd_lpf_vertical_8_c, 8), + make_tuple(&vpx_highbd_lpf_vertical_16_sse2, + &vpx_highbd_lpf_vertical_16_c, 8), + make_tuple(&vpx_highbd_lpf_horizontal_4_sse2, + &vpx_highbd_lpf_horizontal_4_c, 10), + make_tuple(&vpx_highbd_lpf_vertical_4_sse2, + &vpx_highbd_lpf_vertical_4_c, 10), + make_tuple(&vpx_highbd_lpf_horizontal_8_sse2, + &vpx_highbd_lpf_horizontal_8_c, 10), + make_tuple(&vpx_highbd_lpf_horizontal_edge_8_sse2, + &vpx_highbd_lpf_horizontal_edge_8_c, 10), + make_tuple(&vpx_highbd_lpf_horizontal_edge_16_sse2, + &vpx_highbd_lpf_horizontal_edge_16_c, 10), + make_tuple(&vpx_highbd_lpf_vertical_8_sse2, + &vpx_highbd_lpf_vertical_8_c, 10), + make_tuple(&vpx_highbd_lpf_vertical_16_sse2, + &vpx_highbd_lpf_vertical_16_c, 10), + make_tuple(&vpx_highbd_lpf_horizontal_4_sse2, + &vpx_highbd_lpf_horizontal_4_c, 12), + make_tuple(&vpx_highbd_lpf_vertical_4_sse2, + &vpx_highbd_lpf_vertical_4_c, 12), + make_tuple(&vpx_highbd_lpf_horizontal_8_sse2, + &vpx_highbd_lpf_horizontal_8_c, 12), + make_tuple(&vpx_highbd_lpf_horizontal_edge_8_sse2, + &vpx_highbd_lpf_horizontal_edge_8_c, 12), + make_tuple(&vpx_highbd_lpf_horizontal_edge_16_sse2, + &vpx_highbd_lpf_horizontal_edge_16_c, 12), + make_tuple(&vpx_highbd_lpf_vertical_8_sse2, + &vpx_highbd_lpf_vertical_8_c, 12), + make_tuple(&vpx_highbd_lpf_vertical_16_sse2, + &vpx_highbd_lpf_vertical_16_c, 12), + make_tuple(&vpx_highbd_lpf_vertical_16_dual_sse2, + &vpx_highbd_lpf_vertical_16_dual_c, 8), + make_tuple(&vpx_highbd_lpf_vertical_16_dual_sse2, + &vpx_highbd_lpf_vertical_16_dual_c, 10), + make_tuple(&vpx_highbd_lpf_vertical_16_dual_sse2, + &vpx_highbd_lpf_vertical_16_dual_c, 12))); +#else +INSTANTIATE_TEST_CASE_P( + SSE2, Loop8Test6Param, + ::testing::Values( + make_tuple(&vpx_lpf_horizontal_4_sse2, + &vpx_lpf_horizontal_4_c, 8), + make_tuple(&vpx_lpf_horizontal_8_sse2, + &vpx_lpf_horizontal_8_c, 8), + make_tuple(&vpx_lpf_horizontal_edge_8_sse2, + &vpx_lpf_horizontal_edge_8_c, 8), + make_tuple(&vpx_lpf_horizontal_edge_16_sse2, + &vpx_lpf_horizontal_edge_16_c, 8), + make_tuple(&vpx_lpf_vertical_4_sse2, + &vpx_lpf_vertical_4_c, 8), + make_tuple(&vpx_lpf_vertical_8_sse2, + &vpx_lpf_vertical_8_c, 8), + make_tuple(&vpx_lpf_vertical_16_sse2, + &vpx_lpf_vertical_16_c, 8), + make_tuple(&vpx_lpf_vertical_16_dual_sse2, + &vpx_lpf_vertical_16_dual_c, 8))); +#endif // CONFIG_VP9_HIGHBITDEPTH +#endif + +#if HAVE_AVX2 && (!CONFIG_VP9_HIGHBITDEPTH) +INSTANTIATE_TEST_CASE_P( + AVX2, Loop8Test6Param, + ::testing::Values( + make_tuple(&vpx_lpf_horizontal_edge_8_avx2, + &vpx_lpf_horizontal_edge_8_c, 8), + make_tuple(&vpx_lpf_horizontal_edge_16_avx2, + &vpx_lpf_horizontal_edge_16_c, 8))); +#endif + +#if HAVE_SSE2 +#if CONFIG_VP9_HIGHBITDEPTH +INSTANTIATE_TEST_CASE_P( + SSE2, Loop8Test9Param, + ::testing::Values( + make_tuple(&vpx_highbd_lpf_horizontal_4_dual_sse2, + &vpx_highbd_lpf_horizontal_4_dual_c, 8), + make_tuple(&vpx_highbd_lpf_horizontal_8_dual_sse2, + &vpx_highbd_lpf_horizontal_8_dual_c, 8), + make_tuple(&vpx_highbd_lpf_vertical_4_dual_sse2, + &vpx_highbd_lpf_vertical_4_dual_c, 8), + make_tuple(&vpx_highbd_lpf_vertical_8_dual_sse2, + &vpx_highbd_lpf_vertical_8_dual_c, 8), + make_tuple(&vpx_highbd_lpf_horizontal_4_dual_sse2, + &vpx_highbd_lpf_horizontal_4_dual_c, 10), + make_tuple(&vpx_highbd_lpf_horizontal_8_dual_sse2, + &vpx_highbd_lpf_horizontal_8_dual_c, 10), + make_tuple(&vpx_highbd_lpf_vertical_4_dual_sse2, + &vpx_highbd_lpf_vertical_4_dual_c, 10), + make_tuple(&vpx_highbd_lpf_vertical_8_dual_sse2, + &vpx_highbd_lpf_vertical_8_dual_c, 10), + make_tuple(&vpx_highbd_lpf_horizontal_4_dual_sse2, + &vpx_highbd_lpf_horizontal_4_dual_c, 12), + make_tuple(&vpx_highbd_lpf_horizontal_8_dual_sse2, + &vpx_highbd_lpf_horizontal_8_dual_c, 12), + make_tuple(&vpx_highbd_lpf_vertical_4_dual_sse2, + &vpx_highbd_lpf_vertical_4_dual_c, 12), + make_tuple(&vpx_highbd_lpf_vertical_8_dual_sse2, + &vpx_highbd_lpf_vertical_8_dual_c, 12))); +#else +INSTANTIATE_TEST_CASE_P( + SSE2, Loop8Test9Param, + ::testing::Values( + make_tuple(&vpx_lpf_horizontal_4_dual_sse2, + &vpx_lpf_horizontal_4_dual_c, 8), + make_tuple(&vpx_lpf_horizontal_8_dual_sse2, + &vpx_lpf_horizontal_8_dual_c, 8), + make_tuple(&vpx_lpf_vertical_4_dual_sse2, + &vpx_lpf_vertical_4_dual_c, 8), + make_tuple(&vpx_lpf_vertical_8_dual_sse2, + &vpx_lpf_vertical_8_dual_c, 8))); +#endif // CONFIG_VP9_HIGHBITDEPTH +#endif + +#if HAVE_NEON +#if CONFIG_VP9_HIGHBITDEPTH +// No neon high bitdepth functions. +#else +INSTANTIATE_TEST_CASE_P( + NEON, Loop8Test6Param, + ::testing::Values( +#if HAVE_NEON_ASM +// Using #if inside the macro is unsupported on MSVS but the tests are not +// currently built for MSVS with ARM and NEON. + make_tuple(&vpx_lpf_horizontal_edge_8_neon, + &vpx_lpf_horizontal_edge_8_c, 8), + make_tuple(&vpx_lpf_horizontal_edge_16_neon, + &vpx_lpf_horizontal_edge_16_c, 8), + make_tuple(&vpx_lpf_vertical_16_neon, + &vpx_lpf_vertical_16_c, 8), + make_tuple(&vpx_lpf_vertical_16_dual_neon, + &vpx_lpf_vertical_16_dual_c, 8), +#endif // HAVE_NEON_ASM + make_tuple(&vpx_lpf_horizontal_8_neon, + &vpx_lpf_horizontal_8_c, 8), + make_tuple(&vpx_lpf_vertical_8_neon, + &vpx_lpf_vertical_8_c, 8), + make_tuple(&vpx_lpf_horizontal_4_neon, + &vpx_lpf_horizontal_4_c, 8), + make_tuple(&vpx_lpf_vertical_4_neon, + &vpx_lpf_vertical_4_c, 8))); +INSTANTIATE_TEST_CASE_P( + NEON, Loop8Test9Param, + ::testing::Values( +#if HAVE_NEON_ASM + make_tuple(&vpx_lpf_horizontal_8_dual_neon, + &vpx_lpf_horizontal_8_dual_c, 8), + make_tuple(&vpx_lpf_vertical_8_dual_neon, + &vpx_lpf_vertical_8_dual_c, 8), +#endif // HAVE_NEON_ASM + make_tuple(&vpx_lpf_horizontal_4_dual_neon, + &vpx_lpf_horizontal_4_dual_c, 8), + make_tuple(&vpx_lpf_vertical_4_dual_neon, + &vpx_lpf_vertical_4_dual_c, 8))); +#endif // CONFIG_VP9_HIGHBITDEPTH +#endif // HAVE_NEON + +#if HAVE_DSPR2 && !CONFIG_VP9_HIGHBITDEPTH +INSTANTIATE_TEST_CASE_P( + DSPR2, Loop8Test6Param, + ::testing::Values( + make_tuple(&vpx_lpf_horizontal_4_dspr2, + &vpx_lpf_horizontal_4_c, 8), + make_tuple(&vpx_lpf_horizontal_8_dspr2, + &vpx_lpf_horizontal_8_c, 8), + make_tuple(&vpx_lpf_horizontal_edge_8, + &vpx_lpf_horizontal_edge_8, 8), + make_tuple(&vpx_lpf_horizontal_edge_16, + &vpx_lpf_horizontal_edge_16, 8), + make_tuple(&vpx_lpf_vertical_4_dspr2, + &vpx_lpf_vertical_4_c, 8), + make_tuple(&vpx_lpf_vertical_8_dspr2, + &vpx_lpf_vertical_8_c, 8), + make_tuple(&vpx_lpf_vertical_16_dspr2, + &vpx_lpf_vertical_16_c, 8), + make_tuple(&vpx_lpf_vertical_16_dual_dspr2, + &vpx_lpf_vertical_16_dual_c, 8))); + +INSTANTIATE_TEST_CASE_P( + DSPR2, Loop8Test9Param, + ::testing::Values( + make_tuple(&vpx_lpf_horizontal_4_dual_dspr2, + &vpx_lpf_horizontal_4_dual_c, 8), + make_tuple(&vpx_lpf_horizontal_8_dual_dspr2, + &vpx_lpf_horizontal_8_dual_c, 8), + make_tuple(&vpx_lpf_vertical_4_dual_dspr2, + &vpx_lpf_vertical_4_dual_c, 8), + make_tuple(&vpx_lpf_vertical_8_dual_dspr2, + &vpx_lpf_vertical_8_dual_c, 8))); +#endif // HAVE_DSPR2 && !CONFIG_VP9_HIGHBITDEPTH + +#if HAVE_MSA && (!CONFIG_VP9_HIGHBITDEPTH) +INSTANTIATE_TEST_CASE_P( + MSA, Loop8Test6Param, + ::testing::Values( + make_tuple(&vpx_lpf_horizontal_4_msa, + &vpx_lpf_horizontal_4_c, 8), + make_tuple(&vpx_lpf_horizontal_8_msa, + &vpx_lpf_horizontal_8_c, 8), + make_tuple(&vpx_lpf_horizontal_edge_8_msa, + &vpx_lpf_horizontal_edge_8_c, 8), + make_tuple(&vpx_lpf_horizontal_edge_16_msa, + &vpx_lpf_horizontal_edge_16_c, 8), + make_tuple(&vpx_lpf_vertical_4_msa, + &vpx_lpf_vertical_4_c, 8), + make_tuple(&vpx_lpf_vertical_8_msa, + &vpx_lpf_vertical_8_c, 8), + make_tuple(&vpx_lpf_vertical_16_msa, + &vpx_lpf_vertical_16_c, 8))); + +INSTANTIATE_TEST_CASE_P( + MSA, Loop8Test9Param, + ::testing::Values( + make_tuple(&vpx_lpf_horizontal_4_dual_msa, + &vpx_lpf_horizontal_4_dual_c, 8), + make_tuple(&vpx_lpf_horizontal_8_dual_msa, + &vpx_lpf_horizontal_8_dual_c, 8), + make_tuple(&vpx_lpf_vertical_4_dual_msa, + &vpx_lpf_vertical_4_dual_c, 8), + make_tuple(&vpx_lpf_vertical_8_dual_msa, + &vpx_lpf_vertical_8_dual_c, 8))); +#endif // HAVE_MSA && (!CONFIG_VP9_HIGHBITDEPTH) + +} // namespace
diff --git a/src/third_party/libvpx/test/md5_helper.h b/src/third_party/libvpx/test/md5_helper.h new file mode 100644 index 0000000..742cf0b --- /dev/null +++ b/src/third_party/libvpx/test/md5_helper.h
@@ -0,0 +1,74 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef TEST_MD5_HELPER_H_ +#define TEST_MD5_HELPER_H_ + +#include "./md5_utils.h" +#include "vpx/vpx_decoder.h" + +namespace libvpx_test { +class MD5 { + public: + MD5() { + MD5Init(&md5_); + } + + void Add(const vpx_image_t *img) { + for (int plane = 0; plane < 3; ++plane) { + const uint8_t *buf = img->planes[plane]; + // Calculate the width and height to do the md5 check. For the chroma + // plane, we never want to round down and thus skip a pixel so if + // we are shifting by 1 (chroma_shift) we add 1 before doing the shift. + // This works only for chroma_shift of 0 and 1. + const int bytes_per_sample = + (img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1; + const int h = plane ? (img->d_h + img->y_chroma_shift) >> + img->y_chroma_shift : img->d_h; + const int w = (plane ? (img->d_w + img->x_chroma_shift) >> + img->x_chroma_shift : img->d_w) * bytes_per_sample; + + for (int y = 0; y < h; ++y) { + MD5Update(&md5_, buf, w); + buf += img->stride[plane]; + } + } + } + + void Add(const uint8_t *data, size_t size) { + MD5Update(&md5_, data, static_cast<uint32_t>(size)); + } + + const char *Get(void) { + static const char hex[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', + }; + uint8_t tmp[16]; + MD5Context ctx_tmp = md5_; + + MD5Final(tmp, &ctx_tmp); + for (int i = 0; i < 16; i++) { + res_[i * 2 + 0] = hex[tmp[i] >> 4]; + res_[i * 2 + 1] = hex[tmp[i] & 0xf]; + } + res_[32] = 0; + + return res_; + } + + protected: + char res_[33]; + MD5Context md5_; +}; + +} // namespace libvpx_test + +#endif // TEST_MD5_HELPER_H_
diff --git a/src/third_party/libvpx/test/minmax_test.cc b/src/third_party/libvpx/test/minmax_test.cc new file mode 100644 index 0000000..dbe4342 --- /dev/null +++ b/src/third_party/libvpx/test/minmax_test.cc
@@ -0,0 +1,132 @@ +/* + * Copyright (c) 2016 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <stdlib.h> +#include <string.h> + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "./vpx_dsp_rtcd.h" +#include "vpx/vpx_integer.h" + +#include "test/acm_random.h" +#include "test/register_state_check.h" + +namespace { + +using ::libvpx_test::ACMRandom; + +typedef void (*MinMaxFunc)(const uint8_t *a, int a_stride, + const uint8_t *b, int b_stride, + int *min, int *max); + +class MinMaxTest : public ::testing::TestWithParam<MinMaxFunc> { + public: + virtual void SetUp() { + mm_func_ = GetParam(); + rnd_.Reset(ACMRandom::DeterministicSeed()); + } + + protected: + MinMaxFunc mm_func_; + ACMRandom rnd_; +}; + +void reference_minmax(const uint8_t *a, int a_stride, + const uint8_t *b, int b_stride, + int *min_ret, int *max_ret) { + int min = 255; + int max = 0; + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 8; j++) { + const int diff = abs(a[i * a_stride + j] - b[i * b_stride + j]); + if (min > diff) min = diff; + if (max < diff) max = diff; + } + } + + *min_ret = min; + *max_ret = max; +} + +TEST_P(MinMaxTest, MinValue) { + for (int i = 0; i < 64; i++) { + uint8_t a[64], b[64]; + memset(a, 0, sizeof(a)); + memset(b, 255, sizeof(b)); + b[i] = i; // Set a minimum difference of i. + + int min, max; + ASM_REGISTER_STATE_CHECK(mm_func_(a, 8, b, 8, &min, &max)); + EXPECT_EQ(255, max); + EXPECT_EQ(i, min); + } +} + +TEST_P(MinMaxTest, MaxValue) { + for (int i = 0; i < 64; i++) { + uint8_t a[64], b[64]; + memset(a, 0, sizeof(a)); + memset(b, 0, sizeof(b)); + b[i] = i; // Set a maximum difference of i. + + int min, max; + ASM_REGISTER_STATE_CHECK(mm_func_(a, 8, b, 8, &min, &max)); + EXPECT_EQ(i, max); + EXPECT_EQ(0, min); + } +} + +TEST_P(MinMaxTest, CompareReference) { + uint8_t a[64], b[64]; + for (int j = 0; j < 64; j++) { + a[j] = rnd_.Rand8(); + b[j] = rnd_.Rand8(); + } + + int min_ref, max_ref, min, max; + reference_minmax(a, 8, b, 8, &min_ref, &max_ref); + ASM_REGISTER_STATE_CHECK(mm_func_(a, 8, b, 8, &min, &max)); + EXPECT_EQ(max_ref, max); + EXPECT_EQ(min_ref, min); +} + +TEST_P(MinMaxTest, CompareReferenceAndVaryStride) { + uint8_t a[8 * 64], b[8 * 64]; + for (int i = 0; i < 8 * 64; i++) { + a[i] = rnd_.Rand8(); + b[i] = rnd_.Rand8(); + } + for (int a_stride = 8; a_stride <= 64; a_stride += 8) { + for (int b_stride = 8; b_stride <= 64; b_stride += 8) { + int min_ref, max_ref, min, max; + reference_minmax(a, a_stride, b, b_stride, &min_ref, &max_ref); + ASM_REGISTER_STATE_CHECK(mm_func_(a, a_stride, b, b_stride, &min, &max)); + EXPECT_EQ(max_ref, max) << "when a_stride = " << a_stride + << " and b_stride = " << b_stride;; + EXPECT_EQ(min_ref, min) << "when a_stride = " << a_stride + << " and b_stride = " << b_stride;; + } + } +} + +INSTANTIATE_TEST_CASE_P(C, MinMaxTest, ::testing::Values(&vpx_minmax_8x8_c)); + +#if HAVE_SSE2 +INSTANTIATE_TEST_CASE_P(SSE2, MinMaxTest, + ::testing::Values(&vpx_minmax_8x8_sse2)); +#endif + +#if HAVE_NEON +INSTANTIATE_TEST_CASE_P(NEON, MinMaxTest, + ::testing::Values(&vpx_minmax_8x8_neon)); +#endif + +} // namespace
diff --git a/src/third_party/libvpx/test/partial_idct_test.cc b/src/third_party/libvpx/test/partial_idct_test.cc new file mode 100644 index 0000000..6c82412 --- /dev/null +++ b/src/third_party/libvpx/test/partial_idct_test.cc
@@ -0,0 +1,343 @@ +/* + * Copyright (c) 2013 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <math.h> +#include <stdlib.h> +#include <string.h> + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "./vp9_rtcd.h" +#include "./vpx_dsp_rtcd.h" +#include "test/acm_random.h" +#include "test/clear_system_state.h" +#include "test/register_state_check.h" +#include "test/util.h" +#include "vp9/common/vp9_blockd.h" +#include "vp9/common/vp9_scan.h" +#include "vpx/vpx_integer.h" + +using libvpx_test::ACMRandom; + +namespace { +typedef void (*FwdTxfmFunc)(const int16_t *in, tran_low_t *out, int stride); +typedef void (*InvTxfmFunc)(const tran_low_t *in, uint8_t *out, int stride); +typedef std::tr1::tuple<FwdTxfmFunc, + InvTxfmFunc, + InvTxfmFunc, + TX_SIZE, int> PartialInvTxfmParam; +const int kMaxNumCoeffs = 1024; +class PartialIDctTest : public ::testing::TestWithParam<PartialInvTxfmParam> { + public: + virtual ~PartialIDctTest() {} + virtual void SetUp() { + ftxfm_ = GET_PARAM(0); + full_itxfm_ = GET_PARAM(1); + partial_itxfm_ = GET_PARAM(2); + tx_size_ = GET_PARAM(3); + last_nonzero_ = GET_PARAM(4); + } + + virtual void TearDown() { libvpx_test::ClearSystemState(); } + + protected: + int last_nonzero_; + TX_SIZE tx_size_; + FwdTxfmFunc ftxfm_; + InvTxfmFunc full_itxfm_; + InvTxfmFunc partial_itxfm_; +}; + +TEST_P(PartialIDctTest, RunQuantCheck) { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + int size; + switch (tx_size_) { + case TX_4X4: + size = 4; + break; + case TX_8X8: + size = 8; + break; + case TX_16X16: + size = 16; + break; + case TX_32X32: + size = 32; + break; + default: + FAIL() << "Wrong Size!"; + break; + } + DECLARE_ALIGNED(16, tran_low_t, test_coef_block1[kMaxNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, test_coef_block2[kMaxNumCoeffs]); + DECLARE_ALIGNED(16, uint8_t, dst1[kMaxNumCoeffs]); + DECLARE_ALIGNED(16, uint8_t, dst2[kMaxNumCoeffs]); + + const int count_test_block = 1000; + const int block_size = size * size; + + DECLARE_ALIGNED(16, int16_t, input_extreme_block[kMaxNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kMaxNumCoeffs]); + + int max_error = 0; + for (int i = 0; i < count_test_block; ++i) { + // clear out destination buffer + memset(dst1, 0, sizeof(*dst1) * block_size); + memset(dst2, 0, sizeof(*dst2) * block_size); + memset(test_coef_block1, 0, sizeof(*test_coef_block1) * block_size); + memset(test_coef_block2, 0, sizeof(*test_coef_block2) * block_size); + + ACMRandom rnd(ACMRandom::DeterministicSeed()); + + for (int i = 0; i < count_test_block; ++i) { + // Initialize a test block with input range [-255, 255]. + if (i == 0) { + for (int j = 0; j < block_size; ++j) + input_extreme_block[j] = 255; + } else if (i == 1) { + for (int j = 0; j < block_size; ++j) + input_extreme_block[j] = -255; + } else { + for (int j = 0; j < block_size; ++j) { + input_extreme_block[j] = rnd.Rand8() % 2 ? 255 : -255; + } + } + + ftxfm_(input_extreme_block, output_ref_block, size); + + // quantization with maximum allowed step sizes + test_coef_block1[0] = (output_ref_block[0] / 1336) * 1336; + for (int j = 1; j < last_nonzero_; ++j) + test_coef_block1[vp9_default_scan_orders[tx_size_].scan[j]] + = (output_ref_block[j] / 1828) * 1828; + } + + ASM_REGISTER_STATE_CHECK(full_itxfm_(test_coef_block1, dst1, size)); + ASM_REGISTER_STATE_CHECK(partial_itxfm_(test_coef_block1, dst2, size)); + + for (int j = 0; j < block_size; ++j) { + const int diff = dst1[j] - dst2[j]; + const int error = diff * diff; + if (max_error < error) + max_error = error; + } + } + + EXPECT_EQ(0, max_error) + << "Error: partial inverse transform produces different results"; +} + +TEST_P(PartialIDctTest, ResultsMatch) { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + int size; + switch (tx_size_) { + case TX_4X4: + size = 4; + break; + case TX_8X8: + size = 8; + break; + case TX_16X16: + size = 16; + break; + case TX_32X32: + size = 32; + break; + default: + FAIL() << "Wrong Size!"; + break; + } + DECLARE_ALIGNED(16, tran_low_t, test_coef_block1[kMaxNumCoeffs]); + DECLARE_ALIGNED(16, tran_low_t, test_coef_block2[kMaxNumCoeffs]); + DECLARE_ALIGNED(16, uint8_t, dst1[kMaxNumCoeffs]); + DECLARE_ALIGNED(16, uint8_t, dst2[kMaxNumCoeffs]); + const int count_test_block = 1000; + const int max_coeff = 32766 / 4; + const int block_size = size * size; + int max_error = 0; + for (int i = 0; i < count_test_block; ++i) { + // clear out destination buffer + memset(dst1, 0, sizeof(*dst1) * block_size); + memset(dst2, 0, sizeof(*dst2) * block_size); + memset(test_coef_block1, 0, sizeof(*test_coef_block1) * block_size); + memset(test_coef_block2, 0, sizeof(*test_coef_block2) * block_size); + int max_energy_leftover = max_coeff * max_coeff; + for (int j = 0; j < last_nonzero_; ++j) { + int16_t coef = static_cast<int16_t>(sqrt(1.0 * max_energy_leftover) * + (rnd.Rand16() - 32768) / 65536); + max_energy_leftover -= coef * coef; + if (max_energy_leftover < 0) { + max_energy_leftover = 0; + coef = 0; + } + test_coef_block1[vp9_default_scan_orders[tx_size_].scan[j]] = coef; + } + + memcpy(test_coef_block2, test_coef_block1, + sizeof(*test_coef_block2) * block_size); + + ASM_REGISTER_STATE_CHECK(full_itxfm_(test_coef_block1, dst1, size)); + ASM_REGISTER_STATE_CHECK(partial_itxfm_(test_coef_block2, dst2, size)); + + for (int j = 0; j < block_size; ++j) { + const int diff = dst1[j] - dst2[j]; + const int error = diff * diff; + if (max_error < error) + max_error = error; + } + } + + EXPECT_EQ(0, max_error) + << "Error: partial inverse transform produces different results"; +} +using std::tr1::make_tuple; + +INSTANTIATE_TEST_CASE_P( + C, PartialIDctTest, + ::testing::Values( + make_tuple(&vpx_fdct32x32_c, + &vpx_idct32x32_1024_add_c, + &vpx_idct32x32_34_add_c, + TX_32X32, 34), + make_tuple(&vpx_fdct32x32_c, + &vpx_idct32x32_1024_add_c, + &vpx_idct32x32_1_add_c, + TX_32X32, 1), + make_tuple(&vpx_fdct16x16_c, + &vpx_idct16x16_256_add_c, + &vpx_idct16x16_10_add_c, + TX_16X16, 10), + make_tuple(&vpx_fdct16x16_c, + &vpx_idct16x16_256_add_c, + &vpx_idct16x16_1_add_c, + TX_16X16, 1), + make_tuple(&vpx_fdct8x8_c, + &vpx_idct8x8_64_add_c, + &vpx_idct8x8_12_add_c, + TX_8X8, 12), + make_tuple(&vpx_fdct8x8_c, + &vpx_idct8x8_64_add_c, + &vpx_idct8x8_1_add_c, + TX_8X8, 1), + make_tuple(&vpx_fdct4x4_c, + &vpx_idct4x4_16_add_c, + &vpx_idct4x4_1_add_c, + TX_4X4, 1))); + +#if HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + NEON, PartialIDctTest, + ::testing::Values( + make_tuple(&vpx_fdct32x32_c, + &vpx_idct32x32_1024_add_c, + &vpx_idct32x32_1_add_neon, + TX_32X32, 1), + make_tuple(&vpx_fdct16x16_c, + &vpx_idct16x16_256_add_c, + &vpx_idct16x16_10_add_neon, + TX_16X16, 10), + make_tuple(&vpx_fdct16x16_c, + &vpx_idct16x16_256_add_c, + &vpx_idct16x16_1_add_neon, + TX_16X16, 1), + make_tuple(&vpx_fdct8x8_c, + &vpx_idct8x8_64_add_c, + &vpx_idct8x8_12_add_neon, + TX_8X8, 12), + make_tuple(&vpx_fdct8x8_c, + &vpx_idct8x8_64_add_c, + &vpx_idct8x8_1_add_neon, + TX_8X8, 1), + make_tuple(&vpx_fdct4x4_c, + &vpx_idct4x4_16_add_c, + &vpx_idct4x4_1_add_neon, + TX_4X4, 1))); +#endif // HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE + +#if HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + SSE2, PartialIDctTest, + ::testing::Values( + make_tuple(&vpx_fdct32x32_c, + &vpx_idct32x32_1024_add_c, + &vpx_idct32x32_34_add_sse2, + TX_32X32, 34), + make_tuple(&vpx_fdct32x32_c, + &vpx_idct32x32_1024_add_c, + &vpx_idct32x32_1_add_sse2, + TX_32X32, 1), + make_tuple(&vpx_fdct16x16_c, + &vpx_idct16x16_256_add_c, + &vpx_idct16x16_10_add_sse2, + TX_16X16, 10), + make_tuple(&vpx_fdct16x16_c, + &vpx_idct16x16_256_add_c, + &vpx_idct16x16_1_add_sse2, + TX_16X16, 1), + make_tuple(&vpx_fdct8x8_c, + &vpx_idct8x8_64_add_c, + &vpx_idct8x8_12_add_sse2, + TX_8X8, 12), + make_tuple(&vpx_fdct8x8_c, + &vpx_idct8x8_64_add_c, + &vpx_idct8x8_1_add_sse2, + TX_8X8, 1), + make_tuple(&vpx_fdct4x4_c, + &vpx_idct4x4_16_add_c, + &vpx_idct4x4_1_add_sse2, + TX_4X4, 1))); +#endif + +#if HAVE_SSSE3 && CONFIG_USE_X86INC && ARCH_X86_64 && \ + !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + SSSE3_64, PartialIDctTest, + ::testing::Values( + make_tuple(&vpx_fdct8x8_c, + &vpx_idct8x8_64_add_c, + &vpx_idct8x8_12_add_ssse3, + TX_8X8, 12))); +#endif + +#if HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE +INSTANTIATE_TEST_CASE_P( + MSA, PartialIDctTest, + ::testing::Values( + make_tuple(&vpx_fdct32x32_c, + &vpx_idct32x32_1024_add_c, + &vpx_idct32x32_34_add_msa, + TX_32X32, 34), + make_tuple(&vpx_fdct32x32_c, + &vpx_idct32x32_1024_add_c, + &vpx_idct32x32_1_add_msa, + TX_32X32, 1), + make_tuple(&vpx_fdct16x16_c, + &vpx_idct16x16_256_add_c, + &vpx_idct16x16_10_add_msa, + TX_16X16, 10), + make_tuple(&vpx_fdct16x16_c, + &vpx_idct16x16_256_add_c, + &vpx_idct16x16_1_add_msa, + TX_16X16, 1), + make_tuple(&vpx_fdct8x8_c, + &vpx_idct8x8_64_add_c, + &vpx_idct8x8_12_add_msa, + TX_8X8, 10), + make_tuple(&vpx_fdct8x8_c, + &vpx_idct8x8_64_add_c, + &vpx_idct8x8_1_add_msa, + TX_8X8, 1), + make_tuple(&vpx_fdct4x4_c, + &vpx_idct4x4_16_add_c, + &vpx_idct4x4_1_add_msa, + TX_4X4, 1))); +#endif // HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE + +} // namespace
diff --git a/src/third_party/libvpx/test/postproc.sh b/src/third_party/libvpx/test/postproc.sh new file mode 100755 index 0000000..939a3e7 --- /dev/null +++ b/src/third_party/libvpx/test/postproc.sh
@@ -0,0 +1,63 @@ +#!/bin/sh +## +## Copyright (c) 2014 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## +## This file tests the libvpx postproc example code. To add new tests to this +## file, do the following: +## 1. Write a shell function (this is your test). +## 2. Add the function to postproc_tests (on a new line). +## +. $(dirname $0)/tools_common.sh + +# Environment check: Make sure input is available: +# $VP8_IVF_FILE and $VP9_IVF_FILE are required. +postproc_verify_environment() { + if [ ! -e "${VP8_IVF_FILE}" ] || [ ! -e "${VP9_IVF_FILE}" ]; then + echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH." + return 1 + fi +} + +# Runs postproc using $1 as input file. $2 is the codec name, and is used +# solely to name the output file. +postproc() { + local decoder="${LIBVPX_BIN_PATH}/postproc${VPX_TEST_EXE_SUFFIX}" + local input_file="$1" + local codec="$2" + local output_file="${VPX_TEST_OUTPUT_DIR}/postproc_${codec}.raw" + + if [ ! -x "${decoder}" ]; then + elog "${decoder} does not exist or is not executable." + return 1 + fi + + eval "${VPX_TEST_PREFIX}" "${decoder}" "${input_file}" "${output_file}" \ + ${devnull} + + [ -e "${output_file}" ] || return 1 +} + +postproc_vp8() { + if [ "$(vp8_decode_available)" = "yes" ]; then + postproc "${VP8_IVF_FILE}" vp8 || return 1 + fi +} + +postproc_vp9() { + if [ "$(vpx_config_option_enabled CONFIG_VP9_POSTPROC)" = "yes" ]; then + if [ "$(vp9_decode_available)" = "yes" ]; then + postproc "${VP9_IVF_FILE}" vp9 || return 1 + fi + fi +} + +postproc_tests="postproc_vp8 + postproc_vp9" + +run_tests postproc_verify_environment "${postproc_tests}"
diff --git a/src/third_party/libvpx/test/pp_filter_test.cc b/src/third_party/libvpx/test/pp_filter_test.cc new file mode 100644 index 0000000..e4688dd --- /dev/null +++ b/src/third_party/libvpx/test/pp_filter_test.cc
@@ -0,0 +1,118 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include "test/clear_system_state.h" +#include "test/register_state_check.h" +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "./vpx_config.h" +#include "./vp8_rtcd.h" +#include "vpx/vpx_integer.h" +#include "vpx_mem/vpx_mem.h" + +typedef void (*PostProcFunc)(unsigned char *src_ptr, + unsigned char *dst_ptr, + int src_pixels_per_line, + int dst_pixels_per_line, + int cols, + unsigned char *flimit, + int size); + +namespace { + +class VP8PostProcessingFilterTest + : public ::testing::TestWithParam<PostProcFunc> { + public: + virtual void TearDown() { + libvpx_test::ClearSystemState(); + } +}; + +// Test routine for the VP8 post-processing function +// vp8_post_proc_down_and_across_mb_row_c. + +TEST_P(VP8PostProcessingFilterTest, FilterOutputCheck) { + // Size of the underlying data block that will be filtered. + const int block_width = 16; + const int block_height = 16; + + // 5-tap filter needs 2 padding rows above and below the block in the input. + const int input_width = block_width; + const int input_height = block_height + 4; + const int input_stride = input_width; + const int input_size = input_width * input_height; + + // Filter extends output block by 8 samples at left and right edges. + const int output_width = block_width + 16; + const int output_height = block_height; + const int output_stride = output_width; + const int output_size = output_width * output_height; + + uint8_t *const src_image = + reinterpret_cast<uint8_t*>(vpx_calloc(input_size, 1)); + uint8_t *const dst_image = + reinterpret_cast<uint8_t*>(vpx_calloc(output_size, 1)); + + // Pointers to top-left pixel of block in the input and output images. + uint8_t *const src_image_ptr = src_image + (input_stride << 1); + uint8_t *const dst_image_ptr = dst_image + 8; + uint8_t *const flimits = + reinterpret_cast<uint8_t *>(vpx_memalign(16, block_width)); + (void)memset(flimits, 255, block_width); + + // Initialize pixels in the input: + // block pixels to value 1, + // border pixels to value 10. + (void)memset(src_image, 10, input_size); + uint8_t *pixel_ptr = src_image_ptr; + for (int i = 0; i < block_height; ++i) { + for (int j = 0; j < block_width; ++j) { + pixel_ptr[j] = 1; + } + pixel_ptr += input_stride; + } + + // Initialize pixels in the output to 99. + (void)memset(dst_image, 99, output_size); + + ASM_REGISTER_STATE_CHECK( + GetParam()(src_image_ptr, dst_image_ptr, input_stride, + output_stride, block_width, flimits, 16)); + + static const uint8_t expected_data[block_height] = { + 4, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 4 + }; + + pixel_ptr = dst_image_ptr; + for (int i = 0; i < block_height; ++i) { + for (int j = 0; j < block_width; ++j) { + EXPECT_EQ(expected_data[i], pixel_ptr[j]) + << "VP8PostProcessingFilterTest failed with invalid filter output"; + } + pixel_ptr += output_stride; + } + + vpx_free(src_image); + vpx_free(dst_image); + vpx_free(flimits); +}; + +INSTANTIATE_TEST_CASE_P(C, VP8PostProcessingFilterTest, + ::testing::Values(vp8_post_proc_down_and_across_mb_row_c)); + +#if HAVE_SSE2 +INSTANTIATE_TEST_CASE_P(SSE2, VP8PostProcessingFilterTest, + ::testing::Values(vp8_post_proc_down_and_across_mb_row_sse2)); +#endif + +#if HAVE_MSA +INSTANTIATE_TEST_CASE_P(MSA, VP8PostProcessingFilterTest, + ::testing::Values(vp8_post_proc_down_and_across_mb_row_msa)); +#endif + +} // namespace
diff --git a/src/third_party/libvpx/test/quantize_test.cc b/src/third_party/libvpx/test/quantize_test.cc new file mode 100644 index 0000000..69da899 --- /dev/null +++ b/src/third_party/libvpx/test/quantize_test.cc
@@ -0,0 +1,203 @@ +/* + * Copyright (c) 2014 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <string.h> + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "./vpx_config.h" +#include "./vp8_rtcd.h" +#include "test/acm_random.h" +#include "test/clear_system_state.h" +#include "test/register_state_check.h" +#include "test/util.h" +#include "vp8/common/blockd.h" +#include "vp8/common/onyx.h" +#include "vp8/encoder/block.h" +#include "vp8/encoder/onyx_int.h" +#include "vp8/encoder/quantize.h" +#include "vpx/vpx_integer.h" +#include "vpx_mem/vpx_mem.h" + +namespace { + +const int kNumBlocks = 25; +const int kNumBlockEntries = 16; + +typedef void (*VP8Quantize)(BLOCK *b, BLOCKD *d); + +typedef std::tr1::tuple<VP8Quantize, VP8Quantize> VP8QuantizeParam; + +using libvpx_test::ACMRandom; +using std::tr1::make_tuple; + +// Create and populate a VP8_COMP instance which has a complete set of +// quantization inputs as well as a second MACROBLOCKD for output. +class QuantizeTestBase { + public: + virtual ~QuantizeTestBase() { + vp8_remove_compressor(&vp8_comp_); + vp8_comp_ = NULL; + vpx_free(macroblockd_dst_); + macroblockd_dst_ = NULL; + libvpx_test::ClearSystemState(); + } + + protected: + void SetupCompressor() { + rnd_.Reset(ACMRandom::DeterministicSeed()); + + // The full configuration is necessary to generate the quantization tables. + VP8_CONFIG vp8_config; + memset(&vp8_config, 0, sizeof(vp8_config)); + + vp8_comp_ = vp8_create_compressor(&vp8_config); + + // Set the tables based on a quantizer of 0. + vp8_set_quantizer(vp8_comp_, 0); + + // Set up all the block/blockd pointers for the mb in vp8_comp_. + vp8cx_frame_init_quantizer(vp8_comp_); + + // Copy macroblockd from the reference to get pre-set-up dequant values. + macroblockd_dst_ = reinterpret_cast<MACROBLOCKD *>( + vpx_memalign(32, sizeof(*macroblockd_dst_))); + memcpy(macroblockd_dst_, &vp8_comp_->mb.e_mbd, sizeof(*macroblockd_dst_)); + // Fix block pointers - currently they point to the blocks in the reference + // structure. + vp8_setup_block_dptrs(macroblockd_dst_); + } + + void UpdateQuantizer(int q) { + vp8_set_quantizer(vp8_comp_, q); + + memcpy(macroblockd_dst_, &vp8_comp_->mb.e_mbd, sizeof(*macroblockd_dst_)); + vp8_setup_block_dptrs(macroblockd_dst_); + } + + void FillCoeffConstant(int16_t c) { + for (int i = 0; i < kNumBlocks * kNumBlockEntries; ++i) { + vp8_comp_->mb.coeff[i] = c; + } + } + + void FillCoeffRandom() { + for (int i = 0; i < kNumBlocks * kNumBlockEntries; ++i) { + vp8_comp_->mb.coeff[i] = rnd_.Rand8(); + } + } + + void CheckOutput() { + EXPECT_EQ(0, memcmp(vp8_comp_->mb.e_mbd.qcoeff, macroblockd_dst_->qcoeff, + sizeof(*macroblockd_dst_->qcoeff) * kNumBlocks * + kNumBlockEntries)) + << "qcoeff mismatch"; + EXPECT_EQ(0, memcmp(vp8_comp_->mb.e_mbd.dqcoeff, macroblockd_dst_->dqcoeff, + sizeof(*macroblockd_dst_->dqcoeff) * kNumBlocks * + kNumBlockEntries)) + << "dqcoeff mismatch"; + EXPECT_EQ(0, memcmp(vp8_comp_->mb.e_mbd.eobs, macroblockd_dst_->eobs, + sizeof(*macroblockd_dst_->eobs) * kNumBlocks)) + << "eobs mismatch"; + } + + VP8_COMP *vp8_comp_; + MACROBLOCKD *macroblockd_dst_; + + private: + ACMRandom rnd_; +}; + +class QuantizeTest : public QuantizeTestBase, + public ::testing::TestWithParam<VP8QuantizeParam> { + protected: + virtual void SetUp() { + SetupCompressor(); + asm_quant_ = GET_PARAM(0); + c_quant_ = GET_PARAM(1); + } + + void RunComparison() { + for (int i = 0; i < kNumBlocks; ++i) { + ASM_REGISTER_STATE_CHECK( + c_quant_(&vp8_comp_->mb.block[i], &vp8_comp_->mb.e_mbd.block[i])); + ASM_REGISTER_STATE_CHECK( + asm_quant_(&vp8_comp_->mb.block[i], ¯oblockd_dst_->block[i])); + } + + CheckOutput(); + } + + private: + VP8Quantize asm_quant_; + VP8Quantize c_quant_; +}; + +TEST_P(QuantizeTest, TestZeroInput) { + FillCoeffConstant(0); + RunComparison(); +} + +TEST_P(QuantizeTest, TestLargeNegativeInput) { + FillCoeffConstant(0); + // Generate a qcoeff which contains 512/-512 (0x0100/0xFE00) to catch issues + // like BUG=883 where the constant being compared was incorrectly initialized. + vp8_comp_->mb.coeff[0] = -8191; + RunComparison(); +} + +TEST_P(QuantizeTest, TestRandomInput) { + FillCoeffRandom(); + RunComparison(); +} + +TEST_P(QuantizeTest, TestMultipleQ) { + for (int q = 0; q < QINDEX_RANGE; ++q) { + UpdateQuantizer(q); + FillCoeffRandom(); + RunComparison(); + } +} + +#if HAVE_SSE2 +INSTANTIATE_TEST_CASE_P( + SSE2, QuantizeTest, + ::testing::Values( + make_tuple(&vp8_fast_quantize_b_sse2, &vp8_fast_quantize_b_c), + make_tuple(&vp8_regular_quantize_b_sse2, &vp8_regular_quantize_b_c))); +#endif // HAVE_SSE2 + +#if HAVE_SSSE3 +INSTANTIATE_TEST_CASE_P(SSSE3, QuantizeTest, + ::testing::Values(make_tuple(&vp8_fast_quantize_b_ssse3, + &vp8_fast_quantize_b_c))); +#endif // HAVE_SSSE3 + +#if HAVE_SSE4_1 +INSTANTIATE_TEST_CASE_P( + SSE4_1, QuantizeTest, + ::testing::Values(make_tuple(&vp8_regular_quantize_b_sse4_1, + &vp8_regular_quantize_b_c))); +#endif // HAVE_SSE4_1 + +#if HAVE_NEON +INSTANTIATE_TEST_CASE_P(NEON, QuantizeTest, + ::testing::Values(make_tuple(&vp8_fast_quantize_b_neon, + &vp8_fast_quantize_b_c))); +#endif // HAVE_NEON + +#if HAVE_MSA +INSTANTIATE_TEST_CASE_P( + MSA, QuantizeTest, + ::testing::Values( + make_tuple(&vp8_fast_quantize_b_msa, &vp8_fast_quantize_b_c), + make_tuple(&vp8_regular_quantize_b_msa, &vp8_regular_quantize_b_c))); +#endif // HAVE_MSA +} // namespace
diff --git a/src/third_party/libvpx/test/realtime_test.cc b/src/third_party/libvpx/test/realtime_test.cc new file mode 100644 index 0000000..24749e4 --- /dev/null +++ b/src/third_party/libvpx/test/realtime_test.cc
@@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include "test/codec_factory.h" +#include "test/encode_test_driver.h" +#include "test/util.h" +#include "test/video_source.h" +#include "third_party/googletest/src/include/gtest/gtest.h" + +namespace { + +const int kVideoSourceWidth = 320; +const int kVideoSourceHeight = 240; +const int kFramesToEncode = 2; + +class RealtimeTest + : public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> { + protected: + RealtimeTest() + : EncoderTest(GET_PARAM(0)), frame_packets_(0) {} + virtual ~RealtimeTest() {} + + virtual void SetUp() { + InitializeConfig(); + cfg_.g_lag_in_frames = 0; + SetMode(::libvpx_test::kRealTime); + } + + virtual void BeginPassHook(unsigned int /*pass*/) { + // TODO(tomfinegan): We're changing the pass value here to make sure + // we get frames when real time mode is combined with |g_pass| set to + // VPX_RC_FIRST_PASS. This is necessary because EncoderTest::RunLoop() sets + // the pass value based on the mode passed into EncoderTest::SetMode(), + // which overrides the one specified in SetUp() above. + cfg_.g_pass = VPX_RC_FIRST_PASS; + } + virtual void FramePktHook(const vpx_codec_cx_pkt_t * /*pkt*/) { + frame_packets_++; + } + + int frame_packets_; +}; + +TEST_P(RealtimeTest, RealtimeFirstPassProducesFrames) { + ::libvpx_test::RandomVideoSource video; + video.SetSize(kVideoSourceWidth, kVideoSourceHeight); + video.set_limit(kFramesToEncode); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + EXPECT_EQ(kFramesToEncode, frame_packets_); +} + +VP8_INSTANTIATE_TEST_CASE(RealtimeTest, + ::testing::Values(::libvpx_test::kRealTime)); +VP9_INSTANTIATE_TEST_CASE(RealtimeTest, + ::testing::Values(::libvpx_test::kRealTime)); + +} // namespace
diff --git a/src/third_party/libvpx/test/register_state_check.h b/src/third_party/libvpx/test/register_state_check.h new file mode 100644 index 0000000..5336f2f --- /dev/null +++ b/src/third_party/libvpx/test/register_state_check.h
@@ -0,0 +1,192 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef TEST_REGISTER_STATE_CHECK_H_ +#define TEST_REGISTER_STATE_CHECK_H_ + +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "./vpx_config.h" +#include "vpx/vpx_integer.h" + +// ASM_REGISTER_STATE_CHECK(asm_function) +// Minimally validates the environment pre & post function execution. This +// variant should be used with assembly functions which are not expected to +// fully restore the system state. See platform implementations of +// RegisterStateCheck for details. +// +// API_REGISTER_STATE_CHECK(api_function) +// Performs all the checks done by ASM_REGISTER_STATE_CHECK() and any +// additional checks to ensure the environment is in a consistent state pre & +// post function execution. This variant should be used with API functions. +// See platform implementations of RegisterStateCheckXXX for details. +// + +#if defined(_WIN64) + +#undef NOMINMAX +#define NOMINMAX +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <winnt.h> + +inline bool operator==(const M128A& lhs, const M128A& rhs) { + return (lhs.Low == rhs.Low && lhs.High == rhs.High); +} + +namespace libvpx_test { + +// Compares the state of xmm[6-15] at construction with their state at +// destruction. These registers should be preserved by the callee on +// Windows x64. +class RegisterStateCheck { + public: + RegisterStateCheck() { initialized_ = StoreRegisters(&pre_context_); } + ~RegisterStateCheck() { EXPECT_TRUE(Check()); } + + private: + static bool StoreRegisters(CONTEXT* const context) { + const HANDLE this_thread = GetCurrentThread(); + EXPECT_TRUE(this_thread != NULL); + context->ContextFlags = CONTEXT_FLOATING_POINT; + const bool context_saved = GetThreadContext(this_thread, context) == TRUE; + EXPECT_TRUE(context_saved) << "GetLastError: " << GetLastError(); + return context_saved; + } + + // Compares the register state. Returns true if the states match. + bool Check() const { + if (!initialized_) return false; + CONTEXT post_context; + if (!StoreRegisters(&post_context)) return false; + + const M128A* xmm_pre = &pre_context_.Xmm6; + const M128A* xmm_post = &post_context.Xmm6; + for (int i = 6; i <= 15; ++i) { + EXPECT_EQ(*xmm_pre, *xmm_post) << "xmm" << i << " has been modified!"; + ++xmm_pre; + ++xmm_post; + } + return !testing::Test::HasNonfatalFailure(); + } + + bool initialized_; + CONTEXT pre_context_; +}; + +#define ASM_REGISTER_STATE_CHECK(statement) do { \ + libvpx_test::RegisterStateCheck reg_check; \ + statement; \ +} while (false) + +} // namespace libvpx_test + +#elif defined(CONFIG_SHARED) && defined(HAVE_NEON_ASM) && defined(CONFIG_VP9) \ + && !CONFIG_SHARED && HAVE_NEON_ASM && CONFIG_VP9 + +extern "C" { +// Save the d8-d15 registers into store. +void vpx_push_neon(int64_t *store); +} + +namespace libvpx_test { + +// Compares the state of d8-d15 at construction with their state at +// destruction. These registers should be preserved by the callee on +// arm platform. +class RegisterStateCheck { + public: + RegisterStateCheck() { initialized_ = StoreRegisters(pre_store_); } + ~RegisterStateCheck() { EXPECT_TRUE(Check()); } + + private: + static bool StoreRegisters(int64_t store[8]) { + vpx_push_neon(store); + return true; + } + + // Compares the register state. Returns true if the states match. + bool Check() const { + if (!initialized_) return false; + int64_t post_store[8]; + vpx_push_neon(post_store); + for (int i = 0; i < 8; ++i) { + EXPECT_EQ(pre_store_[i], post_store[i]) << "d" + << i + 8 << " has been modified"; + } + return !testing::Test::HasNonfatalFailure(); + } + + bool initialized_; + int64_t pre_store_[8]; +}; + +#define ASM_REGISTER_STATE_CHECK(statement) do { \ + libvpx_test::RegisterStateCheck reg_check; \ + statement; \ +} while (false) + +} // namespace libvpx_test + +#else + +namespace libvpx_test { + +class RegisterStateCheck {}; +#define ASM_REGISTER_STATE_CHECK(statement) statement + +} // namespace libvpx_test + +#endif // _WIN64 + +#if ARCH_X86 || ARCH_X86_64 +#if defined(__GNUC__) + +namespace libvpx_test { + +// Checks the FPU tag word pre/post execution to ensure emms has been called. +class RegisterStateCheckMMX { + public: + RegisterStateCheckMMX() { + __asm__ volatile("fstenv %0" : "=rm"(pre_fpu_env_)); + } + ~RegisterStateCheckMMX() { EXPECT_TRUE(Check()); } + + private: + // Checks the FPU tag word pre/post execution, returning false if not cleared + // to 0xffff. + bool Check() const { + EXPECT_EQ(0xffff, pre_fpu_env_[4]) + << "FPU was in an inconsistent state prior to call"; + + uint16_t post_fpu_env[14]; + __asm__ volatile("fstenv %0" : "=rm"(post_fpu_env)); + EXPECT_EQ(0xffff, post_fpu_env[4]) + << "FPU was left in an inconsistent state after call"; + return !testing::Test::HasNonfatalFailure(); + } + + uint16_t pre_fpu_env_[14]; +}; + +#define API_REGISTER_STATE_CHECK(statement) do { \ + libvpx_test::RegisterStateCheckMMX reg_check; \ + ASM_REGISTER_STATE_CHECK(statement); \ +} while (false) + +} // namespace libvpx_test + +#endif // __GNUC__ +#endif // ARCH_X86 || ARCH_X86_64 + +#ifndef API_REGISTER_STATE_CHECK +#define API_REGISTER_STATE_CHECK ASM_REGISTER_STATE_CHECK +#endif + +#endif // TEST_REGISTER_STATE_CHECK_H_
diff --git a/src/third_party/libvpx/test/resize_test.cc b/src/third_party/libvpx/test/resize_test.cc new file mode 100644 index 0000000..90f5452 --- /dev/null +++ b/src/third_party/libvpx/test/resize_test.cc
@@ -0,0 +1,735 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include <stdio.h> + +#include <climits> +#include <vector> +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "test/codec_factory.h" +#include "test/encode_test_driver.h" +#include "test/i420_video_source.h" +#include "test/video_source.h" +#include "test/util.h" + +// Enable(1) or Disable(0) writing of the compressed bitstream. +#define WRITE_COMPRESSED_STREAM 0 + +namespace { + +#if WRITE_COMPRESSED_STREAM +static void mem_put_le16(char *const mem, const unsigned int val) { + mem[0] = val; + mem[1] = val >> 8; +} + +static void mem_put_le32(char *const mem, const unsigned int val) { + mem[0] = val; + mem[1] = val >> 8; + mem[2] = val >> 16; + mem[3] = val >> 24; +} + +static void write_ivf_file_header(const vpx_codec_enc_cfg_t *const cfg, + int frame_cnt, FILE *const outfile) { + char header[32]; + + header[0] = 'D'; + header[1] = 'K'; + header[2] = 'I'; + header[3] = 'F'; + mem_put_le16(header + 4, 0); /* version */ + mem_put_le16(header + 6, 32); /* headersize */ + mem_put_le32(header + 8, 0x30395056); /* fourcc (vp9) */ + mem_put_le16(header + 12, cfg->g_w); /* width */ + mem_put_le16(header + 14, cfg->g_h); /* height */ + mem_put_le32(header + 16, cfg->g_timebase.den); /* rate */ + mem_put_le32(header + 20, cfg->g_timebase.num); /* scale */ + mem_put_le32(header + 24, frame_cnt); /* length */ + mem_put_le32(header + 28, 0); /* unused */ + + (void)fwrite(header, 1, 32, outfile); +} + +static void write_ivf_frame_size(FILE *const outfile, const size_t size) { + char header[4]; + mem_put_le32(header, static_cast<unsigned int>(size)); + (void)fwrite(header, 1, 4, outfile); +} + +static void write_ivf_frame_header(const vpx_codec_cx_pkt_t *const pkt, + FILE *const outfile) { + char header[12]; + vpx_codec_pts_t pts; + + if (pkt->kind != VPX_CODEC_CX_FRAME_PKT) + return; + + pts = pkt->data.frame.pts; + mem_put_le32(header, static_cast<unsigned int>(pkt->data.frame.sz)); + mem_put_le32(header + 4, pts & 0xFFFFFFFF); + mem_put_le32(header + 8, pts >> 32); + + (void)fwrite(header, 1, 12, outfile); +} +#endif // WRITE_COMPRESSED_STREAM + +const unsigned int kInitialWidth = 320; +const unsigned int kInitialHeight = 240; + +struct FrameInfo { + FrameInfo(vpx_codec_pts_t _pts, unsigned int _w, unsigned int _h) + : pts(_pts), w(_w), h(_h) {} + + vpx_codec_pts_t pts; + unsigned int w; + unsigned int h; +}; + +void ScaleForFrameNumber(unsigned int frame, + unsigned int initial_w, + unsigned int initial_h, + unsigned int *w, + unsigned int *h, + int flag_codec) { + if (frame < 10) { + *w = initial_w; + *h = initial_h; + return; + } + if (frame < 20) { + *w = initial_w * 3 / 4; + *h = initial_h * 3 / 4; + return; + } + if (frame < 30) { + *w = initial_w / 2; + *h = initial_h / 2; + return; + } + if (frame < 40) { + *w = initial_w; + *h = initial_h; + return; + } + if (frame < 50) { + *w = initial_w * 3 / 4; + *h = initial_h * 3 / 4; + return; + } + if (frame < 60) { + *w = initial_w / 2; + *h = initial_h / 2; + return; + } + if (frame < 70) { + *w = initial_w; + *h = initial_h; + return; + } + if (frame < 80) { + *w = initial_w * 3 / 4; + *h = initial_h * 3 / 4; + return; + } + if (frame < 90) { + *w = initial_w / 2; + *h = initial_h / 2; + return; + } + if (frame < 100) { + *w = initial_w * 3 / 4; + *h = initial_h * 3 / 4; + return; + } + if (frame < 110) { + *w = initial_w; + *h = initial_h; + return; + } + if (frame < 120) { + *w = initial_w * 3 / 4; + *h = initial_h * 3 / 4; + return; + } + if (frame < 130) { + *w = initial_w / 2; + *h = initial_h / 2; + return; + } + if (frame < 140) { + *w = initial_w * 3 / 4; + *h = initial_h * 3 / 4; + return; + } + if (frame < 150) { + *w = initial_w; + *h = initial_h; + return; + } + if (frame < 160) { + *w = initial_w * 3 / 4; + *h = initial_h * 3 / 4; + return; + } + if (frame < 170) { + *w = initial_w / 2; + *h = initial_h / 2; + return; + } + if (frame < 180) { + *w = initial_w * 3 / 4; + *h = initial_h * 3 / 4; + return; + } + if (frame < 190) { + *w = initial_w; + *h = initial_h; + return; + } + if (frame < 200) { + *w = initial_w * 3 / 4; + *h = initial_h * 3 / 4; + return; + } + if (frame < 210) { + *w = initial_w / 2; + *h = initial_h / 2; + return; + } + if (frame < 220) { + *w = initial_w * 3 / 4; + *h = initial_h * 3 / 4; + return; + } + if (frame < 230) { + *w = initial_w; + *h = initial_h; + return; + } + if (frame < 240) { + *w = initial_w * 3 / 4; + *h = initial_h * 3 / 4; + return; + } + if (frame < 250) { + *w = initial_w / 2; + *h = initial_h / 2; + return; + } + if (frame < 260) { + *w = initial_w; + *h = initial_h; + return; + } + // Go down very low. + if (frame < 270) { + *w = initial_w / 4; + *h = initial_h / 4; + return; + } + if (flag_codec == 1) { + // Cases that only works for VP9. + // For VP9: Swap width and height of original. + if (frame < 320) { + *w = initial_h; + *h = initial_w; + return; + } + } + *w = initial_w; + *h = initial_h; +} + +class ResizingVideoSource : public ::libvpx_test::DummyVideoSource { + public: + ResizingVideoSource() { + SetSize(kInitialWidth, kInitialHeight); + limit_ = 350; + } + int flag_codec_; + virtual ~ResizingVideoSource() {} + + protected: + virtual void Next() { + ++frame_; + unsigned int width; + unsigned int height; + ScaleForFrameNumber(frame_, kInitialWidth, kInitialHeight, &width, &height, + flag_codec_); + SetSize(width, height); + FillFrame(); + } +}; + +class ResizeTest : public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> { + protected: + ResizeTest() : EncoderTest(GET_PARAM(0)) {} + + virtual ~ResizeTest() {} + + virtual void SetUp() { + InitializeConfig(); + SetMode(GET_PARAM(1)); + } + + virtual void DecompressedFrameHook(const vpx_image_t &img, + vpx_codec_pts_t pts) { + frame_info_list_.push_back(FrameInfo(pts, img.d_w, img.d_h)); + } + + std::vector< FrameInfo > frame_info_list_; +}; + +TEST_P(ResizeTest, TestExternalResizeWorks) { + ResizingVideoSource video; + video.flag_codec_ = 0; + cfg_.g_lag_in_frames = 0; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + + for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin(); + info != frame_info_list_.end(); ++info) { + const unsigned int frame = static_cast<unsigned>(info->pts); + unsigned int expected_w; + unsigned int expected_h; + ScaleForFrameNumber(frame, kInitialWidth, kInitialHeight, + &expected_w, &expected_h, 0); + EXPECT_EQ(expected_w, info->w) + << "Frame " << frame << " had unexpected width"; + EXPECT_EQ(expected_h, info->h) + << "Frame " << frame << " had unexpected height"; + } +} + +const unsigned int kStepDownFrame = 3; +const unsigned int kStepUpFrame = 6; + +class ResizeInternalTest : public ResizeTest { + protected: +#if WRITE_COMPRESSED_STREAM + ResizeInternalTest() + : ResizeTest(), + frame0_psnr_(0.0), + outfile_(NULL), + out_frames_(0) {} +#else + ResizeInternalTest() : ResizeTest(), frame0_psnr_(0.0) {} +#endif + + virtual ~ResizeInternalTest() {} + + virtual void BeginPassHook(unsigned int /*pass*/) { +#if WRITE_COMPRESSED_STREAM + outfile_ = fopen("vp90-2-05-resize.ivf", "wb"); +#endif + } + + virtual void EndPassHook() { +#if WRITE_COMPRESSED_STREAM + if (outfile_) { + if (!fseek(outfile_, 0, SEEK_SET)) + write_ivf_file_header(&cfg_, out_frames_, outfile_); + fclose(outfile_); + outfile_ = NULL; + } +#endif + } + + virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video, + libvpx_test::Encoder *encoder) { + if (change_config_) { + int new_q = 60; + if (video->frame() == 0) { + struct vpx_scaling_mode mode = {VP8E_ONETWO, VP8E_ONETWO}; + encoder->Control(VP8E_SET_SCALEMODE, &mode); + } + if (video->frame() == 1) { + struct vpx_scaling_mode mode = {VP8E_NORMAL, VP8E_NORMAL}; + encoder->Control(VP8E_SET_SCALEMODE, &mode); + cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = new_q; + encoder->Config(&cfg_); + } + } else { + if (video->frame() == kStepDownFrame) { + struct vpx_scaling_mode mode = {VP8E_FOURFIVE, VP8E_THREEFIVE}; + encoder->Control(VP8E_SET_SCALEMODE, &mode); + } + if (video->frame() == kStepUpFrame) { + struct vpx_scaling_mode mode = {VP8E_NORMAL, VP8E_NORMAL}; + encoder->Control(VP8E_SET_SCALEMODE, &mode); + } + } + } + + virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) { + if (!frame0_psnr_) + frame0_psnr_ = pkt->data.psnr.psnr[0]; + EXPECT_NEAR(pkt->data.psnr.psnr[0], frame0_psnr_, 2.0); + } + +#if WRITE_COMPRESSED_STREAM + virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) { + ++out_frames_; + + // Write initial file header if first frame. + if (pkt->data.frame.pts == 0) + write_ivf_file_header(&cfg_, 0, outfile_); + + // Write frame header and data. + write_ivf_frame_header(pkt, outfile_); + (void)fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile_); + } +#endif + + double frame0_psnr_; + bool change_config_; +#if WRITE_COMPRESSED_STREAM + FILE *outfile_; + unsigned int out_frames_; +#endif +}; + +TEST_P(ResizeInternalTest, TestInternalResizeWorks) { + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 10); + init_flags_ = VPX_CODEC_USE_PSNR; + change_config_ = false; + + // q picked such that initial keyframe on this clip is ~30dB PSNR + cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = 48; + + // If the number of frames being encoded is smaller than g_lag_in_frames + // the encoded frame is unavailable using the current API. Comparing + // frames to detect mismatch would then not be possible. Set + // g_lag_in_frames = 0 to get around this. + cfg_.g_lag_in_frames = 0; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + + for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin(); + info != frame_info_list_.end(); ++info) { + const vpx_codec_pts_t pts = info->pts; + if (pts >= kStepDownFrame && pts < kStepUpFrame) { + ASSERT_EQ(282U, info->w) << "Frame " << pts << " had unexpected width"; + ASSERT_EQ(173U, info->h) << "Frame " << pts << " had unexpected height"; + } else { + EXPECT_EQ(352U, info->w) << "Frame " << pts << " had unexpected width"; + EXPECT_EQ(288U, info->h) << "Frame " << pts << " had unexpected height"; + } + } +} + +TEST_P(ResizeInternalTest, TestInternalResizeChangeConfig) { + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 10); + cfg_.g_w = 352; + cfg_.g_h = 288; + change_config_ = true; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); +} + +class ResizeRealtimeTest : public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> { + protected: + ResizeRealtimeTest() : EncoderTest(GET_PARAM(0)) {} + virtual ~ResizeRealtimeTest() {} + + virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video, + libvpx_test::Encoder *encoder) { + if (video->frame() == 0) { + encoder->Control(VP9E_SET_AQ_MODE, 3); + encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_); + } + + if (change_bitrate_ && video->frame() == 120) { + change_bitrate_ = false; + cfg_.rc_target_bitrate = 500; + encoder->Config(&cfg_); + } + } + + virtual void SetUp() { + InitializeConfig(); + SetMode(GET_PARAM(1)); + set_cpu_used_ = GET_PARAM(2); + } + + virtual void DecompressedFrameHook(const vpx_image_t &img, + vpx_codec_pts_t pts) { + frame_info_list_.push_back(FrameInfo(pts, img.d_w, img.d_h)); + } + + virtual void MismatchHook(const vpx_image_t *img1, + const vpx_image_t *img2) { + double mismatch_psnr = compute_psnr(img1, img2); + mismatch_psnr_ += mismatch_psnr; + ++mismatch_nframes_; + } + + unsigned int GetMismatchFrames() { + return mismatch_nframes_; + } + + void DefaultConfig() { + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 600; + cfg_.rc_buf_sz = 1000; + cfg_.rc_min_quantizer = 2; + cfg_.rc_max_quantizer = 56; + cfg_.rc_undershoot_pct = 50; + cfg_.rc_overshoot_pct = 50; + cfg_.rc_end_usage = VPX_CBR; + cfg_.kf_mode = VPX_KF_AUTO; + cfg_.g_lag_in_frames = 0; + cfg_.kf_min_dist = cfg_.kf_max_dist = 3000; + // Enable dropped frames. + cfg_.rc_dropframe_thresh = 1; + // Enable error_resilience mode. + cfg_.g_error_resilient = 1; + // Enable dynamic resizing. + cfg_.rc_resize_allowed = 1; + // Run at low bitrate. + cfg_.rc_target_bitrate = 200; + } + + std::vector< FrameInfo > frame_info_list_; + int set_cpu_used_; + bool change_bitrate_; + double mismatch_psnr_; + int mismatch_nframes_; +}; + +TEST_P(ResizeRealtimeTest, TestExternalResizeWorks) { + ResizingVideoSource video; + video.flag_codec_ = 1; + DefaultConfig(); + // Disable internal resize for this test. + cfg_.rc_resize_allowed = 0; + change_bitrate_ = false; + mismatch_psnr_ = 0.0; + mismatch_nframes_ = 0; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + + for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin(); + info != frame_info_list_.end(); ++info) { + const unsigned int frame = static_cast<unsigned>(info->pts); + unsigned int expected_w; + unsigned int expected_h; + ScaleForFrameNumber(frame, kInitialWidth, kInitialHeight, + &expected_w, &expected_h, 1); + EXPECT_EQ(expected_w, info->w) + << "Frame " << frame << " had unexpected width"; + EXPECT_EQ(expected_h, info->h) + << "Frame " << frame << " had unexpected height"; + EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames()); + } +} + +// Verify the dynamic resizer behavior for real time, 1 pass CBR mode. +// Run at low bitrate, with resize_allowed = 1, and verify that we get +// one resize down event. +TEST_P(ResizeRealtimeTest, TestInternalResizeDown) { + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 299); + DefaultConfig(); + cfg_.g_w = 352; + cfg_.g_h = 288; + change_bitrate_ = false; + mismatch_psnr_ = 0.0; + mismatch_nframes_ = 0; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + + unsigned int last_w = cfg_.g_w; + unsigned int last_h = cfg_.g_h; + int resize_count = 0; + for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin(); + info != frame_info_list_.end(); ++info) { + if (info->w != last_w || info->h != last_h) { + // Verify that resize down occurs. + ASSERT_LT(info->w, last_w); + ASSERT_LT(info->h, last_h); + last_w = info->w; + last_h = info->h; + resize_count++; + } + } + +#if CONFIG_VP9_DECODER + // Verify that we get 1 resize down event in this test. + ASSERT_EQ(1, resize_count) << "Resizing should occur."; + EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames()); +#else + printf("Warning: VP9 decoder unavailable, unable to check resize count!\n"); +#endif +} + +// Verify the dynamic resizer behavior for real time, 1 pass CBR mode. +// Start at low target bitrate, raise the bitrate in the middle of the clip, +// scaling-up should occur after bitrate changed. +TEST_P(ResizeRealtimeTest, TestInternalResizeDownUpChangeBitRate) { + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 359); + DefaultConfig(); + cfg_.g_w = 352; + cfg_.g_h = 288; + change_bitrate_ = true; + mismatch_psnr_ = 0.0; + mismatch_nframes_ = 0; + // Disable dropped frames. + cfg_.rc_dropframe_thresh = 0; + // Starting bitrate low. + cfg_.rc_target_bitrate = 80; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + + unsigned int last_w = cfg_.g_w; + unsigned int last_h = cfg_.g_h; + int resize_count = 0; + for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin(); + info != frame_info_list_.end(); ++info) { + if (info->w != last_w || info->h != last_h) { + resize_count++; + if (resize_count == 1) { + // Verify that resize down occurs. + ASSERT_LT(info->w, last_w); + ASSERT_LT(info->h, last_h); + } else if (resize_count == 2) { + // Verify that resize up occurs. + ASSERT_GT(info->w, last_w); + ASSERT_GT(info->h, last_h); + } + last_w = info->w; + last_h = info->h; + } + } + +#if CONFIG_VP9_DECODER + // Verify that we get 2 resize events in this test. + ASSERT_EQ(resize_count, 2) << "Resizing should occur twice."; + EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames()); +#else + printf("Warning: VP9 decoder unavailable, unable to check resize count!\n"); +#endif +} + +vpx_img_fmt_t CspForFrameNumber(int frame) { + if (frame < 10) + return VPX_IMG_FMT_I420; + if (frame < 20) + return VPX_IMG_FMT_I444; + return VPX_IMG_FMT_I420; +} + +class ResizeCspTest : public ResizeTest { + protected: +#if WRITE_COMPRESSED_STREAM + ResizeCspTest() + : ResizeTest(), + frame0_psnr_(0.0), + outfile_(NULL), + out_frames_(0) {} +#else + ResizeCspTest() : ResizeTest(), frame0_psnr_(0.0) {} +#endif + + virtual ~ResizeCspTest() {} + + virtual void BeginPassHook(unsigned int /*pass*/) { +#if WRITE_COMPRESSED_STREAM + outfile_ = fopen("vp91-2-05-cspchape.ivf", "wb"); +#endif + } + + virtual void EndPassHook() { +#if WRITE_COMPRESSED_STREAM + if (outfile_) { + if (!fseek(outfile_, 0, SEEK_SET)) + write_ivf_file_header(&cfg_, out_frames_, outfile_); + fclose(outfile_); + outfile_ = NULL; + } +#endif + } + + virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video, + libvpx_test::Encoder *encoder) { + if (CspForFrameNumber(video->frame()) != VPX_IMG_FMT_I420 && + cfg_.g_profile != 1) { + cfg_.g_profile = 1; + encoder->Config(&cfg_); + } + if (CspForFrameNumber(video->frame()) == VPX_IMG_FMT_I420 && + cfg_.g_profile != 0) { + cfg_.g_profile = 0; + encoder->Config(&cfg_); + } + } + + virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) { + if (!frame0_psnr_) + frame0_psnr_ = pkt->data.psnr.psnr[0]; + EXPECT_NEAR(pkt->data.psnr.psnr[0], frame0_psnr_, 2.0); + } + +#if WRITE_COMPRESSED_STREAM + virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) { + ++out_frames_; + + // Write initial file header if first frame. + if (pkt->data.frame.pts == 0) + write_ivf_file_header(&cfg_, 0, outfile_); + + // Write frame header and data. + write_ivf_frame_header(pkt, outfile_); + (void)fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile_); + } +#endif + + double frame0_psnr_; +#if WRITE_COMPRESSED_STREAM + FILE *outfile_; + unsigned int out_frames_; +#endif +}; + +class ResizingCspVideoSource : public ::libvpx_test::DummyVideoSource { + public: + ResizingCspVideoSource() { + SetSize(kInitialWidth, kInitialHeight); + limit_ = 30; + } + + virtual ~ResizingCspVideoSource() {} + + protected: + virtual void Next() { + ++frame_; + SetImageFormat(CspForFrameNumber(frame_)); + FillFrame(); + } +}; + +TEST_P(ResizeCspTest, TestResizeCspWorks) { + ResizingCspVideoSource video; + init_flags_ = VPX_CODEC_USE_PSNR; + cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = 48; + cfg_.g_lag_in_frames = 0; + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); +} + +VP8_INSTANTIATE_TEST_CASE(ResizeTest, ONE_PASS_TEST_MODES); +VP9_INSTANTIATE_TEST_CASE(ResizeTest, + ::testing::Values(::libvpx_test::kRealTime)); +VP9_INSTANTIATE_TEST_CASE(ResizeInternalTest, + ::testing::Values(::libvpx_test::kOnePassBest)); +VP9_INSTANTIATE_TEST_CASE(ResizeRealtimeTest, + ::testing::Values(::libvpx_test::kRealTime), + ::testing::Range(5, 9)); +VP9_INSTANTIATE_TEST_CASE(ResizeCspTest, + ::testing::Values(::libvpx_test::kRealTime)); +} // namespace
diff --git a/src/third_party/libvpx/test/resize_util.sh b/src/third_party/libvpx/test/resize_util.sh new file mode 100755 index 0000000..5e47271 --- /dev/null +++ b/src/third_party/libvpx/test/resize_util.sh
@@ -0,0 +1,69 @@ +#!/bin/sh +## +## Copyright (c) 2014 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## +## This file tests the libvpx resize_util example code. To add new tests to +## this file, do the following: +## 1. Write a shell function (this is your test). +## 2. Add the function to resize_util_tests (on a new line). +## +. $(dirname $0)/tools_common.sh + +# Environment check: $YUV_RAW_INPUT is required. +resize_util_verify_environment() { + if [ ! -e "${YUV_RAW_INPUT}" ]; then + echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH." + return 1 + fi +} + +# Resizes $YUV_RAW_INPUT using the resize_util example. $1 is the output +# dimensions that will be passed to resize_util. +resize_util() { + local resizer="${LIBVPX_BIN_PATH}/resize_util${VPX_TEST_EXE_SUFFIX}" + local output_file="${VPX_TEST_OUTPUT_DIR}/resize_util.raw" + local frames_to_resize="10" + local target_dimensions="$1" + + # resize_util is available only when CONFIG_SHARED is disabled. + if [ -z "$(vpx_config_option_enabled CONFIG_SHARED)" ]; then + if [ ! -x "${resizer}" ]; then + elog "${resizer} does not exist or is not executable." + return 1 + fi + + eval "${VPX_TEST_PREFIX}" "${resizer}" "${YUV_RAW_INPUT}" \ + "${YUV_RAW_INPUT_WIDTH}x${YUV_RAW_INPUT_HEIGHT}" \ + "${target_dimensions}" "${output_file}" ${frames_to_resize} \ + ${devnull} + + [ -e "${output_file}" ] || return 1 + fi +} + +# Halves each dimension of $YUV_RAW_INPUT using resize_util(). +resize_down() { + local target_width=$((${YUV_RAW_INPUT_WIDTH} / 2)) + local target_height=$((${YUV_RAW_INPUT_HEIGHT} / 2)) + + resize_util "${target_width}x${target_height}" +} + +# Doubles each dimension of $YUV_RAW_INPUT using resize_util(). +resize_up() { + local target_width=$((${YUV_RAW_INPUT_WIDTH} * 2)) + local target_height=$((${YUV_RAW_INPUT_HEIGHT} * 2)) + + resize_util "${target_width}x${target_height}" +} + +resize_util_tests="resize_down + resize_up" + +run_tests resize_util_verify_environment "${resize_util_tests}"
diff --git a/src/third_party/libvpx/test/sad_test.cc b/src/third_party/libvpx/test/sad_test.cc new file mode 100644 index 0000000..e6bd0d7 --- /dev/null +++ b/src/third_party/libvpx/test/sad_test.cc
@@ -0,0 +1,951 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + + +#include <string.h> +#include <limits.h> +#include <stdio.h> + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "./vpx_config.h" +#include "./vpx_dsp_rtcd.h" +#include "test/acm_random.h" +#include "test/clear_system_state.h" +#include "test/register_state_check.h" +#include "test/util.h" +#include "vpx/vpx_codec.h" +#include "vpx_mem/vpx_mem.h" +#include "vpx_ports/mem.h" + +typedef unsigned int (*SadMxNFunc)(const uint8_t *src_ptr, + int src_stride, + const uint8_t *ref_ptr, + int ref_stride); +typedef std::tr1::tuple<int, int, SadMxNFunc, int> SadMxNParam; + +typedef uint32_t (*SadMxNAvgFunc)(const uint8_t *src_ptr, + int src_stride, + const uint8_t *ref_ptr, + int ref_stride, + const uint8_t *second_pred); +typedef std::tr1::tuple<int, int, SadMxNAvgFunc, int> SadMxNAvgParam; + +typedef void (*SadMxNx4Func)(const uint8_t *src_ptr, + int src_stride, + const uint8_t *const ref_ptr[], + int ref_stride, + uint32_t *sad_array); +typedef std::tr1::tuple<int, int, SadMxNx4Func, int> SadMxNx4Param; + +using libvpx_test::ACMRandom; + +namespace { +class SADTestBase : public ::testing::Test { + public: + SADTestBase(int width, int height, int bit_depth) : + width_(width), height_(height), bd_(bit_depth) {} + + static void SetUpTestCase() { + source_data8_ = reinterpret_cast<uint8_t*>( + vpx_memalign(kDataAlignment, kDataBlockSize)); + reference_data8_ = reinterpret_cast<uint8_t*>( + vpx_memalign(kDataAlignment, kDataBufferSize)); + second_pred8_ = reinterpret_cast<uint8_t*>( + vpx_memalign(kDataAlignment, 64*64)); + source_data16_ = reinterpret_cast<uint16_t*>( + vpx_memalign(kDataAlignment, kDataBlockSize*sizeof(uint16_t))); + reference_data16_ = reinterpret_cast<uint16_t*>( + vpx_memalign(kDataAlignment, kDataBufferSize*sizeof(uint16_t))); + second_pred16_ = reinterpret_cast<uint16_t*>( + vpx_memalign(kDataAlignment, 64*64*sizeof(uint16_t))); + } + + static void TearDownTestCase() { + vpx_free(source_data8_); + source_data8_ = NULL; + vpx_free(reference_data8_); + reference_data8_ = NULL; + vpx_free(second_pred8_); + second_pred8_ = NULL; + vpx_free(source_data16_); + source_data16_ = NULL; + vpx_free(reference_data16_); + reference_data16_ = NULL; + vpx_free(second_pred16_); + second_pred16_ = NULL; + } + + virtual void TearDown() { + libvpx_test::ClearSystemState(); + } + + protected: + // Handle blocks up to 4 blocks 64x64 with stride up to 128 + static const int kDataAlignment = 16; + static const int kDataBlockSize = 64 * 128; + static const int kDataBufferSize = 4 * kDataBlockSize; + + virtual void SetUp() { + if (bd_ == -1) { + use_high_bit_depth_ = false; + bit_depth_ = VPX_BITS_8; + source_data_ = source_data8_; + reference_data_ = reference_data8_; + second_pred_ = second_pred8_; +#if CONFIG_VP9_HIGHBITDEPTH + } else { + use_high_bit_depth_ = true; + bit_depth_ = static_cast<vpx_bit_depth_t>(bd_); + source_data_ = CONVERT_TO_BYTEPTR(source_data16_); + reference_data_ = CONVERT_TO_BYTEPTR(reference_data16_); + second_pred_ = CONVERT_TO_BYTEPTR(second_pred16_); +#endif // CONFIG_VP9_HIGHBITDEPTH + } + mask_ = (1 << bit_depth_) - 1; + source_stride_ = (width_ + 31) & ~31; + reference_stride_ = width_ * 2; + rnd_.Reset(ACMRandom::DeterministicSeed()); + } + + virtual uint8_t *GetReference(int block_idx) { +#if CONFIG_VP9_HIGHBITDEPTH + if (use_high_bit_depth_) + return CONVERT_TO_BYTEPTR(CONVERT_TO_SHORTPTR(reference_data_) + + block_idx * kDataBlockSize); +#endif // CONFIG_VP9_HIGHBITDEPTH + return reference_data_ + block_idx * kDataBlockSize; + } + + // Sum of Absolute Differences. Given two blocks, calculate the absolute + // difference between two pixels in the same relative location; accumulate. + unsigned int ReferenceSAD(int block_idx) { + unsigned int sad = 0; + const uint8_t *const reference8 = GetReference(block_idx); + const uint8_t *const source8 = source_data_; +#if CONFIG_VP9_HIGHBITDEPTH + const uint16_t *const reference16 = + CONVERT_TO_SHORTPTR(GetReference(block_idx)); + const uint16_t *const source16 = CONVERT_TO_SHORTPTR(source_data_); +#endif // CONFIG_VP9_HIGHBITDEPTH + for (int h = 0; h < height_; ++h) { + for (int w = 0; w < width_; ++w) { + if (!use_high_bit_depth_) { + sad += abs(source8[h * source_stride_ + w] - + reference8[h * reference_stride_ + w]); +#if CONFIG_VP9_HIGHBITDEPTH + } else { + sad += abs(source16[h * source_stride_ + w] - + reference16[h * reference_stride_ + w]); +#endif // CONFIG_VP9_HIGHBITDEPTH + } + } + } + return sad; + } + + // Sum of Absolute Differences Average. Given two blocks, and a prediction + // calculate the absolute difference between one pixel and average of the + // corresponding and predicted pixels; accumulate. + unsigned int ReferenceSADavg(int block_idx) { + unsigned int sad = 0; + const uint8_t *const reference8 = GetReference(block_idx); + const uint8_t *const source8 = source_data_; + const uint8_t *const second_pred8 = second_pred_; +#if CONFIG_VP9_HIGHBITDEPTH + const uint16_t *const reference16 = + CONVERT_TO_SHORTPTR(GetReference(block_idx)); + const uint16_t *const source16 = CONVERT_TO_SHORTPTR(source_data_); + const uint16_t *const second_pred16 = CONVERT_TO_SHORTPTR(second_pred_); +#endif // CONFIG_VP9_HIGHBITDEPTH + for (int h = 0; h < height_; ++h) { + for (int w = 0; w < width_; ++w) { + if (!use_high_bit_depth_) { + const int tmp = second_pred8[h * width_ + w] + + reference8[h * reference_stride_ + w]; + const uint8_t comp_pred = ROUND_POWER_OF_TWO(tmp, 1); + sad += abs(source8[h * source_stride_ + w] - comp_pred); +#if CONFIG_VP9_HIGHBITDEPTH + } else { + const int tmp = second_pred16[h * width_ + w] + + reference16[h * reference_stride_ + w]; + const uint16_t comp_pred = ROUND_POWER_OF_TWO(tmp, 1); + sad += abs(source16[h * source_stride_ + w] - comp_pred); +#endif // CONFIG_VP9_HIGHBITDEPTH + } + } + } + return sad; + } + + void FillConstant(uint8_t *data, int stride, uint16_t fill_constant) { + uint8_t *data8 = data; +#if CONFIG_VP9_HIGHBITDEPTH + uint16_t *data16 = CONVERT_TO_SHORTPTR(data); +#endif // CONFIG_VP9_HIGHBITDEPTH + for (int h = 0; h < height_; ++h) { + for (int w = 0; w < width_; ++w) { + if (!use_high_bit_depth_) { + data8[h * stride + w] = static_cast<uint8_t>(fill_constant); +#if CONFIG_VP9_HIGHBITDEPTH + } else { + data16[h * stride + w] = fill_constant; +#endif // CONFIG_VP9_HIGHBITDEPTH + } + } + } + } + + void FillRandom(uint8_t *data, int stride) { + uint8_t *data8 = data; +#if CONFIG_VP9_HIGHBITDEPTH + uint16_t *data16 = CONVERT_TO_SHORTPTR(data); +#endif // CONFIG_VP9_HIGHBITDEPTH + for (int h = 0; h < height_; ++h) { + for (int w = 0; w < width_; ++w) { + if (!use_high_bit_depth_) { + data8[h * stride + w] = rnd_.Rand8(); +#if CONFIG_VP9_HIGHBITDEPTH + } else { + data16[h * stride + w] = rnd_.Rand16() & mask_; +#endif // CONFIG_VP9_HIGHBITDEPTH + } + } + } + } + + int width_, height_, mask_, bd_; + vpx_bit_depth_t bit_depth_; + static uint8_t *source_data_; + static uint8_t *reference_data_; + static uint8_t *second_pred_; + int source_stride_; + bool use_high_bit_depth_; + static uint8_t *source_data8_; + static uint8_t *reference_data8_; + static uint8_t *second_pred8_; + static uint16_t *source_data16_; + static uint16_t *reference_data16_; + static uint16_t *second_pred16_; + int reference_stride_; + + ACMRandom rnd_; +}; + +class SADx4Test + : public SADTestBase, + public ::testing::WithParamInterface<SadMxNx4Param> { + public: + SADx4Test() : SADTestBase(GET_PARAM(0), GET_PARAM(1), GET_PARAM(3)) {} + + protected: + void SADs(unsigned int *results) { + const uint8_t *references[] = {GetReference(0), GetReference(1), + GetReference(2), GetReference(3)}; + + ASM_REGISTER_STATE_CHECK(GET_PARAM(2)(source_data_, source_stride_, + references, reference_stride_, + results)); + } + + void CheckSADs() { + unsigned int reference_sad, exp_sad[4]; + + SADs(exp_sad); + for (int block = 0; block < 4; ++block) { + reference_sad = ReferenceSAD(block); + + EXPECT_EQ(reference_sad, exp_sad[block]) << "block " << block; + } + } +}; + +class SADTest + : public SADTestBase, + public ::testing::WithParamInterface<SadMxNParam> { + public: + SADTest() : SADTestBase(GET_PARAM(0), GET_PARAM(1), GET_PARAM(3)) {} + + protected: + unsigned int SAD(int block_idx) { + unsigned int ret; + const uint8_t *const reference = GetReference(block_idx); + + ASM_REGISTER_STATE_CHECK(ret = GET_PARAM(2)(source_data_, source_stride_, + reference, reference_stride_)); + return ret; + } + + void CheckSAD() { + const unsigned int reference_sad = ReferenceSAD(0); + const unsigned int exp_sad = SAD(0); + + ASSERT_EQ(reference_sad, exp_sad); + } +}; + +class SADavgTest + : public SADTestBase, + public ::testing::WithParamInterface<SadMxNAvgParam> { + public: + SADavgTest() : SADTestBase(GET_PARAM(0), GET_PARAM(1), GET_PARAM(3)) {} + + protected: + unsigned int SAD_avg(int block_idx) { + unsigned int ret; + const uint8_t *const reference = GetReference(block_idx); + + ASM_REGISTER_STATE_CHECK(ret = GET_PARAM(2)(source_data_, source_stride_, + reference, reference_stride_, + second_pred_)); + return ret; + } + + void CheckSAD() { + const unsigned int reference_sad = ReferenceSADavg(0); + const unsigned int exp_sad = SAD_avg(0); + + ASSERT_EQ(reference_sad, exp_sad); + } +}; + +uint8_t *SADTestBase::source_data_ = NULL; +uint8_t *SADTestBase::reference_data_ = NULL; +uint8_t *SADTestBase::second_pred_ = NULL; +uint8_t *SADTestBase::source_data8_ = NULL; +uint8_t *SADTestBase::reference_data8_ = NULL; +uint8_t *SADTestBase::second_pred8_ = NULL; +uint16_t *SADTestBase::source_data16_ = NULL; +uint16_t *SADTestBase::reference_data16_ = NULL; +uint16_t *SADTestBase::second_pred16_ = NULL; + +TEST_P(SADTest, MaxRef) { + FillConstant(source_data_, source_stride_, 0); + FillConstant(reference_data_, reference_stride_, mask_); + CheckSAD(); +} + +TEST_P(SADTest, MaxSrc) { + FillConstant(source_data_, source_stride_, mask_); + FillConstant(reference_data_, reference_stride_, 0); + CheckSAD(); +} + +TEST_P(SADTest, ShortRef) { + const int tmp_stride = reference_stride_; + reference_stride_ >>= 1; + FillRandom(source_data_, source_stride_); + FillRandom(reference_data_, reference_stride_); + CheckSAD(); + reference_stride_ = tmp_stride; +} + +TEST_P(SADTest, UnalignedRef) { + // The reference frame, but not the source frame, may be unaligned for + // certain types of searches. + const int tmp_stride = reference_stride_; + reference_stride_ -= 1; + FillRandom(source_data_, source_stride_); + FillRandom(reference_data_, reference_stride_); + CheckSAD(); + reference_stride_ = tmp_stride; +} + +TEST_P(SADTest, ShortSrc) { + const int tmp_stride = source_stride_; + source_stride_ >>= 1; + FillRandom(source_data_, source_stride_); + FillRandom(reference_data_, reference_stride_); + CheckSAD(); + source_stride_ = tmp_stride; +} + +TEST_P(SADavgTest, MaxRef) { + FillConstant(source_data_, source_stride_, 0); + FillConstant(reference_data_, reference_stride_, mask_); + FillConstant(second_pred_, width_, 0); + CheckSAD(); +} +TEST_P(SADavgTest, MaxSrc) { + FillConstant(source_data_, source_stride_, mask_); + FillConstant(reference_data_, reference_stride_, 0); + FillConstant(second_pred_, width_, 0); + CheckSAD(); +} + +TEST_P(SADavgTest, ShortRef) { + const int tmp_stride = reference_stride_; + reference_stride_ >>= 1; + FillRandom(source_data_, source_stride_); + FillRandom(reference_data_, reference_stride_); + FillRandom(second_pred_, width_); + CheckSAD(); + reference_stride_ = tmp_stride; +} + +TEST_P(SADavgTest, UnalignedRef) { + // The reference frame, but not the source frame, may be unaligned for + // certain types of searches. + const int tmp_stride = reference_stride_; + reference_stride_ -= 1; + FillRandom(source_data_, source_stride_); + FillRandom(reference_data_, reference_stride_); + FillRandom(second_pred_, width_); + CheckSAD(); + reference_stride_ = tmp_stride; +} + +TEST_P(SADavgTest, ShortSrc) { + const int tmp_stride = source_stride_; + source_stride_ >>= 1; + FillRandom(source_data_, source_stride_); + FillRandom(reference_data_, reference_stride_); + FillRandom(second_pred_, width_); + CheckSAD(); + source_stride_ = tmp_stride; +} + +TEST_P(SADx4Test, MaxRef) { + FillConstant(source_data_, source_stride_, 0); + FillConstant(GetReference(0), reference_stride_, mask_); + FillConstant(GetReference(1), reference_stride_, mask_); + FillConstant(GetReference(2), reference_stride_, mask_); + FillConstant(GetReference(3), reference_stride_, mask_); + CheckSADs(); +} + +TEST_P(SADx4Test, MaxSrc) { + FillConstant(source_data_, source_stride_, mask_); + FillConstant(GetReference(0), reference_stride_, 0); + FillConstant(GetReference(1), reference_stride_, 0); + FillConstant(GetReference(2), reference_stride_, 0); + FillConstant(GetReference(3), reference_stride_, 0); + CheckSADs(); +} + +TEST_P(SADx4Test, ShortRef) { + int tmp_stride = reference_stride_; + reference_stride_ >>= 1; + FillRandom(source_data_, source_stride_); + FillRandom(GetReference(0), reference_stride_); + FillRandom(GetReference(1), reference_stride_); + FillRandom(GetReference(2), reference_stride_); + FillRandom(GetReference(3), reference_stride_); + CheckSADs(); + reference_stride_ = tmp_stride; +} + +TEST_P(SADx4Test, UnalignedRef) { + // The reference frame, but not the source frame, may be unaligned for + // certain types of searches. + int tmp_stride = reference_stride_; + reference_stride_ -= 1; + FillRandom(source_data_, source_stride_); + FillRandom(GetReference(0), reference_stride_); + FillRandom(GetReference(1), reference_stride_); + FillRandom(GetReference(2), reference_stride_); + FillRandom(GetReference(3), reference_stride_); + CheckSADs(); + reference_stride_ = tmp_stride; +} + +TEST_P(SADx4Test, ShortSrc) { + int tmp_stride = source_stride_; + source_stride_ >>= 1; + FillRandom(source_data_, source_stride_); + FillRandom(GetReference(0), reference_stride_); + FillRandom(GetReference(1), reference_stride_); + FillRandom(GetReference(2), reference_stride_); + FillRandom(GetReference(3), reference_stride_); + CheckSADs(); + source_stride_ = tmp_stride; +} + +TEST_P(SADx4Test, SrcAlignedByWidth) { + uint8_t * tmp_source_data = source_data_; + source_data_ += width_; + FillRandom(source_data_, source_stride_); + FillRandom(GetReference(0), reference_stride_); + FillRandom(GetReference(1), reference_stride_); + FillRandom(GetReference(2), reference_stride_); + FillRandom(GetReference(3), reference_stride_); + CheckSADs(); + source_data_ = tmp_source_data; +} + +using std::tr1::make_tuple; + +//------------------------------------------------------------------------------ +// C functions +const SadMxNParam c_tests[] = { + make_tuple(64, 64, &vpx_sad64x64_c, -1), + make_tuple(64, 32, &vpx_sad64x32_c, -1), + make_tuple(32, 64, &vpx_sad32x64_c, -1), + make_tuple(32, 32, &vpx_sad32x32_c, -1), + make_tuple(32, 16, &vpx_sad32x16_c, -1), + make_tuple(16, 32, &vpx_sad16x32_c, -1), + make_tuple(16, 16, &vpx_sad16x16_c, -1), + make_tuple(16, 8, &vpx_sad16x8_c, -1), + make_tuple(8, 16, &vpx_sad8x16_c, -1), + make_tuple(8, 8, &vpx_sad8x8_c, -1), + make_tuple(8, 4, &vpx_sad8x4_c, -1), + make_tuple(4, 8, &vpx_sad4x8_c, -1), + make_tuple(4, 4, &vpx_sad4x4_c, -1), +#if CONFIG_VP9_HIGHBITDEPTH + make_tuple(64, 64, &vpx_highbd_sad64x64_c, 8), + make_tuple(64, 32, &vpx_highbd_sad64x32_c, 8), + make_tuple(32, 64, &vpx_highbd_sad32x64_c, 8), + make_tuple(32, 32, &vpx_highbd_sad32x32_c, 8), + make_tuple(32, 16, &vpx_highbd_sad32x16_c, 8), + make_tuple(16, 32, &vpx_highbd_sad16x32_c, 8), + make_tuple(16, 16, &vpx_highbd_sad16x16_c, 8), + make_tuple(16, 8, &vpx_highbd_sad16x8_c, 8), + make_tuple(8, 16, &vpx_highbd_sad8x16_c, 8), + make_tuple(8, 8, &vpx_highbd_sad8x8_c, 8), + make_tuple(8, 4, &vpx_highbd_sad8x4_c, 8), + make_tuple(4, 8, &vpx_highbd_sad4x8_c, 8), + make_tuple(4, 4, &vpx_highbd_sad4x4_c, 8), + make_tuple(64, 64, &vpx_highbd_sad64x64_c, 10), + make_tuple(64, 32, &vpx_highbd_sad64x32_c, 10), + make_tuple(32, 64, &vpx_highbd_sad32x64_c, 10), + make_tuple(32, 32, &vpx_highbd_sad32x32_c, 10), + make_tuple(32, 16, &vpx_highbd_sad32x16_c, 10), + make_tuple(16, 32, &vpx_highbd_sad16x32_c, 10), + make_tuple(16, 16, &vpx_highbd_sad16x16_c, 10), + make_tuple(16, 8, &vpx_highbd_sad16x8_c, 10), + make_tuple(8, 16, &vpx_highbd_sad8x16_c, 10), + make_tuple(8, 8, &vpx_highbd_sad8x8_c, 10), + make_tuple(8, 4, &vpx_highbd_sad8x4_c, 10), + make_tuple(4, 8, &vpx_highbd_sad4x8_c, 10), + make_tuple(4, 4, &vpx_highbd_sad4x4_c, 10), + make_tuple(64, 64, &vpx_highbd_sad64x64_c, 12), + make_tuple(64, 32, &vpx_highbd_sad64x32_c, 12), + make_tuple(32, 64, &vpx_highbd_sad32x64_c, 12), + make_tuple(32, 32, &vpx_highbd_sad32x32_c, 12), + make_tuple(32, 16, &vpx_highbd_sad32x16_c, 12), + make_tuple(16, 32, &vpx_highbd_sad16x32_c, 12), + make_tuple(16, 16, &vpx_highbd_sad16x16_c, 12), + make_tuple(16, 8, &vpx_highbd_sad16x8_c, 12), + make_tuple(8, 16, &vpx_highbd_sad8x16_c, 12), + make_tuple(8, 8, &vpx_highbd_sad8x8_c, 12), + make_tuple(8, 4, &vpx_highbd_sad8x4_c, 12), + make_tuple(4, 8, &vpx_highbd_sad4x8_c, 12), + make_tuple(4, 4, &vpx_highbd_sad4x4_c, 12), +#endif // CONFIG_VP9_HIGHBITDEPTH +}; +INSTANTIATE_TEST_CASE_P(C, SADTest, ::testing::ValuesIn(c_tests)); + +const SadMxNAvgParam avg_c_tests[] = { + make_tuple(64, 64, &vpx_sad64x64_avg_c, -1), + make_tuple(64, 32, &vpx_sad64x32_avg_c, -1), + make_tuple(32, 64, &vpx_sad32x64_avg_c, -1), + make_tuple(32, 32, &vpx_sad32x32_avg_c, -1), + make_tuple(32, 16, &vpx_sad32x16_avg_c, -1), + make_tuple(16, 32, &vpx_sad16x32_avg_c, -1), + make_tuple(16, 16, &vpx_sad16x16_avg_c, -1), + make_tuple(16, 8, &vpx_sad16x8_avg_c, -1), + make_tuple(8, 16, &vpx_sad8x16_avg_c, -1), + make_tuple(8, 8, &vpx_sad8x8_avg_c, -1), + make_tuple(8, 4, &vpx_sad8x4_avg_c, -1), + make_tuple(4, 8, &vpx_sad4x8_avg_c, -1), + make_tuple(4, 4, &vpx_sad4x4_avg_c, -1), +#if CONFIG_VP9_HIGHBITDEPTH + make_tuple(64, 64, &vpx_highbd_sad64x64_avg_c, 8), + make_tuple(64, 32, &vpx_highbd_sad64x32_avg_c, 8), + make_tuple(32, 64, &vpx_highbd_sad32x64_avg_c, 8), + make_tuple(32, 32, &vpx_highbd_sad32x32_avg_c, 8), + make_tuple(32, 16, &vpx_highbd_sad32x16_avg_c, 8), + make_tuple(16, 32, &vpx_highbd_sad16x32_avg_c, 8), + make_tuple(16, 16, &vpx_highbd_sad16x16_avg_c, 8), + make_tuple(16, 8, &vpx_highbd_sad16x8_avg_c, 8), + make_tuple(8, 16, &vpx_highbd_sad8x16_avg_c, 8), + make_tuple(8, 8, &vpx_highbd_sad8x8_avg_c, 8), + make_tuple(8, 4, &vpx_highbd_sad8x4_avg_c, 8), + make_tuple(4, 8, &vpx_highbd_sad4x8_avg_c, 8), + make_tuple(4, 4, &vpx_highbd_sad4x4_avg_c, 8), + make_tuple(64, 64, &vpx_highbd_sad64x64_avg_c, 10), + make_tuple(64, 32, &vpx_highbd_sad64x32_avg_c, 10), + make_tuple(32, 64, &vpx_highbd_sad32x64_avg_c, 10), + make_tuple(32, 32, &vpx_highbd_sad32x32_avg_c, 10), + make_tuple(32, 16, &vpx_highbd_sad32x16_avg_c, 10), + make_tuple(16, 32, &vpx_highbd_sad16x32_avg_c, 10), + make_tuple(16, 16, &vpx_highbd_sad16x16_avg_c, 10), + make_tuple(16, 8, &vpx_highbd_sad16x8_avg_c, 10), + make_tuple(8, 16, &vpx_highbd_sad8x16_avg_c, 10), + make_tuple(8, 8, &vpx_highbd_sad8x8_avg_c, 10), + make_tuple(8, 4, &vpx_highbd_sad8x4_avg_c, 10), + make_tuple(4, 8, &vpx_highbd_sad4x8_avg_c, 10), + make_tuple(4, 4, &vpx_highbd_sad4x4_avg_c, 10), + make_tuple(64, 64, &vpx_highbd_sad64x64_avg_c, 12), + make_tuple(64, 32, &vpx_highbd_sad64x32_avg_c, 12), + make_tuple(32, 64, &vpx_highbd_sad32x64_avg_c, 12), + make_tuple(32, 32, &vpx_highbd_sad32x32_avg_c, 12), + make_tuple(32, 16, &vpx_highbd_sad32x16_avg_c, 12), + make_tuple(16, 32, &vpx_highbd_sad16x32_avg_c, 12), + make_tuple(16, 16, &vpx_highbd_sad16x16_avg_c, 12), + make_tuple(16, 8, &vpx_highbd_sad16x8_avg_c, 12), + make_tuple(8, 16, &vpx_highbd_sad8x16_avg_c, 12), + make_tuple(8, 8, &vpx_highbd_sad8x8_avg_c, 12), + make_tuple(8, 4, &vpx_highbd_sad8x4_avg_c, 12), + make_tuple(4, 8, &vpx_highbd_sad4x8_avg_c, 12), + make_tuple(4, 4, &vpx_highbd_sad4x4_avg_c, 12), +#endif // CONFIG_VP9_HIGHBITDEPTH +}; +INSTANTIATE_TEST_CASE_P(C, SADavgTest, ::testing::ValuesIn(avg_c_tests)); + +const SadMxNx4Param x4d_c_tests[] = { + make_tuple(64, 64, &vpx_sad64x64x4d_c, -1), + make_tuple(64, 32, &vpx_sad64x32x4d_c, -1), + make_tuple(32, 64, &vpx_sad32x64x4d_c, -1), + make_tuple(32, 32, &vpx_sad32x32x4d_c, -1), + make_tuple(32, 16, &vpx_sad32x16x4d_c, -1), + make_tuple(16, 32, &vpx_sad16x32x4d_c, -1), + make_tuple(16, 16, &vpx_sad16x16x4d_c, -1), + make_tuple(16, 8, &vpx_sad16x8x4d_c, -1), + make_tuple(8, 16, &vpx_sad8x16x4d_c, -1), + make_tuple(8, 8, &vpx_sad8x8x4d_c, -1), + make_tuple(8, 4, &vpx_sad8x4x4d_c, -1), + make_tuple(4, 8, &vpx_sad4x8x4d_c, -1), + make_tuple(4, 4, &vpx_sad4x4x4d_c, -1), +#if CONFIG_VP9_HIGHBITDEPTH + make_tuple(64, 64, &vpx_highbd_sad64x64x4d_c, 8), + make_tuple(64, 32, &vpx_highbd_sad64x32x4d_c, 8), + make_tuple(32, 64, &vpx_highbd_sad32x64x4d_c, 8), + make_tuple(32, 32, &vpx_highbd_sad32x32x4d_c, 8), + make_tuple(32, 16, &vpx_highbd_sad32x16x4d_c, 8), + make_tuple(16, 32, &vpx_highbd_sad16x32x4d_c, 8), + make_tuple(16, 16, &vpx_highbd_sad16x16x4d_c, 8), + make_tuple(16, 8, &vpx_highbd_sad16x8x4d_c, 8), + make_tuple(8, 16, &vpx_highbd_sad8x16x4d_c, 8), + make_tuple(8, 8, &vpx_highbd_sad8x8x4d_c, 8), + make_tuple(8, 4, &vpx_highbd_sad8x4x4d_c, 8), + make_tuple(4, 8, &vpx_highbd_sad4x8x4d_c, 8), + make_tuple(4, 4, &vpx_highbd_sad4x4x4d_c, 8), + make_tuple(64, 64, &vpx_highbd_sad64x64x4d_c, 10), + make_tuple(64, 32, &vpx_highbd_sad64x32x4d_c, 10), + make_tuple(32, 64, &vpx_highbd_sad32x64x4d_c, 10), + make_tuple(32, 32, &vpx_highbd_sad32x32x4d_c, 10), + make_tuple(32, 16, &vpx_highbd_sad32x16x4d_c, 10), + make_tuple(16, 32, &vpx_highbd_sad16x32x4d_c, 10), + make_tuple(16, 16, &vpx_highbd_sad16x16x4d_c, 10), + make_tuple(16, 8, &vpx_highbd_sad16x8x4d_c, 10), + make_tuple(8, 16, &vpx_highbd_sad8x16x4d_c, 10), + make_tuple(8, 8, &vpx_highbd_sad8x8x4d_c, 10), + make_tuple(8, 4, &vpx_highbd_sad8x4x4d_c, 10), + make_tuple(4, 8, &vpx_highbd_sad4x8x4d_c, 10), + make_tuple(4, 4, &vpx_highbd_sad4x4x4d_c, 10), + make_tuple(64, 64, &vpx_highbd_sad64x64x4d_c, 12), + make_tuple(64, 32, &vpx_highbd_sad64x32x4d_c, 12), + make_tuple(32, 64, &vpx_highbd_sad32x64x4d_c, 12), + make_tuple(32, 32, &vpx_highbd_sad32x32x4d_c, 12), + make_tuple(32, 16, &vpx_highbd_sad32x16x4d_c, 12), + make_tuple(16, 32, &vpx_highbd_sad16x32x4d_c, 12), + make_tuple(16, 16, &vpx_highbd_sad16x16x4d_c, 12), + make_tuple(16, 8, &vpx_highbd_sad16x8x4d_c, 12), + make_tuple(8, 16, &vpx_highbd_sad8x16x4d_c, 12), + make_tuple(8, 8, &vpx_highbd_sad8x8x4d_c, 12), + make_tuple(8, 4, &vpx_highbd_sad8x4x4d_c, 12), + make_tuple(4, 8, &vpx_highbd_sad4x8x4d_c, 12), + make_tuple(4, 4, &vpx_highbd_sad4x4x4d_c, 12), +#endif // CONFIG_VP9_HIGHBITDEPTH +}; +INSTANTIATE_TEST_CASE_P(C, SADx4Test, ::testing::ValuesIn(x4d_c_tests)); + +//------------------------------------------------------------------------------ +// ARM functions +#if HAVE_MEDIA +const SadMxNParam media_tests[] = { + make_tuple(16, 16, &vpx_sad16x16_media, -1), +}; +INSTANTIATE_TEST_CASE_P(MEDIA, SADTest, ::testing::ValuesIn(media_tests)); +#endif // HAVE_MEDIA + +#if HAVE_NEON +const SadMxNParam neon_tests[] = { + make_tuple(64, 64, &vpx_sad64x64_neon, -1), + make_tuple(32, 32, &vpx_sad32x32_neon, -1), + make_tuple(16, 16, &vpx_sad16x16_neon, -1), + make_tuple(16, 8, &vpx_sad16x8_neon, -1), + make_tuple(8, 16, &vpx_sad8x16_neon, -1), + make_tuple(8, 8, &vpx_sad8x8_neon, -1), + make_tuple(4, 4, &vpx_sad4x4_neon, -1), +}; +INSTANTIATE_TEST_CASE_P(NEON, SADTest, ::testing::ValuesIn(neon_tests)); + +const SadMxNx4Param x4d_neon_tests[] = { + make_tuple(64, 64, &vpx_sad64x64x4d_neon, -1), + make_tuple(32, 32, &vpx_sad32x32x4d_neon, -1), + make_tuple(16, 16, &vpx_sad16x16x4d_neon, -1), +}; +INSTANTIATE_TEST_CASE_P(NEON, SADx4Test, ::testing::ValuesIn(x4d_neon_tests)); +#endif // HAVE_NEON + +//------------------------------------------------------------------------------ +// x86 functions +#if HAVE_SSE2 +#if CONFIG_USE_X86INC +const SadMxNParam sse2_tests[] = { + make_tuple(64, 64, &vpx_sad64x64_sse2, -1), + make_tuple(64, 32, &vpx_sad64x32_sse2, -1), + make_tuple(32, 64, &vpx_sad32x64_sse2, -1), + make_tuple(32, 32, &vpx_sad32x32_sse2, -1), + make_tuple(32, 16, &vpx_sad32x16_sse2, -1), + make_tuple(16, 32, &vpx_sad16x32_sse2, -1), + make_tuple(16, 16, &vpx_sad16x16_sse2, -1), + make_tuple(16, 8, &vpx_sad16x8_sse2, -1), + make_tuple(8, 16, &vpx_sad8x16_sse2, -1), + make_tuple(8, 8, &vpx_sad8x8_sse2, -1), + make_tuple(8, 4, &vpx_sad8x4_sse2, -1), + make_tuple(4, 8, &vpx_sad4x8_sse2, -1), + make_tuple(4, 4, &vpx_sad4x4_sse2, -1), +#if CONFIG_VP9_HIGHBITDEPTH + make_tuple(64, 64, &vpx_highbd_sad64x64_sse2, 8), + make_tuple(64, 32, &vpx_highbd_sad64x32_sse2, 8), + make_tuple(32, 64, &vpx_highbd_sad32x64_sse2, 8), + make_tuple(32, 32, &vpx_highbd_sad32x32_sse2, 8), + make_tuple(32, 16, &vpx_highbd_sad32x16_sse2, 8), + make_tuple(16, 32, &vpx_highbd_sad16x32_sse2, 8), + make_tuple(16, 16, &vpx_highbd_sad16x16_sse2, 8), + make_tuple(16, 8, &vpx_highbd_sad16x8_sse2, 8), + make_tuple(8, 16, &vpx_highbd_sad8x16_sse2, 8), + make_tuple(8, 8, &vpx_highbd_sad8x8_sse2, 8), + make_tuple(8, 4, &vpx_highbd_sad8x4_sse2, 8), + make_tuple(64, 64, &vpx_highbd_sad64x64_sse2, 10), + make_tuple(64, 32, &vpx_highbd_sad64x32_sse2, 10), + make_tuple(32, 64, &vpx_highbd_sad32x64_sse2, 10), + make_tuple(32, 32, &vpx_highbd_sad32x32_sse2, 10), + make_tuple(32, 16, &vpx_highbd_sad32x16_sse2, 10), + make_tuple(16, 32, &vpx_highbd_sad16x32_sse2, 10), + make_tuple(16, 16, &vpx_highbd_sad16x16_sse2, 10), + make_tuple(16, 8, &vpx_highbd_sad16x8_sse2, 10), + make_tuple(8, 16, &vpx_highbd_sad8x16_sse2, 10), + make_tuple(8, 8, &vpx_highbd_sad8x8_sse2, 10), + make_tuple(8, 4, &vpx_highbd_sad8x4_sse2, 10), + make_tuple(64, 64, &vpx_highbd_sad64x64_sse2, 12), + make_tuple(64, 32, &vpx_highbd_sad64x32_sse2, 12), + make_tuple(32, 64, &vpx_highbd_sad32x64_sse2, 12), + make_tuple(32, 32, &vpx_highbd_sad32x32_sse2, 12), + make_tuple(32, 16, &vpx_highbd_sad32x16_sse2, 12), + make_tuple(16, 32, &vpx_highbd_sad16x32_sse2, 12), + make_tuple(16, 16, &vpx_highbd_sad16x16_sse2, 12), + make_tuple(16, 8, &vpx_highbd_sad16x8_sse2, 12), + make_tuple(8, 16, &vpx_highbd_sad8x16_sse2, 12), + make_tuple(8, 8, &vpx_highbd_sad8x8_sse2, 12), + make_tuple(8, 4, &vpx_highbd_sad8x4_sse2, 12), +#endif // CONFIG_VP9_HIGHBITDEPTH +}; +INSTANTIATE_TEST_CASE_P(SSE2, SADTest, ::testing::ValuesIn(sse2_tests)); + +const SadMxNAvgParam avg_sse2_tests[] = { + make_tuple(64, 64, &vpx_sad64x64_avg_sse2, -1), + make_tuple(64, 32, &vpx_sad64x32_avg_sse2, -1), + make_tuple(32, 64, &vpx_sad32x64_avg_sse2, -1), + make_tuple(32, 32, &vpx_sad32x32_avg_sse2, -1), + make_tuple(32, 16, &vpx_sad32x16_avg_sse2, -1), + make_tuple(16, 32, &vpx_sad16x32_avg_sse2, -1), + make_tuple(16, 16, &vpx_sad16x16_avg_sse2, -1), + make_tuple(16, 8, &vpx_sad16x8_avg_sse2, -1), + make_tuple(8, 16, &vpx_sad8x16_avg_sse2, -1), + make_tuple(8, 8, &vpx_sad8x8_avg_sse2, -1), + make_tuple(8, 4, &vpx_sad8x4_avg_sse2, -1), + make_tuple(4, 8, &vpx_sad4x8_avg_sse2, -1), + make_tuple(4, 4, &vpx_sad4x4_avg_sse2, -1), +#if CONFIG_VP9_HIGHBITDEPTH + make_tuple(64, 64, &vpx_highbd_sad64x64_avg_sse2, 8), + make_tuple(64, 32, &vpx_highbd_sad64x32_avg_sse2, 8), + make_tuple(32, 64, &vpx_highbd_sad32x64_avg_sse2, 8), + make_tuple(32, 32, &vpx_highbd_sad32x32_avg_sse2, 8), + make_tuple(32, 16, &vpx_highbd_sad32x16_avg_sse2, 8), + make_tuple(16, 32, &vpx_highbd_sad16x32_avg_sse2, 8), + make_tuple(16, 16, &vpx_highbd_sad16x16_avg_sse2, 8), + make_tuple(16, 8, &vpx_highbd_sad16x8_avg_sse2, 8), + make_tuple(8, 16, &vpx_highbd_sad8x16_avg_sse2, 8), + make_tuple(8, 8, &vpx_highbd_sad8x8_avg_sse2, 8), + make_tuple(8, 4, &vpx_highbd_sad8x4_avg_sse2, 8), + make_tuple(64, 64, &vpx_highbd_sad64x64_avg_sse2, 10), + make_tuple(64, 32, &vpx_highbd_sad64x32_avg_sse2, 10), + make_tuple(32, 64, &vpx_highbd_sad32x64_avg_sse2, 10), + make_tuple(32, 32, &vpx_highbd_sad32x32_avg_sse2, 10), + make_tuple(32, 16, &vpx_highbd_sad32x16_avg_sse2, 10), + make_tuple(16, 32, &vpx_highbd_sad16x32_avg_sse2, 10), + make_tuple(16, 16, &vpx_highbd_sad16x16_avg_sse2, 10), + make_tuple(16, 8, &vpx_highbd_sad16x8_avg_sse2, 10), + make_tuple(8, 16, &vpx_highbd_sad8x16_avg_sse2, 10), + make_tuple(8, 8, &vpx_highbd_sad8x8_avg_sse2, 10), + make_tuple(8, 4, &vpx_highbd_sad8x4_avg_sse2, 10), + make_tuple(64, 64, &vpx_highbd_sad64x64_avg_sse2, 12), + make_tuple(64, 32, &vpx_highbd_sad64x32_avg_sse2, 12), + make_tuple(32, 64, &vpx_highbd_sad32x64_avg_sse2, 12), + make_tuple(32, 32, &vpx_highbd_sad32x32_avg_sse2, 12), + make_tuple(32, 16, &vpx_highbd_sad32x16_avg_sse2, 12), + make_tuple(16, 32, &vpx_highbd_sad16x32_avg_sse2, 12), + make_tuple(16, 16, &vpx_highbd_sad16x16_avg_sse2, 12), + make_tuple(16, 8, &vpx_highbd_sad16x8_avg_sse2, 12), + make_tuple(8, 16, &vpx_highbd_sad8x16_avg_sse2, 12), + make_tuple(8, 8, &vpx_highbd_sad8x8_avg_sse2, 12), + make_tuple(8, 4, &vpx_highbd_sad8x4_avg_sse2, 12), +#endif // CONFIG_VP9_HIGHBITDEPTH +}; +INSTANTIATE_TEST_CASE_P(SSE2, SADavgTest, ::testing::ValuesIn(avg_sse2_tests)); + +const SadMxNx4Param x4d_sse2_tests[] = { + make_tuple(64, 64, &vpx_sad64x64x4d_sse2, -1), + make_tuple(64, 32, &vpx_sad64x32x4d_sse2, -1), + make_tuple(32, 64, &vpx_sad32x64x4d_sse2, -1), + make_tuple(32, 32, &vpx_sad32x32x4d_sse2, -1), + make_tuple(32, 16, &vpx_sad32x16x4d_sse2, -1), + make_tuple(16, 32, &vpx_sad16x32x4d_sse2, -1), + make_tuple(16, 16, &vpx_sad16x16x4d_sse2, -1), + make_tuple(16, 8, &vpx_sad16x8x4d_sse2, -1), + make_tuple(8, 16, &vpx_sad8x16x4d_sse2, -1), + make_tuple(8, 8, &vpx_sad8x8x4d_sse2, -1), + make_tuple(8, 4, &vpx_sad8x4x4d_sse2, -1), + make_tuple(4, 8, &vpx_sad4x8x4d_sse2, -1), + make_tuple(4, 4, &vpx_sad4x4x4d_sse2, -1), +#if CONFIG_VP9_HIGHBITDEPTH + make_tuple(64, 64, &vpx_highbd_sad64x64x4d_sse2, 8), + make_tuple(64, 32, &vpx_highbd_sad64x32x4d_sse2, 8), + make_tuple(32, 64, &vpx_highbd_sad32x64x4d_sse2, 8), + make_tuple(32, 32, &vpx_highbd_sad32x32x4d_sse2, 8), + make_tuple(32, 16, &vpx_highbd_sad32x16x4d_sse2, 8), + make_tuple(16, 32, &vpx_highbd_sad16x32x4d_sse2, 8), + make_tuple(16, 16, &vpx_highbd_sad16x16x4d_sse2, 8), + make_tuple(16, 8, &vpx_highbd_sad16x8x4d_sse2, 8), + make_tuple(8, 16, &vpx_highbd_sad8x16x4d_sse2, 8), + make_tuple(8, 8, &vpx_highbd_sad8x8x4d_sse2, 8), + make_tuple(8, 4, &vpx_highbd_sad8x4x4d_sse2, 8), + make_tuple(4, 8, &vpx_highbd_sad4x8x4d_sse2, 8), + make_tuple(4, 4, &vpx_highbd_sad4x4x4d_sse2, 8), + make_tuple(64, 64, &vpx_highbd_sad64x64x4d_sse2, 10), + make_tuple(64, 32, &vpx_highbd_sad64x32x4d_sse2, 10), + make_tuple(32, 64, &vpx_highbd_sad32x64x4d_sse2, 10), + make_tuple(32, 32, &vpx_highbd_sad32x32x4d_sse2, 10), + make_tuple(32, 16, &vpx_highbd_sad32x16x4d_sse2, 10), + make_tuple(16, 32, &vpx_highbd_sad16x32x4d_sse2, 10), + make_tuple(16, 16, &vpx_highbd_sad16x16x4d_sse2, 10), + make_tuple(16, 8, &vpx_highbd_sad16x8x4d_sse2, 10), + make_tuple(8, 16, &vpx_highbd_sad8x16x4d_sse2, 10), + make_tuple(8, 8, &vpx_highbd_sad8x8x4d_sse2, 10), + make_tuple(8, 4, &vpx_highbd_sad8x4x4d_sse2, 10), + make_tuple(4, 8, &vpx_highbd_sad4x8x4d_sse2, 10), + make_tuple(4, 4, &vpx_highbd_sad4x4x4d_sse2, 10), + make_tuple(64, 64, &vpx_highbd_sad64x64x4d_sse2, 12), + make_tuple(64, 32, &vpx_highbd_sad64x32x4d_sse2, 12), + make_tuple(32, 64, &vpx_highbd_sad32x64x4d_sse2, 12), + make_tuple(32, 32, &vpx_highbd_sad32x32x4d_sse2, 12), + make_tuple(32, 16, &vpx_highbd_sad32x16x4d_sse2, 12), + make_tuple(16, 32, &vpx_highbd_sad16x32x4d_sse2, 12), + make_tuple(16, 16, &vpx_highbd_sad16x16x4d_sse2, 12), + make_tuple(16, 8, &vpx_highbd_sad16x8x4d_sse2, 12), + make_tuple(8, 16, &vpx_highbd_sad8x16x4d_sse2, 12), + make_tuple(8, 8, &vpx_highbd_sad8x8x4d_sse2, 12), + make_tuple(8, 4, &vpx_highbd_sad8x4x4d_sse2, 12), + make_tuple(4, 8, &vpx_highbd_sad4x8x4d_sse2, 12), + make_tuple(4, 4, &vpx_highbd_sad4x4x4d_sse2, 12), +#endif // CONFIG_VP9_HIGHBITDEPTH +}; +INSTANTIATE_TEST_CASE_P(SSE2, SADx4Test, ::testing::ValuesIn(x4d_sse2_tests)); +#endif // CONFIG_USE_X86INC +#endif // HAVE_SSE2 + +#if HAVE_SSE3 +// Only functions are x3, which do not have tests. +#endif // HAVE_SSE3 + +#if HAVE_SSSE3 +// Only functions are x3, which do not have tests. +#endif // HAVE_SSSE3 + +#if HAVE_SSE4_1 +// Only functions are x8, which do not have tests. +#endif // HAVE_SSE4_1 + +#if HAVE_AVX2 +const SadMxNParam avx2_tests[] = { + make_tuple(64, 64, &vpx_sad64x64_avx2, -1), + make_tuple(64, 32, &vpx_sad64x32_avx2, -1), + make_tuple(32, 64, &vpx_sad32x64_avx2, -1), + make_tuple(32, 32, &vpx_sad32x32_avx2, -1), + make_tuple(32, 16, &vpx_sad32x16_avx2, -1), +}; +INSTANTIATE_TEST_CASE_P(AVX2, SADTest, ::testing::ValuesIn(avx2_tests)); + +const SadMxNAvgParam avg_avx2_tests[] = { + make_tuple(64, 64, &vpx_sad64x64_avg_avx2, -1), + make_tuple(64, 32, &vpx_sad64x32_avg_avx2, -1), + make_tuple(32, 64, &vpx_sad32x64_avg_avx2, -1), + make_tuple(32, 32, &vpx_sad32x32_avg_avx2, -1), + make_tuple(32, 16, &vpx_sad32x16_avg_avx2, -1), +}; +INSTANTIATE_TEST_CASE_P(AVX2, SADavgTest, ::testing::ValuesIn(avg_avx2_tests)); + +const SadMxNx4Param x4d_avx2_tests[] = { + make_tuple(64, 64, &vpx_sad64x64x4d_avx2, -1), + make_tuple(32, 32, &vpx_sad32x32x4d_avx2, -1), +}; +INSTANTIATE_TEST_CASE_P(AVX2, SADx4Test, ::testing::ValuesIn(x4d_avx2_tests)); +#endif // HAVE_AVX2 + +//------------------------------------------------------------------------------ +// MIPS functions +#if HAVE_MSA +const SadMxNParam msa_tests[] = { + make_tuple(64, 64, &vpx_sad64x64_msa, -1), + make_tuple(64, 32, &vpx_sad64x32_msa, -1), + make_tuple(32, 64, &vpx_sad32x64_msa, -1), + make_tuple(32, 32, &vpx_sad32x32_msa, -1), + make_tuple(32, 16, &vpx_sad32x16_msa, -1), + make_tuple(16, 32, &vpx_sad16x32_msa, -1), + make_tuple(16, 16, &vpx_sad16x16_msa, -1), + make_tuple(16, 8, &vpx_sad16x8_msa, -1), + make_tuple(8, 16, &vpx_sad8x16_msa, -1), + make_tuple(8, 8, &vpx_sad8x8_msa, -1), + make_tuple(8, 4, &vpx_sad8x4_msa, -1), + make_tuple(4, 8, &vpx_sad4x8_msa, -1), + make_tuple(4, 4, &vpx_sad4x4_msa, -1), +}; +INSTANTIATE_TEST_CASE_P(MSA, SADTest, ::testing::ValuesIn(msa_tests)); + +const SadMxNAvgParam avg_msa_tests[] = { + make_tuple(64, 64, &vpx_sad64x64_avg_msa, -1), + make_tuple(64, 32, &vpx_sad64x32_avg_msa, -1), + make_tuple(32, 64, &vpx_sad32x64_avg_msa, -1), + make_tuple(32, 32, &vpx_sad32x32_avg_msa, -1), + make_tuple(32, 16, &vpx_sad32x16_avg_msa, -1), + make_tuple(16, 32, &vpx_sad16x32_avg_msa, -1), + make_tuple(16, 16, &vpx_sad16x16_avg_msa, -1), + make_tuple(16, 8, &vpx_sad16x8_avg_msa, -1), + make_tuple(8, 16, &vpx_sad8x16_avg_msa, -1), + make_tuple(8, 8, &vpx_sad8x8_avg_msa, -1), + make_tuple(8, 4, &vpx_sad8x4_avg_msa, -1), + make_tuple(4, 8, &vpx_sad4x8_avg_msa, -1), + make_tuple(4, 4, &vpx_sad4x4_avg_msa, -1), +}; +INSTANTIATE_TEST_CASE_P(MSA, SADavgTest, ::testing::ValuesIn(avg_msa_tests)); + +const SadMxNx4Param x4d_msa_tests[] = { + make_tuple(64, 64, &vpx_sad64x64x4d_msa, -1), + make_tuple(64, 32, &vpx_sad64x32x4d_msa, -1), + make_tuple(32, 64, &vpx_sad32x64x4d_msa, -1), + make_tuple(32, 32, &vpx_sad32x32x4d_msa, -1), + make_tuple(32, 16, &vpx_sad32x16x4d_msa, -1), + make_tuple(16, 32, &vpx_sad16x32x4d_msa, -1), + make_tuple(16, 16, &vpx_sad16x16x4d_msa, -1), + make_tuple(16, 8, &vpx_sad16x8x4d_msa, -1), + make_tuple(8, 16, &vpx_sad8x16x4d_msa, -1), + make_tuple(8, 8, &vpx_sad8x8x4d_msa, -1), + make_tuple(8, 4, &vpx_sad8x4x4d_msa, -1), + make_tuple(4, 8, &vpx_sad4x8x4d_msa, -1), + make_tuple(4, 4, &vpx_sad4x4x4d_msa, -1), +}; +INSTANTIATE_TEST_CASE_P(MSA, SADx4Test, ::testing::ValuesIn(x4d_msa_tests)); +#endif // HAVE_MSA + +} // namespace
diff --git a/src/third_party/libvpx/test/set_maps.sh b/src/third_party/libvpx/test/set_maps.sh new file mode 100755 index 0000000..e7c8d43 --- /dev/null +++ b/src/third_party/libvpx/test/set_maps.sh
@@ -0,0 +1,59 @@ +#!/bin/sh +## +## Copyright (c) 2014 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## +## This file tests the libvpx set_maps example. To add new tests to this file, +## do the following: +## 1. Write a shell function (this is your test). +## 2. Add the function to set_maps_tests (on a new line). +## +. $(dirname $0)/tools_common.sh + +# Environment check: $YUV_RAW_INPUT is required, and set_maps must exist in +# $LIBVPX_BIN_PATH. +set_maps_verify_environment() { + if [ ! -e "${YUV_RAW_INPUT}" ]; then + echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH." + return 1 + fi + if [ -z "$(vpx_tool_path set_maps)" ]; then + elog "set_maps not found. It must exist in LIBVPX_BIN_PATH or its parent." + return 1 + fi +} + +# Runs set_maps using the codec specified by $1. +set_maps() { + local encoder="$(vpx_tool_path set_maps)" + local codec="$1" + local output_file="${VPX_TEST_OUTPUT_DIR}/set_maps_${codec}.ivf" + + eval "${VPX_TEST_PREFIX}" "${encoder}" "${codec}" "${YUV_RAW_INPUT_WIDTH}" \ + "${YUV_RAW_INPUT_HEIGHT}" "${YUV_RAW_INPUT}" "${output_file}" \ + ${devnull} + + [ -e "${output_file}" ] || return 1 +} + +set_maps_vp8() { + if [ "$(vp8_encode_available)" = "yes" ]; then + set_maps vp8 || return 1 + fi +} + +set_maps_vp9() { + if [ "$(vp9_encode_available)" = "yes" ]; then + set_maps vp9 || return 1 + fi +} + +set_maps_tests="set_maps_vp8 + set_maps_vp9" + +run_tests set_maps_verify_environment "${set_maps_tests}"
diff --git a/src/third_party/libvpx/test/set_roi.cc b/src/third_party/libvpx/test/set_roi.cc new file mode 100644 index 0000000..fea8cca --- /dev/null +++ b/src/third_party/libvpx/test/set_roi.cc
@@ -0,0 +1,184 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + + +#include <math.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> + +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "test/acm_random.h" +#include "vp8/encoder/onyx_int.h" +#include "vpx/vpx_integer.h" +#include "vpx_mem/vpx_mem.h" + +using libvpx_test::ACMRandom; + +namespace { + +TEST(VP8RoiMapTest, ParameterCheck) { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + int delta_q[MAX_MB_SEGMENTS] = { -2, -25, 0, 31 }; + int delta_lf[MAX_MB_SEGMENTS] = { -2, -25, 0, 31 }; + unsigned int threshold[MAX_MB_SEGMENTS] = { 0, 100, 200, 300 }; + + const int internalq_trans[] = { + 0, 1, 2, 3, 4, 5, 7, 8, + 9, 10, 12, 13, 15, 17, 18, 19, + 20, 21, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 33, 35, 37, 39, 41, + 43, 45, 47, 49, 51, 53, 55, 57, + 59, 61, 64, 67, 70, 73, 76, 79, + 82, 85, 88, 91, 94, 97, 100, 103, + 106, 109, 112, 115, 118, 121, 124, 127, + }; + + // Initialize elements of cpi with valid defaults. + VP8_COMP cpi; + cpi.mb.e_mbd.mb_segement_abs_delta = SEGMENT_DELTADATA; + cpi.cyclic_refresh_mode_enabled = 0; + cpi.mb.e_mbd.segmentation_enabled = 0; + cpi.mb.e_mbd.update_mb_segmentation_map = 0; + cpi.mb.e_mbd.update_mb_segmentation_data = 0; + cpi.common.mb_rows = 240 >> 4; + cpi.common.mb_cols = 320 >> 4; + const int mbs = (cpi.common.mb_rows * cpi.common.mb_cols); + memset(cpi.segment_feature_data, 0, sizeof(cpi.segment_feature_data)); + + // Segment map + cpi.segmentation_map = reinterpret_cast<unsigned char *>(vpx_calloc(mbs, 1)); + + // Allocate memory for the source memory map. + unsigned char *roi_map = + reinterpret_cast<unsigned char *>(vpx_calloc(mbs, 1)); + memset(&roi_map[mbs >> 2], 1, (mbs >> 2)); + memset(&roi_map[mbs >> 1], 2, (mbs >> 2)); + memset(&roi_map[mbs -(mbs >> 2)], 3, (mbs >> 2)); + + // Do a test call with valid parameters. + int roi_retval = vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows, + cpi.common.mb_cols, delta_q, delta_lf, + threshold); + EXPECT_EQ(0, roi_retval) + << "vp8_set_roimap roi failed with default test parameters"; + + // Check that the values in the cpi structure get set as expected. + if (roi_retval == 0) { + // Check that the segment map got set. + const int mapcompare = memcmp(roi_map, cpi.segmentation_map, mbs); + EXPECT_EQ(0, mapcompare) << "segment map error"; + + // Check the q deltas (note the need to translate into + // the interanl range of 0-127. + for (int i = 0; i < MAX_MB_SEGMENTS; ++i) { + const int transq = internalq_trans[abs(delta_q[i])]; + if (abs(cpi.segment_feature_data[MB_LVL_ALT_Q][i]) != transq) { + EXPECT_EQ(transq, cpi.segment_feature_data[MB_LVL_ALT_Q][i]) + << "segment delta_q error"; + break; + } + } + + // Check the loop filter deltas + for (int i = 0; i < MAX_MB_SEGMENTS; ++i) { + if (cpi.segment_feature_data[MB_LVL_ALT_LF][i] != delta_lf[i]) { + EXPECT_EQ(delta_lf[i], cpi.segment_feature_data[MB_LVL_ALT_LF][i]) + << "segment delta_lf error"; + break; + } + } + + // Check the breakout thresholds + for (int i = 0; i < MAX_MB_SEGMENTS; ++i) { + unsigned int breakout = + static_cast<unsigned int>(cpi.segment_encode_breakout[i]); + + if (threshold[i] != breakout) { + EXPECT_EQ(threshold[i], breakout) + << "breakout threshold error"; + break; + } + } + + // Segmentation, and segmentation update flages should be set. + EXPECT_EQ(1, cpi.mb.e_mbd.segmentation_enabled) + << "segmentation_enabled error"; + EXPECT_EQ(1, cpi.mb.e_mbd.update_mb_segmentation_map) + << "update_mb_segmentation_map error"; + EXPECT_EQ(1, cpi.mb.e_mbd.update_mb_segmentation_data) + << "update_mb_segmentation_data error"; + + + // Try a range of delta q and lf parameters (some legal, some not) + for (int i = 0; i < 1000; ++i) { + int rand_deltas[4]; + int deltas_valid; + rand_deltas[0] = rnd(160) - 80; + rand_deltas[1] = rnd(160) - 80; + rand_deltas[2] = rnd(160) - 80; + rand_deltas[3] = rnd(160) - 80; + + deltas_valid = ((abs(rand_deltas[0]) <= 63) && + (abs(rand_deltas[1]) <= 63) && + (abs(rand_deltas[2]) <= 63) && + (abs(rand_deltas[3]) <= 63)) ? 0 : -1; + + // Test with random delta q values. + roi_retval = vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows, + cpi.common.mb_cols, rand_deltas, + delta_lf, threshold); + EXPECT_EQ(deltas_valid, roi_retval) << "dq range check error"; + + // One delta_q error shown at a time + if (deltas_valid != roi_retval) + break; + + // Test with random loop filter values. + roi_retval = vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows, + cpi.common.mb_cols, delta_q, + rand_deltas, threshold); + EXPECT_EQ(deltas_valid, roi_retval) << "dlf range check error"; + + // One delta loop filter error shown at a time + if (deltas_valid != roi_retval) + break; + } + + // Test that we report and error if cyclic refresh is enabled. + cpi.cyclic_refresh_mode_enabled = 1; + roi_retval = vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows, + cpi.common.mb_cols, delta_q, + delta_lf, threshold); + EXPECT_EQ(-1, roi_retval) << "cyclic refresh check error"; + cpi.cyclic_refresh_mode_enabled = 0; + + // Test invalid number of rows or colums. + roi_retval = vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows + 1, + cpi.common.mb_cols, delta_q, + delta_lf, threshold); + EXPECT_EQ(-1, roi_retval) << "MB rows bounds check error"; + + roi_retval = vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows, + cpi.common.mb_cols - 1, delta_q, + delta_lf, threshold); + EXPECT_EQ(-1, roi_retval) << "MB cols bounds check error"; + } + + // Free allocated memory + if (cpi.segmentation_map) + vpx_free(cpi.segmentation_map); + if (roi_map) + vpx_free(roi_map); +}; + +} // namespace
diff --git a/src/third_party/libvpx/test/simple_decoder.sh b/src/third_party/libvpx/test/simple_decoder.sh new file mode 100755 index 0000000..7eeaf71 --- /dev/null +++ b/src/third_party/libvpx/test/simple_decoder.sh
@@ -0,0 +1,61 @@ +#!/bin/sh +## +## Copyright (c) 2014 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## +## This file tests the libvpx simple_decoder example code. To add new tests to +## this file, do the following: +## 1. Write a shell function (this is your test). +## 2. Add the function to simple_decoder_tests (on a new line). +## +. $(dirname $0)/tools_common.sh + +# Environment check: Make sure input is available: +# $VP8_IVF_FILE and $VP9_IVF_FILE are required. +simple_decoder_verify_environment() { + if [ ! -e "${VP8_IVF_FILE}" ] || [ ! -e "${VP9_IVF_FILE}" ]; then + echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH." + return 1 + fi +} + +# Runs simple_decoder using $1 as input file. $2 is the codec name, and is used +# solely to name the output file. +simple_decoder() { + local decoder="${LIBVPX_BIN_PATH}/simple_decoder${VPX_TEST_EXE_SUFFIX}" + local input_file="$1" + local codec="$2" + local output_file="${VPX_TEST_OUTPUT_DIR}/simple_decoder_${codec}.raw" + + if [ ! -x "${decoder}" ]; then + elog "${decoder} does not exist or is not executable." + return 1 + fi + + eval "${VPX_TEST_PREFIX}" "${decoder}" "${input_file}" "${output_file}" \ + ${devnull} + + [ -e "${output_file}" ] || return 1 +} + +simple_decoder_vp8() { + if [ "$(vp8_decode_available)" = "yes" ]; then + simple_decoder "${VP8_IVF_FILE}" vp8 || return 1 + fi +} + +simple_decoder_vp9() { + if [ "$(vp9_decode_available)" = "yes" ]; then + simple_decoder "${VP9_IVF_FILE}" vp9 || return 1 + fi +} + +simple_decoder_tests="simple_decoder_vp8 + simple_decoder_vp9" + +run_tests simple_decoder_verify_environment "${simple_decoder_tests}"
diff --git a/src/third_party/libvpx/test/simple_encoder.sh b/src/third_party/libvpx/test/simple_encoder.sh new file mode 100755 index 0000000..ee633ae --- /dev/null +++ b/src/third_party/libvpx/test/simple_encoder.sh
@@ -0,0 +1,59 @@ +#!/bin/sh +## +## Copyright (c) 2014 The WebM project authors. All Rights Reserved. +## +## Use of this source code is governed by a BSD-style license +## that can be found in the LICENSE file in the root of the source +## tree. An additional intellectual property rights grant can be found +## in the file PATENTS. All contributing project authors may +## be found in the AUTHORS file in the root of the source tree. +## +## This file tests the libvpx simple_encoder example. To add new tests to this +## file, do the following: +## 1. Write a shell function (this is your test). +## 2. Add the function to simple_encoder_tests (on a new line). +## +. $(dirname $0)/tools_common.sh + +# Environment check: $YUV_RAW_INPUT is required. +simple_encoder_verify_environment() { + if [ ! -e "${YUV_RAW_INPUT}" ]; then + echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH." + return 1 + fi +} + +# Runs simple_encoder using the codec specified by $1 with a frame limit of 100. +simple_encoder() { + local encoder="${LIBVPX_BIN_PATH}/simple_encoder${VPX_TEST_EXE_SUFFIX}" + local codec="$1" + local output_file="${VPX_TEST_OUTPUT_DIR}/simple_encoder_${codec}.ivf" + + if [ ! -x "${encoder}" ]; then + elog "${encoder} does not exist or is not executable." + return 1 + fi + + eval "${VPX_TEST_PREFIX}" "${encoder}" "${codec}" "${YUV_RAW_INPUT_WIDTH}" \ + "${YUV_RAW_INPUT_HEIGHT}" "${YUV_RAW_INPUT}" "${output_file}" 9999 0 100 \ + ${devnull} + + [ -e "${output_file}" ] || return 1 +} + +simple_encoder_vp8() { + if [ "$(vp8_encode_available)" = "yes" ]; then + simple_encoder vp8 || return 1 + fi +} + +simple_encoder_vp9() { + if [ "$(vp9_encode_available)" = "yes" ]; then + simple_encoder vp9 || return 1 + fi +} + +simple_encoder_tests="simple_encoder_vp8 + simple_encoder_vp9" + +run_tests simple_encoder_verify_environment "${simple_encoder_tests}"
diff --git a/src/third_party/libvpx/test/sixtap_predict_test.cc b/src/third_party/libvpx/test/sixtap_predict_test.cc new file mode 100644 index 0000000..304a148 --- /dev/null +++ b/src/third_party/libvpx/test/sixtap_predict_test.cc
@@ -0,0 +1,233 @@ +/* + * Copyright (c) 2013 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <math.h> +#include <stdlib.h> +#include <string.h> + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "./vpx_config.h" +#include "./vp8_rtcd.h" +#include "test/acm_random.h" +#include "test/clear_system_state.h" +#include "test/register_state_check.h" +#include "test/util.h" +#include "vpx/vpx_integer.h" +#include "vpx_mem/vpx_mem.h" + +namespace { + +typedef void (*SixtapPredictFunc)(uint8_t *src_ptr, + int src_pixels_per_line, + int xoffset, + int yoffset, + uint8_t *dst_ptr, + int dst_pitch); + +typedef std::tr1::tuple<int, int, SixtapPredictFunc> SixtapPredictParam; + +class SixtapPredictTest + : public ::testing::TestWithParam<SixtapPredictParam> { + public: + static void SetUpTestCase() { + src_ = reinterpret_cast<uint8_t*>(vpx_memalign(kDataAlignment, kSrcSize)); + dst_ = reinterpret_cast<uint8_t*>(vpx_memalign(kDataAlignment, kDstSize)); + dst_c_ = reinterpret_cast<uint8_t*>(vpx_memalign(kDataAlignment, kDstSize)); + } + + static void TearDownTestCase() { + vpx_free(src_); + src_ = NULL; + vpx_free(dst_); + dst_ = NULL; + vpx_free(dst_c_); + dst_c_ = NULL; + } + + virtual void TearDown() { + libvpx_test::ClearSystemState(); + } + + protected: + // Make test arrays big enough for 16x16 functions. Six-tap filters + // need 5 extra pixels outside of the macroblock. + static const int kSrcStride = 21; + static const int kDstStride = 16; + static const int kDataAlignment = 16; + static const int kSrcSize = kSrcStride * kSrcStride + 1; + static const int kDstSize = kDstStride * kDstStride; + + virtual void SetUp() { + width_ = GET_PARAM(0); + height_ = GET_PARAM(1); + sixtap_predict_ = GET_PARAM(2); + memset(src_, 0, kSrcSize); + memset(dst_, 0, kDstSize); + memset(dst_c_, 0, kDstSize); + } + + int width_; + int height_; + SixtapPredictFunc sixtap_predict_; + // The src stores the macroblock we will filter on, and makes it 1 byte larger + // in order to test unaligned access. The result is stored in dst and dst_c(c + // reference code result). + static uint8_t* src_; + static uint8_t* dst_; + static uint8_t* dst_c_; +}; + +uint8_t* SixtapPredictTest::src_ = NULL; +uint8_t* SixtapPredictTest::dst_ = NULL; +uint8_t* SixtapPredictTest::dst_c_ = NULL; + +TEST_P(SixtapPredictTest, TestWithPresetData) { + // Test input + static const uint8_t test_data[kSrcSize] = { + 216, 184, 4, 191, 82, 92, 41, 0, 1, 226, 236, 172, 20, 182, 42, 226, 177, + 79, 94, 77, 179, 203, 206, 198, 22, 192, 19, 75, 17, 192, 44, 233, 120, + 48, 168, 203, 141, 210, 203, 143, 180, 184, 59, 201, 110, 102, 171, 32, + 182, 10, 109, 105, 213, 60, 47, 236, 253, 67, 55, 14, 3, 99, 247, 124, + 148, 159, 71, 34, 114, 19, 177, 38, 203, 237, 239, 58, 83, 155, 91, 10, + 166, 201, 115, 124, 5, 163, 104, 2, 231, 160, 16, 234, 4, 8, 103, 153, + 167, 174, 187, 26, 193, 109, 64, 141, 90, 48, 200, 174, 204, 36, 184, + 114, 237, 43, 238, 242, 207, 86, 245, 182, 247, 6, 161, 251, 14, 8, 148, + 182, 182, 79, 208, 120, 188, 17, 6, 23, 65, 206, 197, 13, 242, 126, 128, + 224, 170, 110, 211, 121, 197, 200, 47, 188, 207, 208, 184, 221, 216, 76, + 148, 143, 156, 100, 8, 89, 117, 14, 112, 183, 221, 54, 197, 208, 180, 69, + 176, 94, 180, 131, 215, 121, 76, 7, 54, 28, 216, 238, 249, 176, 58, 142, + 64, 215, 242, 72, 49, 104, 87, 161, 32, 52, 216, 230, 4, 141, 44, 181, + 235, 224, 57, 195, 89, 134, 203, 144, 162, 163, 126, 156, 84, 185, 42, + 148, 145, 29, 221, 194, 134, 52, 100, 166, 105, 60, 140, 110, 201, 184, + 35, 181, 153, 93, 121, 243, 227, 68, 131, 134, 232, 2, 35, 60, 187, 77, + 209, 76, 106, 174, 15, 241, 227, 115, 151, 77, 175, 36, 187, 121, 221, + 223, 47, 118, 61, 168, 105, 32, 237, 236, 167, 213, 238, 202, 17, 170, + 24, 226, 247, 131, 145, 6, 116, 117, 121, 11, 194, 41, 48, 126, 162, 13, + 93, 209, 131, 154, 122, 237, 187, 103, 217, 99, 60, 200, 45, 78, 115, 69, + 49, 106, 200, 194, 112, 60, 56, 234, 72, 251, 19, 120, 121, 182, 134, 215, + 135, 10, 114, 2, 247, 46, 105, 209, 145, 165, 153, 191, 243, 12, 5, 36, + 119, 206, 231, 231, 11, 32, 209, 83, 27, 229, 204, 149, 155, 83, 109, 35, + 93, 223, 37, 84, 14, 142, 37, 160, 52, 191, 96, 40, 204, 101, 77, 67, 52, + 53, 43, 63, 85, 253, 147, 113, 226, 96, 6, 125, 179, 115, 161, 17, 83, + 198, 101, 98, 85, 139, 3, 137, 75, 99, 178, 23, 201, 255, 91, 253, 52, + 134, 60, 138, 131, 208, 251, 101, 48, 2, 227, 228, 118, 132, 245, 202, + 75, 91, 44, 160, 231, 47, 41, 50, 147, 220, 74, 92, 219, 165, 89, 16 + }; + + // Expected result + static const uint8_t expected_dst[kDstSize] = { + 117, 102, 74, 135, 42, 98, 175, 206, 70, 73, 222, 197, 50, 24, 39, 49, 38, + 105, 90, 47, 169, 40, 171, 215, 200, 73, 109, 141, 53, 85, 177, 164, 79, + 208, 124, 89, 212, 18, 81, 145, 151, 164, 217, 153, 91, 154, 102, 102, + 159, 75, 164, 152, 136, 51, 213, 219, 186, 116, 193, 224, 186, 36, 231, + 208, 84, 211, 155, 167, 35, 59, 42, 76, 216, 149, 73, 201, 78, 149, 184, + 100, 96, 196, 189, 198, 188, 235, 195, 117, 129, 120, 129, 49, 25, 133, + 113, 69, 221, 114, 70, 143, 99, 157, 108, 189, 140, 78, 6, 55, 65, 240, + 255, 245, 184, 72, 90, 100, 116, 131, 39, 60, 234, 167, 33, 160, 88, 185, + 200, 157, 159, 176, 127, 151, 138, 102, 168, 106, 170, 86, 82, 219, 189, + 76, 33, 115, 197, 106, 96, 198, 136, 97, 141, 237, 151, 98, 137, 191, + 185, 2, 57, 95, 142, 91, 255, 185, 97, 137, 76, 162, 94, 173, 131, 193, + 161, 81, 106, 72, 135, 222, 234, 137, 66, 137, 106, 243, 210, 147, 95, + 15, 137, 110, 85, 66, 16, 96, 167, 147, 150, 173, 203, 140, 118, 196, + 84, 147, 160, 19, 95, 101, 123, 74, 132, 202, 82, 166, 12, 131, 166, + 189, 170, 159, 85, 79, 66, 57, 152, 132, 203, 194, 0, 1, 56, 146, 180, + 224, 156, 28, 83, 181, 79, 76, 80, 46, 160, 175, 59, 106, 43, 87, 75, + 136, 85, 189, 46, 71, 200, 90 + }; + + uint8_t *src = const_cast<uint8_t*>(test_data); + + ASM_REGISTER_STATE_CHECK( + sixtap_predict_(&src[kSrcStride * 2 + 2 + 1], kSrcStride, + 2, 2, dst_, kDstStride)); + + for (int i = 0; i < height_; ++i) + for (int j = 0; j < width_; ++j) + ASSERT_EQ(expected_dst[i * kDstStride + j], dst_[i * kDstStride + j]) + << "i==" << (i * width_ + j); +} + +using libvpx_test::ACMRandom; + +TEST_P(SixtapPredictTest, TestWithRandomData) { + ACMRandom rnd(ACMRandom::DeterministicSeed()); + for (int i = 0; i < kSrcSize; ++i) + src_[i] = rnd.Rand8(); + + // Run tests for all possible offsets. + for (int xoffset = 0; xoffset < 8; ++xoffset) { + for (int yoffset = 0; yoffset < 8; ++yoffset) { + // Call c reference function. + // Move start point to next pixel to test if the function reads + // unaligned data correctly. + vp8_sixtap_predict16x16_c(&src_[kSrcStride * 2 + 2 + 1], kSrcStride, + xoffset, yoffset, dst_c_, kDstStride); + + // Run test. + ASM_REGISTER_STATE_CHECK( + sixtap_predict_(&src_[kSrcStride * 2 + 2 + 1], kSrcStride, + xoffset, yoffset, dst_, kDstStride)); + + for (int i = 0; i < height_; ++i) + for (int j = 0; j < width_; ++j) + ASSERT_EQ(dst_c_[i * kDstStride + j], dst_[i * kDstStride + j]) + << "i==" << (i * width_ + j); + } + } +} + +using std::tr1::make_tuple; + +INSTANTIATE_TEST_CASE_P( + C, SixtapPredictTest, ::testing::Values( + make_tuple(16, 16, &vp8_sixtap_predict16x16_c), + make_tuple(8, 8, &vp8_sixtap_predict8x8_c), + make_tuple(8, 4, &vp8_sixtap_predict8x4_c), + make_tuple(4, 4, &vp8_sixtap_predict4x4_c))); +#if HAVE_NEON +INSTANTIATE_TEST_CASE_P( + NEON, SixtapPredictTest, ::testing::Values( + make_tuple(16, 16, &vp8_sixtap_predict16x16_neon), + make_tuple(8, 8, &vp8_sixtap_predict8x8_neon), + make_tuple(8, 4, &vp8_sixtap_predict8x4_neon))); +#endif +#if HAVE_MMX +INSTANTIATE_TEST_CASE_P( + MMX, SixtapPredictTest, ::testing::Values( + make_tuple(16, 16, &vp8_sixtap_predict16x16_mmx), + make_tuple(8, 8, &vp8_sixtap_predict8x8_mmx), + make_tuple(8, 4, &vp8_sixtap_predict8x4_mmx), + make_tuple(4, 4, &vp8_sixtap_predict4x4_mmx))); +#endif +#if HAVE_SSE2 +INSTANTIATE_TEST_CASE_P( + SSE2, SixtapPredictTest, ::testing::Values( + make_tuple(16, 16, &vp8_sixtap_predict16x16_sse2), + make_tuple(8, 8, &vp8_sixtap_predict8x8_sse2), + make_tuple(8, 4, &vp8_sixtap_predict8x4_sse2))); +#endif +#if HAVE_SSSE3 +INSTANTIATE_TEST_CASE_P( + SSSE3, SixtapPredictTest, ::testing::Values( + make_tuple(16, 16, &vp8_sixtap_predict16x16_ssse3), + make_tuple(8, 8, &vp8_sixtap_predict8x8_ssse3), + make_tuple(8, 4, &vp8_sixtap_predict8x4_ssse3), + make_tuple(4, 4, &vp8_sixtap_predict4x4_ssse3))); +#endif +#if HAVE_MSA +INSTANTIATE_TEST_CASE_P( + MSA, SixtapPredictTest, ::testing::Values( + make_tuple(16, 16, &vp8_sixtap_predict16x16_msa), + make_tuple(8, 8, &vp8_sixtap_predict8x8_msa), + make_tuple(8, 4, &vp8_sixtap_predict8x4_msa), + make_tuple(4, 4, &vp8_sixtap_predict4x4_msa))); +#endif +} // namespace
diff --git a/src/third_party/libvpx/test/superframe_test.cc b/src/third_party/libvpx/test/superframe_test.cc new file mode 100644 index 0000000..90aa75b --- /dev/null +++ b/src/third_party/libvpx/test/superframe_test.cc
@@ -0,0 +1,113 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include <climits> +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "test/codec_factory.h" +#include "test/encode_test_driver.h" +#include "test/i420_video_source.h" +#include "test/util.h" + +namespace { + +const int kTestMode = 0; +const int kSuperframeSyntax = 1; + +typedef std::tr1::tuple<libvpx_test::TestMode,int> SuperframeTestParam; + +class SuperframeTest : public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWithParam<SuperframeTestParam> { + protected: + SuperframeTest() : EncoderTest(GET_PARAM(0)), modified_buf_(NULL), + last_sf_pts_(0) {} + virtual ~SuperframeTest() {} + + virtual void SetUp() { + InitializeConfig(); + const SuperframeTestParam input = GET_PARAM(1); + const libvpx_test::TestMode mode = std::tr1::get<kTestMode>(input); + const int syntax = std::tr1::get<kSuperframeSyntax>(input); + SetMode(mode); + sf_count_ = 0; + sf_count_max_ = INT_MAX; + is_vp10_style_superframe_ = syntax; + } + + virtual void TearDown() { + delete[] modified_buf_; + } + + virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video, + libvpx_test::Encoder *encoder) { + if (video->frame() == 1) { + encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1); + } + } + + virtual const vpx_codec_cx_pkt_t * MutateEncoderOutputHook( + const vpx_codec_cx_pkt_t *pkt) { + if (pkt->kind != VPX_CODEC_CX_FRAME_PKT) + return pkt; + + const uint8_t *buffer = reinterpret_cast<uint8_t*>(pkt->data.frame.buf); + const uint8_t marker = buffer[pkt->data.frame.sz - 1]; + const int frames = (marker & 0x7) + 1; + const int mag = ((marker >> 3) & 3) + 1; + const unsigned int index_sz = + 2 + mag * (frames - is_vp10_style_superframe_); + if ((marker & 0xe0) == 0xc0 && + pkt->data.frame.sz >= index_sz && + buffer[pkt->data.frame.sz - index_sz] == marker) { + // frame is a superframe. strip off the index. + if (modified_buf_) + delete[] modified_buf_; + modified_buf_ = new uint8_t[pkt->data.frame.sz - index_sz]; + memcpy(modified_buf_, pkt->data.frame.buf, + pkt->data.frame.sz - index_sz); + modified_pkt_ = *pkt; + modified_pkt_.data.frame.buf = modified_buf_; + modified_pkt_.data.frame.sz -= index_sz; + + sf_count_++; + last_sf_pts_ = pkt->data.frame.pts; + return &modified_pkt_; + } + + // Make sure we do a few frames after the last SF + abort_ |= sf_count_ > sf_count_max_ && + pkt->data.frame.pts - last_sf_pts_ >= 5; + return pkt; + } + + int is_vp10_style_superframe_; + int sf_count_; + int sf_count_max_; + vpx_codec_cx_pkt_t modified_pkt_; + uint8_t *modified_buf_; + vpx_codec_pts_t last_sf_pts_; +}; + +TEST_P(SuperframeTest, TestSuperframeIndexIsOptional) { + sf_count_max_ = 0; // early exit on successful test. + cfg_.g_lag_in_frames = 25; + + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 40); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + EXPECT_EQ(sf_count_, 1); +} + +VP9_INSTANTIATE_TEST_CASE(SuperframeTest, ::testing::Combine( + ::testing::Values(::libvpx_test::kTwoPassGood), + ::testing::Values(0))); + +VP10_INSTANTIATE_TEST_CASE(SuperframeTest, ::testing::Combine( + ::testing::Values(::libvpx_test::kTwoPassGood), + ::testing::Values(CONFIG_MISC_FIXES))); +} // namespace
diff --git a/src/third_party/libvpx/test/svc_test.cc b/src/third_party/libvpx/test/svc_test.cc new file mode 100644 index 0000000..b955cee --- /dev/null +++ b/src/third_party/libvpx/test/svc_test.cc
@@ -0,0 +1,797 @@ +/* + * Copyright (c) 2013 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <string> +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "test/codec_factory.h" +#include "test/decode_test_driver.h" +#include "test/i420_video_source.h" + +#include "vp9/decoder/vp9_decoder.h" + +#include "vpx/svc_context.h" +#include "vpx/vp8cx.h" +#include "vpx/vpx_encoder.h" + +namespace { + +using libvpx_test::CodecFactory; +using libvpx_test::Decoder; +using libvpx_test::DxDataIterator; +using libvpx_test::VP9CodecFactory; + +class SvcTest : public ::testing::Test { + protected: + static const uint32_t kWidth = 352; + static const uint32_t kHeight = 288; + + SvcTest() + : codec_iface_(0), + test_file_name_("hantro_collage_w352h288.yuv"), + codec_initialized_(false), + decoder_(0) { + memset(&svc_, 0, sizeof(svc_)); + memset(&codec_, 0, sizeof(codec_)); + memset(&codec_enc_, 0, sizeof(codec_enc_)); + } + + virtual ~SvcTest() {} + + virtual void SetUp() { + svc_.log_level = SVC_LOG_DEBUG; + svc_.log_print = 0; + + codec_iface_ = vpx_codec_vp9_cx(); + const vpx_codec_err_t res = + vpx_codec_enc_config_default(codec_iface_, &codec_enc_, 0); + EXPECT_EQ(VPX_CODEC_OK, res); + + codec_enc_.g_w = kWidth; + codec_enc_.g_h = kHeight; + codec_enc_.g_timebase.num = 1; + codec_enc_.g_timebase.den = 60; + codec_enc_.kf_min_dist = 100; + codec_enc_.kf_max_dist = 100; + + vpx_codec_dec_cfg_t dec_cfg = vpx_codec_dec_cfg_t(); + VP9CodecFactory codec_factory; + decoder_ = codec_factory.CreateDecoder(dec_cfg, 0); + + tile_columns_ = 0; + tile_rows_ = 0; + } + + virtual void TearDown() { + ReleaseEncoder(); + delete(decoder_); + } + + void InitializeEncoder() { + const vpx_codec_err_t res = + vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); + EXPECT_EQ(VPX_CODEC_OK, res); + vpx_codec_control(&codec_, VP8E_SET_CPUUSED, 4); // Make the test faster + vpx_codec_control(&codec_, VP9E_SET_TILE_COLUMNS, tile_columns_); + vpx_codec_control(&codec_, VP9E_SET_TILE_ROWS, tile_rows_); + codec_initialized_ = true; + } + + void ReleaseEncoder() { + vpx_svc_release(&svc_); + if (codec_initialized_) vpx_codec_destroy(&codec_); + codec_initialized_ = false; + } + + void GetStatsData(std::string *const stats_buf) { + vpx_codec_iter_t iter = NULL; + const vpx_codec_cx_pkt_t *cx_pkt; + + while ((cx_pkt = vpx_codec_get_cx_data(&codec_, &iter)) != NULL) { + if (cx_pkt->kind == VPX_CODEC_STATS_PKT) { + EXPECT_GT(cx_pkt->data.twopass_stats.sz, 0U); + ASSERT_TRUE(cx_pkt->data.twopass_stats.buf != NULL); + stats_buf->append(static_cast<char*>(cx_pkt->data.twopass_stats.buf), + cx_pkt->data.twopass_stats.sz); + } + } + } + + void Pass1EncodeNFrames(const int n, const int layers, + std::string *const stats_buf) { + vpx_codec_err_t res; + + ASSERT_GT(n, 0); + ASSERT_GT(layers, 0); + svc_.spatial_layers = layers; + codec_enc_.g_pass = VPX_RC_FIRST_PASS; + InitializeEncoder(); + + libvpx_test::I420VideoSource video(test_file_name_, + codec_enc_.g_w, codec_enc_.g_h, + codec_enc_.g_timebase.den, + codec_enc_.g_timebase.num, 0, 30); + video.Begin(); + + for (int i = 0; i < n; ++i) { + res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(), + video.duration(), VPX_DL_GOOD_QUALITY); + ASSERT_EQ(VPX_CODEC_OK, res); + GetStatsData(stats_buf); + video.Next(); + } + + // Flush encoder and test EOS packet. + res = vpx_svc_encode(&svc_, &codec_, NULL, video.pts(), + video.duration(), VPX_DL_GOOD_QUALITY); + ASSERT_EQ(VPX_CODEC_OK, res); + GetStatsData(stats_buf); + + ReleaseEncoder(); + } + + void StoreFrames(const size_t max_frame_received, + struct vpx_fixed_buf *const outputs, + size_t *const frame_received) { + vpx_codec_iter_t iter = NULL; + const vpx_codec_cx_pkt_t *cx_pkt; + + while ((cx_pkt = vpx_codec_get_cx_data(&codec_, &iter)) != NULL) { + if (cx_pkt->kind == VPX_CODEC_CX_FRAME_PKT) { + const size_t frame_size = cx_pkt->data.frame.sz; + + EXPECT_GT(frame_size, 0U); + ASSERT_TRUE(cx_pkt->data.frame.buf != NULL); + ASSERT_LT(*frame_received, max_frame_received); + + if (*frame_received == 0) + EXPECT_EQ(1, !!(cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY)); + + outputs[*frame_received].buf = malloc(frame_size + 16); + ASSERT_TRUE(outputs[*frame_received].buf != NULL); + memcpy(outputs[*frame_received].buf, cx_pkt->data.frame.buf, + frame_size); + outputs[*frame_received].sz = frame_size; + ++(*frame_received); + } + } + } + + void Pass2EncodeNFrames(std::string *const stats_buf, + const int n, const int layers, + struct vpx_fixed_buf *const outputs) { + vpx_codec_err_t res; + size_t frame_received = 0; + + ASSERT_TRUE(outputs != NULL); + ASSERT_GT(n, 0); + ASSERT_GT(layers, 0); + svc_.spatial_layers = layers; + codec_enc_.rc_target_bitrate = 500; + if (codec_enc_.g_pass == VPX_RC_LAST_PASS) { + ASSERT_TRUE(stats_buf != NULL); + ASSERT_GT(stats_buf->size(), 0U); + codec_enc_.rc_twopass_stats_in.buf = &(*stats_buf)[0]; + codec_enc_.rc_twopass_stats_in.sz = stats_buf->size(); + } + InitializeEncoder(); + + libvpx_test::I420VideoSource video(test_file_name_, + codec_enc_.g_w, codec_enc_.g_h, + codec_enc_.g_timebase.den, + codec_enc_.g_timebase.num, 0, 30); + video.Begin(); + + for (int i = 0; i < n; ++i) { + res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(), + video.duration(), VPX_DL_GOOD_QUALITY); + ASSERT_EQ(VPX_CODEC_OK, res); + StoreFrames(n, outputs, &frame_received); + video.Next(); + } + + // Flush encoder. + res = vpx_svc_encode(&svc_, &codec_, NULL, 0, + video.duration(), VPX_DL_GOOD_QUALITY); + EXPECT_EQ(VPX_CODEC_OK, res); + StoreFrames(n, outputs, &frame_received); + + EXPECT_EQ(frame_received, static_cast<size_t>(n)); + + ReleaseEncoder(); + } + + void DecodeNFrames(const struct vpx_fixed_buf *const inputs, const int n) { + int decoded_frames = 0; + int received_frames = 0; + + ASSERT_TRUE(inputs != NULL); + ASSERT_GT(n, 0); + + for (int i = 0; i < n; ++i) { + ASSERT_TRUE(inputs[i].buf != NULL); + ASSERT_GT(inputs[i].sz, 0U); + const vpx_codec_err_t res_dec = + decoder_->DecodeFrame(static_cast<const uint8_t *>(inputs[i].buf), + inputs[i].sz); + ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError(); + ++decoded_frames; + + DxDataIterator dec_iter = decoder_->GetDxData(); + while (dec_iter.Next() != NULL) { + ++received_frames; + } + } + EXPECT_EQ(decoded_frames, n); + EXPECT_EQ(received_frames, n); + } + + void DropEnhancementLayers(struct vpx_fixed_buf *const inputs, + const int num_super_frames, + const int remained_spatial_layers) { + ASSERT_TRUE(inputs != NULL); + ASSERT_GT(num_super_frames, 0); + ASSERT_GT(remained_spatial_layers, 0); + + for (int i = 0; i < num_super_frames; ++i) { + uint32_t frame_sizes[8] = {0}; + int frame_count = 0; + int frames_found = 0; + int frame; + ASSERT_TRUE(inputs[i].buf != NULL); + ASSERT_GT(inputs[i].sz, 0U); + + vpx_codec_err_t res = + vp9_parse_superframe_index(static_cast<const uint8_t*>(inputs[i].buf), + inputs[i].sz, frame_sizes, &frame_count, + NULL, NULL); + ASSERT_EQ(VPX_CODEC_OK, res); + + if (frame_count == 0) { + // There's no super frame but only a single frame. + ASSERT_EQ(1, remained_spatial_layers); + } else { + // Found a super frame. + uint8_t *frame_data = static_cast<uint8_t*>(inputs[i].buf); + uint8_t *frame_start = frame_data; + for (frame = 0; frame < frame_count; ++frame) { + // Looking for a visible frame. + if (frame_data[0] & 0x02) { + ++frames_found; + if (frames_found == remained_spatial_layers) + break; + } + frame_data += frame_sizes[frame]; + } + ASSERT_LT(frame, frame_count) << "Couldn't find a visible frame. " + << "remained_spatial_layers: " << remained_spatial_layers + << " super_frame: " << i; + if (frame == frame_count - 1) + continue; + + frame_data += frame_sizes[frame]; + + // We need to add one more frame for multiple frame contexts. + uint8_t marker = + static_cast<const uint8_t*>(inputs[i].buf)[inputs[i].sz - 1]; + const uint32_t mag = ((marker >> 3) & 0x3) + 1; + const size_t index_sz = 2 + mag * frame_count; + const size_t new_index_sz = 2 + mag * (frame + 1); + marker &= 0x0f8; + marker |= frame; + + // Copy existing frame sizes. + memmove(frame_data + 1, frame_start + inputs[i].sz - index_sz + 1, + new_index_sz - 2); + // New marker. + frame_data[0] = marker; + frame_data += (mag * (frame + 1) + 1); + + *frame_data++ = marker; + inputs[i].sz = frame_data - frame_start; + } + } + } + + void FreeBitstreamBuffers(struct vpx_fixed_buf *const inputs, const int n) { + ASSERT_TRUE(inputs != NULL); + ASSERT_GT(n, 0); + + for (int i = 0; i < n; ++i) { + free(inputs[i].buf); + inputs[i].buf = NULL; + inputs[i].sz = 0; + } + } + + SvcContext svc_; + vpx_codec_ctx_t codec_; + struct vpx_codec_enc_cfg codec_enc_; + vpx_codec_iface_t *codec_iface_; + std::string test_file_name_; + bool codec_initialized_; + Decoder *decoder_; + int tile_columns_; + int tile_rows_; +}; + +TEST_F(SvcTest, SvcInit) { + // test missing parameters + vpx_codec_err_t res = vpx_svc_init(NULL, &codec_, codec_iface_, &codec_enc_); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); + res = vpx_svc_init(&svc_, NULL, codec_iface_, &codec_enc_); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); + res = vpx_svc_init(&svc_, &codec_, NULL, &codec_enc_); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); + + res = vpx_svc_init(&svc_, &codec_, codec_iface_, NULL); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); + + svc_.spatial_layers = 6; // too many layers + res = vpx_svc_init(&svc_, &codec_, codec_iface_, &codec_enc_); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); + + svc_.spatial_layers = 0; // use default layers + InitializeEncoder(); + EXPECT_EQ(VPX_SS_DEFAULT_LAYERS, svc_.spatial_layers); +} + +TEST_F(SvcTest, InitTwoLayers) { + svc_.spatial_layers = 2; + InitializeEncoder(); +} + +TEST_F(SvcTest, InvalidOptions) { + vpx_codec_err_t res = vpx_svc_set_options(&svc_, NULL); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); + + res = vpx_svc_set_options(&svc_, "not-an-option=1"); + EXPECT_EQ(VPX_CODEC_OK, res); + res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); +} + +TEST_F(SvcTest, SetLayersOption) { + vpx_codec_err_t res = vpx_svc_set_options(&svc_, "spatial-layers=3"); + EXPECT_EQ(VPX_CODEC_OK, res); + InitializeEncoder(); + EXPECT_EQ(3, svc_.spatial_layers); +} + +TEST_F(SvcTest, SetMultipleOptions) { + vpx_codec_err_t res = + vpx_svc_set_options(&svc_, "spatial-layers=2 scale-factors=1/3,2/3"); + EXPECT_EQ(VPX_CODEC_OK, res); + InitializeEncoder(); + EXPECT_EQ(2, svc_.spatial_layers); +} + +TEST_F(SvcTest, SetScaleFactorsOption) { + svc_.spatial_layers = 2; + vpx_codec_err_t res = + vpx_svc_set_options(&svc_, "scale-factors=not-scale-factors"); + EXPECT_EQ(VPX_CODEC_OK, res); + res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); + + res = vpx_svc_set_options(&svc_, "scale-factors=1/3, 3*3"); + EXPECT_EQ(VPX_CODEC_OK, res); + res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); + + res = vpx_svc_set_options(&svc_, "scale-factors=1/3"); + EXPECT_EQ(VPX_CODEC_OK, res); + res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); + + res = vpx_svc_set_options(&svc_, "scale-factors=1/3,2/3"); + EXPECT_EQ(VPX_CODEC_OK, res); + InitializeEncoder(); +} + +TEST_F(SvcTest, SetQuantizersOption) { + svc_.spatial_layers = 2; + vpx_codec_err_t res = vpx_svc_set_options(&svc_, "max-quantizers=nothing"); + EXPECT_EQ(VPX_CODEC_OK, res); + res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); + + res = vpx_svc_set_options(&svc_, "min-quantizers=nothing"); + EXPECT_EQ(VPX_CODEC_OK, res); + res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); + + res = vpx_svc_set_options(&svc_, "max-quantizers=40"); + EXPECT_EQ(VPX_CODEC_OK, res); + res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); + + res = vpx_svc_set_options(&svc_, "min-quantizers=40"); + EXPECT_EQ(VPX_CODEC_OK, res); + res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); + + res = vpx_svc_set_options(&svc_, "max-quantizers=30,30 min-quantizers=40,40"); + EXPECT_EQ(VPX_CODEC_OK, res); + res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); + + res = vpx_svc_set_options(&svc_, "max-quantizers=40,40 min-quantizers=30,30"); + InitializeEncoder(); +} + +TEST_F(SvcTest, SetAutoAltRefOption) { + svc_.spatial_layers = 5; + vpx_codec_err_t res = vpx_svc_set_options(&svc_, "auto-alt-refs=none"); + EXPECT_EQ(VPX_CODEC_OK, res); + res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); + + res = vpx_svc_set_options(&svc_, "auto-alt-refs=1,1,1,1,0"); + EXPECT_EQ(VPX_CODEC_OK, res); + res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); + + vpx_svc_set_options(&svc_, "auto-alt-refs=0,1,1,1,0"); + InitializeEncoder(); +} + +// Test that decoder can handle an SVC frame as the first frame in a sequence. +TEST_F(SvcTest, OnePassEncodeOneFrame) { + codec_enc_.g_pass = VPX_RC_ONE_PASS; + vpx_fixed_buf output = {0}; + Pass2EncodeNFrames(NULL, 1, 2, &output); + DecodeNFrames(&output, 1); + FreeBitstreamBuffers(&output, 1); +} + +TEST_F(SvcTest, OnePassEncodeThreeFrames) { + codec_enc_.g_pass = VPX_RC_ONE_PASS; + codec_enc_.g_lag_in_frames = 0; + vpx_fixed_buf outputs[3]; + memset(&outputs[0], 0, sizeof(outputs)); + Pass2EncodeNFrames(NULL, 3, 2, &outputs[0]); + DecodeNFrames(&outputs[0], 3); + FreeBitstreamBuffers(&outputs[0], 3); +} + +TEST_F(SvcTest, TwoPassEncode10Frames) { + // First pass encode + std::string stats_buf; + Pass1EncodeNFrames(10, 2, &stats_buf); + + // Second pass encode + codec_enc_.g_pass = VPX_RC_LAST_PASS; + vpx_fixed_buf outputs[10]; + memset(&outputs[0], 0, sizeof(outputs)); + Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]); + DecodeNFrames(&outputs[0], 10); + FreeBitstreamBuffers(&outputs[0], 10); +} + +TEST_F(SvcTest, TwoPassEncode20FramesWithAltRef) { + // First pass encode + std::string stats_buf; + Pass1EncodeNFrames(20, 2, &stats_buf); + + // Second pass encode + codec_enc_.g_pass = VPX_RC_LAST_PASS; + vpx_svc_set_options(&svc_, "auto-alt-refs=1,1"); + vpx_fixed_buf outputs[20]; + memset(&outputs[0], 0, sizeof(outputs)); + Pass2EncodeNFrames(&stats_buf, 20, 2, &outputs[0]); + DecodeNFrames(&outputs[0], 20); + FreeBitstreamBuffers(&outputs[0], 20); +} + +TEST_F(SvcTest, TwoPassEncode2SpatialLayersDecodeBaseLayerOnly) { + // First pass encode + std::string stats_buf; + Pass1EncodeNFrames(10, 2, &stats_buf); + + // Second pass encode + codec_enc_.g_pass = VPX_RC_LAST_PASS; + vpx_svc_set_options(&svc_, "auto-alt-refs=1,1"); + vpx_fixed_buf outputs[10]; + memset(&outputs[0], 0, sizeof(outputs)); + Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]); + DropEnhancementLayers(&outputs[0], 10, 1); + DecodeNFrames(&outputs[0], 10); + FreeBitstreamBuffers(&outputs[0], 10); +} + +TEST_F(SvcTest, TwoPassEncode5SpatialLayersDecode54321Layers) { + // First pass encode + std::string stats_buf; + Pass1EncodeNFrames(10, 5, &stats_buf); + + // Second pass encode + codec_enc_.g_pass = VPX_RC_LAST_PASS; + vpx_svc_set_options(&svc_, "auto-alt-refs=0,1,1,1,0"); + vpx_fixed_buf outputs[10]; + memset(&outputs[0], 0, sizeof(outputs)); + Pass2EncodeNFrames(&stats_buf, 10, 5, &outputs[0]); + + DecodeNFrames(&outputs[0], 10); + DropEnhancementLayers(&outputs[0], 10, 4); + DecodeNFrames(&outputs[0], 10); + DropEnhancementLayers(&outputs[0], 10, 3); + DecodeNFrames(&outputs[0], 10); + DropEnhancementLayers(&outputs[0], 10, 2); + DecodeNFrames(&outputs[0], 10); + DropEnhancementLayers(&outputs[0], 10, 1); + DecodeNFrames(&outputs[0], 10); + + FreeBitstreamBuffers(&outputs[0], 10); +} + +TEST_F(SvcTest, TwoPassEncode2SNRLayers) { + // First pass encode + std::string stats_buf; + vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1"); + Pass1EncodeNFrames(20, 2, &stats_buf); + + // Second pass encode + codec_enc_.g_pass = VPX_RC_LAST_PASS; + vpx_svc_set_options(&svc_, + "auto-alt-refs=1,1 scale-factors=1/1,1/1"); + vpx_fixed_buf outputs[20]; + memset(&outputs[0], 0, sizeof(outputs)); + Pass2EncodeNFrames(&stats_buf, 20, 2, &outputs[0]); + DecodeNFrames(&outputs[0], 20); + FreeBitstreamBuffers(&outputs[0], 20); +} + +TEST_F(SvcTest, TwoPassEncode3SNRLayersDecode321Layers) { + // First pass encode + std::string stats_buf; + vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1,1/1"); + Pass1EncodeNFrames(20, 3, &stats_buf); + + // Second pass encode + codec_enc_.g_pass = VPX_RC_LAST_PASS; + vpx_svc_set_options(&svc_, + "auto-alt-refs=1,1,1 scale-factors=1/1,1/1,1/1"); + vpx_fixed_buf outputs[20]; + memset(&outputs[0], 0, sizeof(outputs)); + Pass2EncodeNFrames(&stats_buf, 20, 3, &outputs[0]); + DecodeNFrames(&outputs[0], 20); + DropEnhancementLayers(&outputs[0], 20, 2); + DecodeNFrames(&outputs[0], 20); + DropEnhancementLayers(&outputs[0], 20, 1); + DecodeNFrames(&outputs[0], 20); + + FreeBitstreamBuffers(&outputs[0], 20); +} + +TEST_F(SvcTest, SetMultipleFrameContextsOption) { + svc_.spatial_layers = 5; + vpx_codec_err_t res = + vpx_svc_set_options(&svc_, "multi-frame-contexts=1"); + EXPECT_EQ(VPX_CODEC_OK, res); + res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_); + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res); + + svc_.spatial_layers = 2; + res = vpx_svc_set_options(&svc_, "multi-frame-contexts=1"); + InitializeEncoder(); +} + +TEST_F(SvcTest, TwoPassEncode2SpatialLayersWithMultipleFrameContexts) { + // First pass encode + std::string stats_buf; + Pass1EncodeNFrames(10, 2, &stats_buf); + + // Second pass encode + codec_enc_.g_pass = VPX_RC_LAST_PASS; + codec_enc_.g_error_resilient = 0; + vpx_svc_set_options(&svc_, "auto-alt-refs=1,1 multi-frame-contexts=1"); + vpx_fixed_buf outputs[10]; + memset(&outputs[0], 0, sizeof(outputs)); + Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]); + DecodeNFrames(&outputs[0], 10); + FreeBitstreamBuffers(&outputs[0], 10); +} + +TEST_F(SvcTest, + TwoPassEncode2SpatialLayersWithMultipleFrameContextsDecodeBaselayer) { + // First pass encode + std::string stats_buf; + Pass1EncodeNFrames(10, 2, &stats_buf); + + // Second pass encode + codec_enc_.g_pass = VPX_RC_LAST_PASS; + codec_enc_.g_error_resilient = 0; + vpx_svc_set_options(&svc_, "auto-alt-refs=1,1 multi-frame-contexts=1"); + vpx_fixed_buf outputs[10]; + memset(&outputs[0], 0, sizeof(outputs)); + Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]); + DropEnhancementLayers(&outputs[0], 10, 1); + DecodeNFrames(&outputs[0], 10); + FreeBitstreamBuffers(&outputs[0], 10); +} + +TEST_F(SvcTest, TwoPassEncode2SNRLayersWithMultipleFrameContexts) { + // First pass encode + std::string stats_buf; + vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1"); + Pass1EncodeNFrames(10, 2, &stats_buf); + + // Second pass encode + codec_enc_.g_pass = VPX_RC_LAST_PASS; + codec_enc_.g_error_resilient = 0; + vpx_svc_set_options(&svc_, "auto-alt-refs=1,1 scale-factors=1/1,1/1 " + "multi-frame-contexts=1"); + vpx_fixed_buf outputs[10]; + memset(&outputs[0], 0, sizeof(outputs)); + Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]); + DecodeNFrames(&outputs[0], 10); + FreeBitstreamBuffers(&outputs[0], 10); +} + +TEST_F(SvcTest, + TwoPassEncode3SNRLayersWithMultipleFrameContextsDecode321Layer) { + // First pass encode + std::string stats_buf; + vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1,1/1"); + Pass1EncodeNFrames(10, 3, &stats_buf); + + // Second pass encode + codec_enc_.g_pass = VPX_RC_LAST_PASS; + codec_enc_.g_error_resilient = 0; + vpx_svc_set_options(&svc_, "auto-alt-refs=1,1,1 scale-factors=1/1,1/1,1/1 " + "multi-frame-contexts=1"); + vpx_fixed_buf outputs[10]; + memset(&outputs[0], 0, sizeof(outputs)); + Pass2EncodeNFrames(&stats_buf, 10, 3, &outputs[0]); + + DecodeNFrames(&outputs[0], 10); + DropEnhancementLayers(&outputs[0], 10, 2); + DecodeNFrames(&outputs[0], 10); + DropEnhancementLayers(&outputs[0], 10, 1); + DecodeNFrames(&outputs[0], 10); + + FreeBitstreamBuffers(&outputs[0], 10); +} + +TEST_F(SvcTest, TwoPassEncode2TemporalLayers) { + // First pass encode + std::string stats_buf; + vpx_svc_set_options(&svc_, "scale-factors=1/1"); + svc_.temporal_layers = 2; + Pass1EncodeNFrames(10, 1, &stats_buf); + + // Second pass encode + codec_enc_.g_pass = VPX_RC_LAST_PASS; + svc_.temporal_layers = 2; + vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1"); + vpx_fixed_buf outputs[10]; + memset(&outputs[0], 0, sizeof(outputs)); + Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]); + DecodeNFrames(&outputs[0], 10); + FreeBitstreamBuffers(&outputs[0], 10); +} + +TEST_F(SvcTest, TwoPassEncode2TemporalLayersWithMultipleFrameContexts) { + // First pass encode + std::string stats_buf; + vpx_svc_set_options(&svc_, "scale-factors=1/1"); + svc_.temporal_layers = 2; + Pass1EncodeNFrames(10, 1, &stats_buf); + + // Second pass encode + codec_enc_.g_pass = VPX_RC_LAST_PASS; + svc_.temporal_layers = 2; + codec_enc_.g_error_resilient = 0; + vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1 " + "multi-frame-contexts=1"); + vpx_fixed_buf outputs[10]; + memset(&outputs[0], 0, sizeof(outputs)); + Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]); + DecodeNFrames(&outputs[0], 10); + FreeBitstreamBuffers(&outputs[0], 10); +} + +TEST_F(SvcTest, TwoPassEncode2TemporalLayersDecodeBaseLayer) { + // First pass encode + std::string stats_buf; + vpx_svc_set_options(&svc_, "scale-factors=1/1"); + svc_.temporal_layers = 2; + Pass1EncodeNFrames(10, 1, &stats_buf); + + // Second pass encode + codec_enc_.g_pass = VPX_RC_LAST_PASS; + svc_.temporal_layers = 2; + vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1"); + vpx_fixed_buf outputs[10]; + memset(&outputs[0], 0, sizeof(outputs)); + Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]); + + vpx_fixed_buf base_layer[5]; + for (int i = 0; i < 5; ++i) + base_layer[i] = outputs[i * 2]; + + DecodeNFrames(&base_layer[0], 5); + FreeBitstreamBuffers(&outputs[0], 10); +} + +TEST_F(SvcTest, + TwoPassEncode2TemporalLayersWithMultipleFrameContextsDecodeBaseLayer) { + // First pass encode + std::string stats_buf; + vpx_svc_set_options(&svc_, "scale-factors=1/1"); + svc_.temporal_layers = 2; + Pass1EncodeNFrames(10, 1, &stats_buf); + + // Second pass encode + codec_enc_.g_pass = VPX_RC_LAST_PASS; + svc_.temporal_layers = 2; + codec_enc_.g_error_resilient = 0; + vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1 " + "multi-frame-contexts=1"); + vpx_fixed_buf outputs[10]; + memset(&outputs[0], 0, sizeof(outputs)); + Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]); + + vpx_fixed_buf base_layer[5]; + for (int i = 0; i < 5; ++i) + base_layer[i] = outputs[i * 2]; + + DecodeNFrames(&base_layer[0], 5); + FreeBitstreamBuffers(&outputs[0], 10); +} + +TEST_F(SvcTest, TwoPassEncode2TemporalLayersWithTiles) { + // First pass encode + std::string stats_buf; + vpx_svc_set_options(&svc_, "scale-factors=1/1"); + svc_.temporal_layers = 2; + Pass1EncodeNFrames(10, 1, &stats_buf); + + // Second pass encode + codec_enc_.g_pass = VPX_RC_LAST_PASS; + svc_.temporal_layers = 2; + vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1"); + codec_enc_.g_w = 704; + codec_enc_.g_h = 144; + tile_columns_ = 1; + tile_rows_ = 1; + vpx_fixed_buf outputs[10]; + memset(&outputs[0], 0, sizeof(outputs)); + Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]); + DecodeNFrames(&outputs[0], 10); + FreeBitstreamBuffers(&outputs[0], 10); +} + +TEST_F(SvcTest, + TwoPassEncode2TemporalLayersWithMultipleFrameContextsAndTiles) { + // First pass encode + std::string stats_buf; + vpx_svc_set_options(&svc_, "scale-factors=1/1"); + svc_.temporal_layers = 2; + Pass1EncodeNFrames(10, 1, &stats_buf); + + // Second pass encode + codec_enc_.g_pass = VPX_RC_LAST_PASS; + svc_.temporal_layers = 2; + codec_enc_.g_error_resilient = 0; + codec_enc_.g_w = 704; + codec_enc_.g_h = 144; + tile_columns_ = 1; + tile_rows_ = 1; + vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1 " + "multi-frame-contexts=1"); + vpx_fixed_buf outputs[10]; + memset(&outputs[0], 0, sizeof(outputs)); + Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]); + DecodeNFrames(&outputs[0], 10); + FreeBitstreamBuffers(&outputs[0], 10); +} + +} // namespace
diff --git a/src/third_party/libvpx/test/test-data.mk b/src/third_party/libvpx/test/test-data.mk new file mode 100644 index 0000000..05a0885 --- /dev/null +++ b/src/third_party/libvpx/test/test-data.mk
@@ -0,0 +1,863 @@ +LIBVPX_TEST_SRCS-yes += test-data.mk + +# Encoder test source +LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += hantro_collage_w352h288.yuv +LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += hantro_odd.yuv + +LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_10_420.y4m +LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_10_422.y4m +LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_10_444.y4m +LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_10_440.yuv +LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_12_420.y4m +LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_12_422.y4m +LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_12_444.y4m +LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_12_440.yuv +LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_8_420_a10-1.y4m +LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_8_420.y4m +LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_8_422.y4m +LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_8_444.y4m +LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_8_440.yuv + +LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += desktop_credits.y4m +LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += niklas_1280_720_30.y4m +LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += rush_hour_444.y4m +LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += screendata.y4m + +# Test vectors +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-001.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-001.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-002.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-002.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-003.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-003.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-004.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-004.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-005.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-005.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-006.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-006.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-007.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-007.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-008.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-008.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-009.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-009.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-010.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-010.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-011.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-011.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-012.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-012.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-013.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-013.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-014.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-014.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-015.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-015.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-016.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-016.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-017.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-017.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-018.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-018.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-01-intra-1400.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-01-intra-1400.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-01-intra-1411.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-01-intra-1411.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-01-intra-1416.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-01-intra-1416.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-01-intra-1417.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-01-intra-1417.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-02-inter-1402.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-02-inter-1402.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-02-inter-1412.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-02-inter-1412.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-02-inter-1418.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-02-inter-1418.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-02-inter-1424.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-02-inter-1424.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-01.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-01.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-02.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-02.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-03.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-03.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-04.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-04.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1401.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1401.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1403.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1403.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1407.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1407.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1408.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1408.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1409.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1409.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1410.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1410.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1413.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1413.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1414.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1414.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1415.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1415.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1425.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1425.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1426.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1426.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1427.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1427.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1432.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1432.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1435.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1435.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1436.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1436.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1437.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1437.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1441.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1441.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1442.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1442.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-04-partitions-1404.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-04-partitions-1404.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-04-partitions-1405.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-04-partitions-1405.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-04-partitions-1406.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-04-partitions-1406.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1428.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1428.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1429.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1429.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1430.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1430.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1431.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1431.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1433.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1433.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1434.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1434.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1438.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1438.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1439.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1439.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1440.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1440.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1443.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1443.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-06-smallsize.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-06-smallsize.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-00.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-00.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-01.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-01.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-02.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-02.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-03.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-03.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-04.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-04.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-05.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-05.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-06.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-06.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-07.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-07.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-08.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-08.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-09.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-09.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-10.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-10.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-11.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-11.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-12.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-12.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-13.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-13.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-14.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-14.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-15.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-15.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-16.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-16.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-17.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-17.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-18.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-18.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-19.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-19.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-20.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-20.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-21.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-21.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-22.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-22.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-23.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-23.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-24.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-24.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-25.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-25.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-26.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-26.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-27.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-27.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-28.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-28.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-29.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-29.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-30.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-30.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-31.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-31.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-32.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-32.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-33.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-33.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-34.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-34.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-35.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-35.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-36.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-36.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-37.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-37.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-38.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-38.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-39.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-39.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-40.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-40.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-41.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-41.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-42.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-42.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-43.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-43.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-44.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-44.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-45.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-45.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-46.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-46.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-47.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-47.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-48.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-48.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-49.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-49.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-50.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-50.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-51.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-51.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-52.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-52.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-53.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-53.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-54.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-54.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-55.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-55.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-56.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-56.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-57.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-57.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-58.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-58.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-59.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-59.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-60.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-60.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-61.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-61.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-62.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-62.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-63.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-63.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-1.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-1.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-2.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-3.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-3.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-4.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-4.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-5.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-5.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-6.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-6.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-7.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-7.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x08.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x08.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x10.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x10.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x16.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x16.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x18.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x18.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x32.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x32.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x34.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x34.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x64.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x64.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x66.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x66.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x08.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x08.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x10.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x10.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x16.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x16.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x18.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x18.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x32.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x32.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x34.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x34.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x64.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x64.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x66.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x66.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x08.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x08.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x10.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x10.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x16.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x16.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x18.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x18.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x32.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x32.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x34.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x34.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x64.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x64.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x66.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x66.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x08.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x08.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x10.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x10.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x16.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x16.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x18.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x18.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x32.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x32.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x34.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x34.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x64.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x64.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x66.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x66.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x08.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x08.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x10.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x10.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x16.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x16.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x18.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x18.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x32.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x32.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x34.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x34.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x64.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x64.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x66.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x66.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x08.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x08.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x10.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x10.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x16.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x16.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x18.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x18.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x32.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x32.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x34.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x34.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x64.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x64.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x66.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x66.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x08.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x08.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x10.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x10.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x16.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x16.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x18.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x18.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x32.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x32.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x34.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x34.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x64.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x64.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x66.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x66.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x08.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x08.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x10.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x10.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x16.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x16.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x18.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x18.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x32.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x32.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x34.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x34.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x64.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x64.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x66.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x66.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-130x132.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-130x132.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-132x130.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-132x130.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-132x132.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-132x132.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-178x180.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-178x180.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-180x178.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-180x178.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-180x180.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-180x180.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-lf-1920x1080.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-lf-1920x1080.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-deltaq.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-deltaq.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x196.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x196.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x198.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x198.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x200.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x200.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x202.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x202.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x208.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x208.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x210.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x210.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x224.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x224.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x226.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x226.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x196.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x196.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x198.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x198.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x200.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x200.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x202.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x202.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x208.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x208.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x210.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x210.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x224.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x224.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x226.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x226.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x196.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x196.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x198.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x198.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x200.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x200.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x202.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x202.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x208.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x208.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x210.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x210.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x224.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x224.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x226.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x226.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x196.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x196.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x198.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x198.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x200.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x200.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x202.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x202.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x208.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x208.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x210.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x210.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x224.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x224.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x226.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x226.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x196.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x196.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x198.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x198.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x200.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x200.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x202.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x202.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x208.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x208.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x210.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x210.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x224.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x224.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x226.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x226.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x196.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x196.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x198.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x198.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x200.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x200.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x202.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x202.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x208.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x208.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x210.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x210.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x224.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x224.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x226.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x226.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x196.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x196.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x198.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x198.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x200.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x200.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x202.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x202.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x208.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x208.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x210.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x210.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x224.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x224.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x226.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x226.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x196.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x196.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x198.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x198.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x200.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x200.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x202.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x202.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x208.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x208.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x210.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x210.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x224.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x224.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x226.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x226.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-352x288.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-352x288.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-05-resize.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-05-resize.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-06-bilinear.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-06-bilinear.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-07-frame_parallel.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-07-frame_parallel.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-07-frame_parallel-1.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-07-frame_parallel-1.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile-4x1.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile-4x1.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile-4x4.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile-4x4.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x2.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x2_frame_parallel.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x2_frame_parallel.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x4.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x4.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x4_frame_parallel.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x4_frame_parallel.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x8.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x8.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x8_frame_parallel.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x8_frame_parallel.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-aq2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-aq2.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-lf_deltas.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-lf_deltas.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-subpixel-00.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-subpixel-00.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-10-show-existing-frame.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-10-show-existing-frame.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-10-show-existing-frame2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-10-show-existing-frame2.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-11-size-351x287.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-11-size-351x287.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-11-size-351x288.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-11-size-351x288.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-11-size-352x287.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-11-size-352x287.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-12-droppable_1.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-12-droppable_1.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-12-droppable_2.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-12-droppable_2.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-12-droppable_3.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-12-droppable_3.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-13-largescaling.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-13-largescaling.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-16.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-16.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-2-4-8-16.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-2-4-8-16.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-2.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-4.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-4.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-8.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-8.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-1.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-1.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-2.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-4.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-4.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-8-4-2-1.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-8-4-2-1.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-8.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-8.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-2-1.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-2-1.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-2-16.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-2-16.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-2-4.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-2-4.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-2-8.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-2-8.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-4-1.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-4-1.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-4-16.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-4-16.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-4-2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-4-2.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-4-8.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-4-8.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-8-1.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-8-1.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-8-16.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-8-16.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-8-2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-8-2.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-8-4.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-8-4.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-1-2-4-8.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-1-2-4-8.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-1-2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-1-2.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-1-4.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-1-4.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-1-8.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-1-8.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-2-1.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-2-1.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-2-4.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-2-4.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-2-8.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-2-8.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-4-1.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-4-1.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-4-2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-4-2.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-4-8.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-4-8.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-8-1.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-8-1.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-8-2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-8-2.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-8-4-2-1.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-8-4-2-1.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-8-4.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-8-4.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-15-segkey.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-15-segkey.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-15-segkey_adpq.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-15-segkey_adpq.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-16-intra-only.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-16-intra-only.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-17-show-existing-frame.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-17-show-existing-frame.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-18-resize.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-18-resize.ivf.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-19-skip.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-19-skip.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-19-skip-01.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-19-skip-01.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-19-skip-02.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-19-skip-02.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yuv422.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yuv422.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yuv440.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yuv440.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yuv444.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yuv444.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-20-big_superframe-01.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-20-big_superframe-01.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-20-big_superframe-02.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-20-big_superframe-02.webm.md5 +ifeq ($(CONFIG_VP9_HIGHBITDEPTH),yes) +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp92-2-20-10bit-yuv420.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp92-2-20-10bit-yuv420.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp92-2-20-12bit-yuv420.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp92-2-20-12bit-yuv420.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-10bit-yuv422.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-10bit-yuv422.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-12bit-yuv422.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-12bit-yuv422.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-10bit-yuv440.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-10bit-yuv440.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-12bit-yuv440.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-12bit-yuv440.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-10bit-yuv444.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-10bit-yuv444.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-12bit-yuv444.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-12bit-yuv444.webm.md5 +endif # CONFIG_VP9_HIGHBITDEPTH + +# Invalid files for testing libvpx error checking. +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-01-v3.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-01-v3.webm.res +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-02-v2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-02-v2.webm.res +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-03-v3.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-03-v3.webm.res +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf.res +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf.res +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf.res +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-03-size-202x210.webm.ivf.s113306_r01-05_b6-.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-03-size-202x210.webm.ivf.s113306_r01-05_b6-.ivf.res +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-03-size-224x196.webm.ivf.s44156_r01-05_b6-.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-03-size-224x196.webm.ivf.s44156_r01-05_b6-.ivf.res +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-05-resize.ivf.s59293_r01-05_b6-.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-05-resize.ivf.s59293_r01-05_b6-.ivf.res +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-08-tile_1x2_frame_parallel.webm.ivf.s47039_r01-05_b6-.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-08-tile_1x2_frame_parallel.webm.ivf.s47039_r01-05_b6-.ivf.res +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-08-tile_1x8_frame_parallel.webm.ivf.s288_r01-05_b6-.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-08-tile_1x8_frame_parallel.webm.ivf.s288_r01-05_b6-.ivf.res +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-08-tile_1x4_frame_parallel_all_key.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-08-tile_1x4_frame_parallel_all_key.webm.res +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-09-aq2.webm.ivf.s3984_r01-05_b6-.v2.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-09-aq2.webm.ivf.s3984_r01-05_b6-.v2.ivf.res +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-09-subpixel-00.ivf.s19552_r01-05_b6-.v2.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-09-subpixel-00.ivf.s19552_r01-05_b6-.v2.ivf.res +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-09-subpixel-00.ivf.s20492_r01-05_b6-.v2.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-09-subpixel-00.ivf.s20492_r01-05_b6-.v2.ivf.res +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-12-droppable_1.ivf.s3676_r01-05_b6-.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-12-droppable_1.ivf.s3676_r01-05_b6-.ivf.res +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-12-droppable_1.ivf.s73804_r01-05_b6-.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-12-droppable_1.ivf.s73804_r01-05_b6-.ivf.res +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp91-2-mixedrefcsp-444to420.ivf +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp91-2-mixedrefcsp-444to420.ivf.res +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-07-frame_parallel-1.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-07-frame_parallel-2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-07-frame_parallel-3.webm + +ifeq ($(CONFIG_DECODE_PERF_TESTS),yes) +# Encode / Decode test +LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += niklas_1280_720_30.yuv +# BBB VP9 streams +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-bbb_426x240_tile_1x1_180kbps.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-bbb_640x360_tile_1x2_337kbps.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-bbb_854x480_tile_1x2_651kbps.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-bbb_1280x720_tile_1x4_1310kbps.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-bbb_1920x1080_tile_1x1_2581kbps.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-bbb_1920x1080_tile_1x4_2586kbps.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-bbb_1920x1080_tile_1x4_fpm_2304kbps.webm +# Sintel VP9 streams +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-sintel_426x182_tile_1x1_171kbps.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-sintel_640x272_tile_1x2_318kbps.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-sintel_854x364_tile_1x2_621kbps.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-sintel_1280x546_tile_1x4_1257kbps.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-sintel_1920x818_tile_1x4_fpm_2279kbps.webm +# TOS VP9 streams +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-tos_426x178_tile_1x1_181kbps.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-tos_640x266_tile_1x2_336kbps.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-tos_854x356_tile_1x2_656kbps.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-tos_854x356_tile_1x2_fpm_546kbps.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-tos_1280x534_tile_1x4_1306kbps.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-tos_1280x534_tile_1x4_fpm_952kbps.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-tos_1920x800_tile_1x4_fpm_2335kbps.webm +endif # CONFIG_DECODE_PERF_TESTS + +ifeq ($(CONFIG_ENCODE_PERF_TESTS),yes) +LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += desktop_640_360_30.yuv +LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += kirland_640_480_30.yuv +LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += macmarcomoving_640_480_30.yuv +LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += macmarcostationary_640_480_30.yuv +LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += niklas_1280_720_30.yuv +LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += niklas_640_480_30.yuv +LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += tacomanarrows_640_480_30.yuv +LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += tacomasmallcameramovement_640_480_30.yuv +LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += thaloundeskmtg_640_480_30.yuv +endif # CONFIG_ENCODE_PERF_TESTS + +# sort and remove duplicates +LIBVPX_TEST_DATA-yes := $(sort $(LIBVPX_TEST_DATA-yes)) + +# VP9 dynamic resizing test (decoder) +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x180_5_1-2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x180_5_1-2.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x180_5_3-4.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x180_5_3-4.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x180_7_1-2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x180_7_1-2.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x180_7_3-4.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x180_7_3-4.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x240_5_1-2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x240_5_1-2.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x240_5_3-4.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x240_5_3-4.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x240_7_1-2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x240_7_1-2.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x240_7_3-4.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x240_7_3-4.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x360_5_1-2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x360_5_1-2.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x360_5_3-4.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x360_5_3-4.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x360_7_1-2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x360_7_1-2.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x360_7_3-4.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x360_7_3-4.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x480_5_1-2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x480_5_1-2.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x480_5_3-4.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x480_5_3-4.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x480_7_1-2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x480_7_1-2.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x480_7_3-4.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x480_7_3-4.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1280x720_5_1-2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1280x720_5_1-2.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1280x720_5_3-4.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1280x720_5_3-4.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1280x720_7_1-2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1280x720_7_1-2.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1280x720_7_3-4.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1280x720_7_3-4.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1920x1080_5_1-2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1920x1080_5_1-2.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1920x1080_5_3-4.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1920x1080_5_3-4.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1920x1080_7_1-2.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1920x1080_7_1-2.webm.md5 +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1920x1080_7_3-4.webm +LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1920x1080_7_3-4.webm.md5
diff --git a/src/third_party/libvpx/test/test-data.sha1 b/src/third_party/libvpx/test/test-data.sha1 new file mode 100644 index 0000000..a4ed174 --- /dev/null +++ b/src/third_party/libvpx/test/test-data.sha1
@@ -0,0 +1,836 @@ +d5dfb0151c9051f8c85999255645d7a23916d3c0 *hantro_collage_w352h288.yuv +b87815bf86020c592ccc7a846ba2e28ec8043902 *hantro_odd.yuv +76024eb753cdac6a5e5703aaea189d35c3c30ac7 *invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf +7448d8798a4380162d4b56f9b452e2f6f9e24e7a *invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf.res +83f50908c8dc0ef8760595447a2ff7727489542e *invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf +456d1493e52d32a5c30edf44a27debc1fa6b253a *invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf.res +c123d1f9f02fb4143abb5e271916e3a3080de8f6 *invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf +456d1493e52d32a5c30edf44a27debc1fa6b253a *invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf.res +fe346136b9b8c1e6f6084cc106485706915795e4 *invalid-vp90-01-v3.webm +5d9474c0309b7ca09a182d888f73b37a8fe1362c *invalid-vp90-01-v3.webm.res +d78e2fceba5ac942246503ec8366f879c4775ca5 *invalid-vp90-02-v2.webm +8e2eff4af87d2b561cce2365713269e301457ef3 *invalid-vp90-02-v2.webm.res +df1a1453feb3c00d7d89746c7003b4163523bff3 *invalid-vp90-03-v3.webm +4935c62becc68c13642a03db1e6d3e2331c1c612 *invalid-vp90-03-v3.webm.res +d637297561dd904eb2c97a9015deeb31c4a1e8d2 *invalid-vp90-2-08-tile_1x4_frame_parallel_all_key.webm +3a204bdbeaa3c6458b77bcebb8366d107267f55d *invalid-vp90-2-08-tile_1x4_frame_parallel_all_key.webm.res +a432f96ff0a787268e2f94a8092ab161a18d1b06 *park_joy_90p_10_420.y4m +0b194cc312c3a2e84d156a221b0a5eb615dfddc5 *park_joy_90p_10_422.y4m +ff0e0a21dc2adc95b8c1b37902713700655ced17 *park_joy_90p_10_444.y4m +c934da6fb8cc54ee2a8c17c54cf6076dac37ead0 *park_joy_90p_10_440.yuv +614c32ae1eca391e867c70d19974f0d62664dd99 *park_joy_90p_12_420.y4m +c92825f1ea25c5c37855083a69faac6ac4641a9e *park_joy_90p_12_422.y4m +b592189b885b6cc85db55cc98512a197d73d3b34 *park_joy_90p_12_444.y4m +82c1bfcca368c2f22bad7d693d690d5499ecdd11 *park_joy_90p_12_440.yuv +b9e1e90aece2be6e2c90d89e6ab2372d5f8c792d *park_joy_90p_8_420_a10-1.y4m +4e0eb61e76f0684188d9bc9f3ce61f6b6b77bb2c *park_joy_90p_8_420.y4m +7a193ff7dfeb96ba5f82b2afd7afa9e1fe83d947 *park_joy_90p_8_422.y4m +bdb7856e6bc93599bdda05c2e773a9f22b6c6d03 *park_joy_90p_8_444.y4m +81e1f3843748438b8f2e71db484eb22daf72e939 *park_joy_90p_8_440.yuv +b1f1c3ec79114b9a0651af24ce634afb44a9a419 *rush_hour_444.y4m +5184c46ddca8b1fadd16742e8500115bc8f749da *vp80-00-comprehensive-001.ivf +65bf1bbbced81b97bd030f376d1b7f61a224793f *vp80-00-comprehensive-002.ivf +906b4c1e99eb734504c504b3f1ad8052137ce672 *vp80-00-comprehensive-003.ivf +ec144b1af53af895db78355785650b96dd3f0ade *vp80-00-comprehensive-004.ivf +afc7091785c62f1c121c4554a2830c30704587d9 *vp80-00-comprehensive-005.ivf +42ea9d55c818145d06a9b633b8e85c6a6164fd3e *vp80-00-comprehensive-006.ivf +e5b3a73ab79fe024c14309d653d6bed92902ee3b *vp80-00-comprehensive-007.ivf +f3c50a58875930adfb84525c0ef59d7e4c08540c *vp80-00-comprehensive-008.ivf +4b2841fdb83db51ae322096ae468bbb9dc2c8362 *vp80-00-comprehensive-009.ivf +efbff736e3a91ab6a98c5bc2dce65d645944c7b1 *vp80-00-comprehensive-010.ivf +6b315102cae008d22a3d2c231be92cb704a222f8 *vp80-00-comprehensive-011.ivf +f3214a4fea14c2d5ec689936c1613f274c859ee8 *vp80-00-comprehensive-012.ivf +e4094e96d308c8a35b74c480a43d853c5294cd34 *vp80-00-comprehensive-013.ivf +5b0adfaf60a69e0aaf3ec021a39d0a68fc0e1b5a *vp80-00-comprehensive-014.ivf +e8467688ddf26b5000664f904faf0d70506aa653 *vp80-00-comprehensive-015.ivf +aab55582337dfd2a39ff54fb2576a91910d49337 *vp80-00-comprehensive-016.ivf +1ba24724f80203c9bae4f1d0f99d534721980016 *vp80-00-comprehensive-017.ivf +143a15512b46f436280ddb4d0e6411eb4af434f2 *vp80-00-comprehensive-018.ivf +c5baeaf5714fdfb3a8bc960a8e33ac438e83b16b *vp80-01-intra-1400.ivf +f383955229afe3408453e316d11553d923ca60d5 *vp80-01-intra-1411.ivf +84e1f4343f174c9f3c83f834bac3196fb325bf2c *vp80-01-intra-1416.ivf +fb6e712a47dd57a28a3727d2ae2c97a8b7c7ca51 *vp80-01-intra-1417.ivf +71ea772d3e9d315b8cbecf41207b8a237c34853b *vp80-02-inter-1402.ivf +d85dbc4271525dcd128c503f936fe69091d1f8d0 *vp80-02-inter-1412.ivf +d4e5d3ad56511867d025f93724d090f92ba6ec3d *vp80-02-inter-1418.ivf +91791cbcc37c60f35dbd8090bacb54e5ec6dd4fa *vp80-02-inter-1424.ivf +17fbfe2fea70f6e2f3fa6ca4efaae6c0b03b5f02 *vp80-03-segmentation-01.ivf +3c3600dbbcde08e20d54c66fe3b7eadd4f09bdbb *vp80-03-segmentation-02.ivf +c156778d5340967d4b369c490848076e92f1f875 *vp80-03-segmentation-03.ivf +d25dcff6c60e87a1af70945b8911b6b4998533b0 *vp80-03-segmentation-04.ivf +362baba2ce454c9db21218f35e81c27a5ed0b730 *vp80-03-segmentation-1401.ivf +d223ae7ee748ce07e74c4679bfd219e84aa9f4b0 *vp80-03-segmentation-1403.ivf +033adf7f3a13836a3f1cffcb87c1972900f2b5c6 *vp80-03-segmentation-1407.ivf +4d51dfbf9f3e2c590ec99d1d6f59dd731d04375f *vp80-03-segmentation-1408.ivf +f37a62b197c2600d75e0ccfbb31b60efdedac251 *vp80-03-segmentation-1409.ivf +eb25bd7bfba5b2f6935018a930f42d123b1e7fcd *vp80-03-segmentation-1410.ivf +b9d5c436663a30c27cfff84b53a002e501258843 *vp80-03-segmentation-1413.ivf +6da92b9d1a180cc3a8afe348ab12258f5a37be1a *vp80-03-segmentation-1414.ivf +a4f5842602886bd669f115f93d8a35c035cb0948 *vp80-03-segmentation-1415.ivf +f295dceb8ef278b77251b3f9df8aee22e161d547 *vp80-03-segmentation-1425.ivf +198dbf9f36f733200e432664cc8c5752d59779de *vp80-03-segmentation-1426.ivf +7704804e32f5de976803929934a7fafe101ac7b0 *vp80-03-segmentation-1427.ivf +831ccd862ea95ca025d2f3bd8b88678752f5416d *vp80-03-segmentation-1432.ivf +b3c11978529289f9109f2766fcaba3ebc40e11ef *vp80-03-segmentation-1435.ivf +a835a731f5520ebfc1002c40121264d0020559ac *vp80-03-segmentation-1436.ivf +1d1732942f773bb2a5775fcb9689b1579ce28eab *vp80-03-segmentation-1437.ivf +db04799adfe089dfdf74dbd43cc05ede7161f99e *vp80-03-segmentation-1441.ivf +7caf39b3f20cfd52b998210878062e52a5edf1e6 *vp80-03-segmentation-1442.ivf +3607f6bb4ee106c38fa1ea370dc4ff8b8cde2261 *vp80-04-partitions-1404.ivf +93cc323b6b6867f1b12dd48773424549c6960a6b *vp80-04-partitions-1405.ivf +047eedb14b865bdac8a3538e63801054e0295e9c *vp80-04-partitions-1406.ivf +0f1233bd2bc33f56ce5e495dbd455d122339f384 *vp80-05-sharpness-1428.ivf +51767fc136488a9535c2a4c38067c542ee2048df *vp80-05-sharpness-1429.ivf +9805aa107672de25d6fb8c35e20d06deca5efe18 *vp80-05-sharpness-1430.ivf +61db6b965f9c27aebe71b85bf2d5877e58e4bbdf *vp80-05-sharpness-1431.ivf +10420d266290d2923555f84af38eeb96edbd3ae8 *vp80-05-sharpness-1433.ivf +3ed24f9a80cddfdf75824ba95cdb4ff9286cb443 *vp80-05-sharpness-1434.ivf +c87599cbecd72d4cd4f7ace3313b7a6bc6eb8163 *vp80-05-sharpness-1438.ivf +aff51d865c2621b60510459244ea83e958e4baed *vp80-05-sharpness-1439.ivf +da386e72b19b5485a6af199c5eb60ef25e510dd1 *vp80-05-sharpness-1440.ivf +6759a095203d96ccd267ce09b1b050b8cc4c2f1f *vp80-05-sharpness-1443.ivf +b95d3cc1d0df991e63e150a801710a72f20d9ba0 *vp80-06-smallsize.ivf +db55ec7fd02c864ba996ff060b25b1e08611330b *vp80-00-comprehensive-001.ivf.md5 +29db0ad011cba1e45f856d5623cd38dac3e3bf19 *vp80-00-comprehensive-002.ivf.md5 +e84f258f69e173e7d68f8f8c037a0a3766902182 *vp80-00-comprehensive-003.ivf.md5 +eb7912eaf69559a16fd82bc3f5fb1524cf4a4466 *vp80-00-comprehensive-004.ivf.md5 +4206f71c94894bd5b5b376f6c09b3817dbc65206 *vp80-00-comprehensive-005.ivf.md5 +4f89b356f6f2fecb928f330a10f804f00f5325f5 *vp80-00-comprehensive-006.ivf.md5 +2813236a32964dd8007e17648bcf035a20fcda6c *vp80-00-comprehensive-007.ivf.md5 +10746c72098f872803c900e17c5680e451f5f498 *vp80-00-comprehensive-008.ivf.md5 +39a23d0692ce64421a7bb7cdf6ccec5928d37fff *vp80-00-comprehensive-009.ivf.md5 +f6e3de8931a0cc659bda8fbc14050346955e72d4 *vp80-00-comprehensive-010.ivf.md5 +101683ec195b6e944f7cd1e468fc8921439363e6 *vp80-00-comprehensive-011.ivf.md5 +1f592751ce46d8688998fa0fa4fbdcda0fd4058c *vp80-00-comprehensive-012.ivf.md5 +6066176f90ca790251e795fca1a5797d59999841 *vp80-00-comprehensive-013.ivf.md5 +2656da94ba93691f23edc4d60b3a09e2be46c217 *vp80-00-comprehensive-014.ivf.md5 +c6e0d5f5d61460c8ac8edfa4e701f10312c03133 *vp80-00-comprehensive-015.ivf.md5 +ee60fee501d8493e34e8d6a1fe315b51ed09b24a *vp80-00-comprehensive-016.ivf.md5 +9f1914ceffcad4546c0a29de3ef591d8bea304dc *vp80-00-comprehensive-017.ivf.md5 +e0305178fe288a9fd8082b39e2d03181edb19054 *vp80-00-comprehensive-018.ivf.md5 +612494da2fa799cc9d76dcdd835ae6c7cb2e5c05 *vp80-01-intra-1400.ivf.md5 +48ea06097ac8269c5e8c2131d3d0639f431fcf0e *vp80-01-intra-1411.ivf.md5 +6e2ab4e7677ad0ba868083ca6bc387ee922b400c *vp80-01-intra-1416.ivf.md5 +eca0a90348959ce3854142f8d8641b13050e8349 *vp80-01-intra-1417.ivf.md5 +920feea203145d5c2258a91c4e6991934a79a99e *vp80-02-inter-1402.ivf.md5 +f71d97909fe2b3dd65be7e1f56c72237f0cef200 *vp80-02-inter-1412.ivf.md5 +e911254569a30bbb2a237ff8b79f69ed9da0672d *vp80-02-inter-1418.ivf.md5 +58c789c50c9bb9cc90580bed291164a0939d28ba *vp80-02-inter-1424.ivf.md5 +ff3e2f441327b9c20a0b37c524e0f5a48a36de7b *vp80-03-segmentation-01.ivf.md5 +0791f417f076a542ae66fbc3426ab4d94cbd6c75 *vp80-03-segmentation-02.ivf.md5 +722e50f1a6a91c34302d68681faffc1c26d1cc57 *vp80-03-segmentation-03.ivf.md5 +c701f1885bcfb27fb8e70cc65606b289172ef889 *vp80-03-segmentation-04.ivf.md5 +f79bc9ec189a2b4807632a3d0c5bf04a178b5300 *vp80-03-segmentation-1401.ivf.md5 +b9aa4c74c0219b639811c44760d0b24cd8bb436a *vp80-03-segmentation-1403.ivf.md5 +70d5a2207ca1891bcaebd5cf6dd88ce8d57b4334 *vp80-03-segmentation-1407.ivf.md5 +265f962ee781531f9a93b9309461316fd32b2a1d *vp80-03-segmentation-1408.ivf.md5 +0c4ecbbd6dc042d30e626d951b65f460dd6cd563 *vp80-03-segmentation-1409.ivf.md5 +cf779af36a937f06570a0fca9db64ba133451dee *vp80-03-segmentation-1410.ivf.md5 +0e6c5036d51ab078842f133934926c598a9cff02 *vp80-03-segmentation-1413.ivf.md5 +eb3930aaf229116c80d507516c34759c3f6cdf69 *vp80-03-segmentation-1414.ivf.md5 +123d6c0f72ee87911c4ae7538e87b7d163b22d6c *vp80-03-segmentation-1415.ivf.md5 +e70551d1a38920e097a5d8782390b79ecaeb7505 *vp80-03-segmentation-1425.ivf.md5 +44e8f4117e46dbb302b2cfd81171cc1a1846e431 *vp80-03-segmentation-1426.ivf.md5 +52636e54aee5f95bbace37021bd67de5db767e9a *vp80-03-segmentation-1427.ivf.md5 +b1ad3eff20215c28e295b15ef3636ed926d59cba *vp80-03-segmentation-1432.ivf.md5 +24c22a552fa28a90e5978f67f57181cc2d7546d7 *vp80-03-segmentation-1435.ivf.md5 +96c49c390abfced18a7a8c9b9ea10af778e10edb *vp80-03-segmentation-1436.ivf.md5 +f95eb6214571434f1f73ab7833b9ccdf47588020 *vp80-03-segmentation-1437.ivf.md5 +1c0700ca27c9b0090a7747a4b0b4dc21d1843181 *vp80-03-segmentation-1441.ivf.md5 +81d4f23ca32667ee958bae579c8f5e97ba72eb97 *vp80-03-segmentation-1442.ivf.md5 +272efcef07a3a30fbca51bfd566063d8258ec0be *vp80-04-partitions-1404.ivf.md5 +66ed219ab812ac801b256d35cf495d193d4cf478 *vp80-04-partitions-1405.ivf.md5 +36083f37f56f502bd60ec5e07502ee9e6b8699b0 *vp80-04-partitions-1406.ivf.md5 +6ca909bf168a64c09415626294665dc1be3d1973 *vp80-05-sharpness-1428.ivf.md5 +1667d2ee2334e5fdea8a8a866f4ccf3cf76f033a *vp80-05-sharpness-1429.ivf.md5 +71bcbe5357d36a19df5b07fbe3e27bffa8893f0a *vp80-05-sharpness-1430.ivf.md5 +89a09b1dffce2d55770a89e58d9925c70ef79bf8 *vp80-05-sharpness-1431.ivf.md5 +08444a18b4e6ba3450c0796dd728d48c399a2dc9 *vp80-05-sharpness-1433.ivf.md5 +6d6223719a90c13e848aa2a8a6642098cdb5977a *vp80-05-sharpness-1434.ivf.md5 +41d70bb5fa45bc88da1604a0af466930b8dd77b5 *vp80-05-sharpness-1438.ivf.md5 +086c56378df81b6cee264d7540a7b8f2b405c7a4 *vp80-05-sharpness-1439.ivf.md5 +d32dc2c4165eb266ea4c23c14a45459b363def32 *vp80-05-sharpness-1440.ivf.md5 +8c69dc3d8e563f56ffab5ad1e400d9e689dd23df *vp80-05-sharpness-1443.ivf.md5 +d6f246df012c241b5fa6c1345019a3703d85c419 *vp80-06-smallsize.ivf.md5 +ce881e567fe1d0fbcb2d3e9e6281a1a8d74d82e0 *vp90-2-00-quantizer-00.webm +ac5eda33407d0521c7afca43a63fd305c0cd9d13 *vp90-2-00-quantizer-00.webm.md5 +2ca0463f2cfb93d25d7dded174db70b7cb87cb48 *vp90-2-00-quantizer-01.webm +10d98884fc6d9a5f47a2057922b8e25dd48d7786 *vp90-2-00-quantizer-01.webm.md5 +d80a2920a5e0819d69dcba8fe260c01f820f8982 *vp90-2-00-quantizer-02.webm +c964c8e5e04165fabbf1c6ee8ee5121d35921965 *vp90-2-00-quantizer-02.webm.md5 +fdef046777b5b75c962b715d809dbe2ea331afb9 *vp90-2-00-quantizer-03.webm +f270bee0b0c7aa2bf4c5afe098556b4f3f890faf *vp90-2-00-quantizer-03.webm.md5 +66d98609e809394a6ac730787e6724e3badc075a *vp90-2-00-quantizer-04.webm +427433bfe121c4aea1095ec3124fdc174d200e3a *vp90-2-00-quantizer-04.webm.md5 +e6e42626d8cadf0b5be16313f69212981b96fee5 *vp90-2-00-quantizer-05.webm +c98f6a9a1af4cfd71416792827304266aad4bd46 *vp90-2-00-quantizer-05.webm.md5 +413ef09b721f5dcec1a96e937a97e5873c2e6db6 *vp90-2-00-quantizer-06.webm +5080e940a23805c82e578e21b57fc2c511e76376 *vp90-2-00-quantizer-06.webm.md5 +4a50a5f4ac717c30dfaae8bb46702e3542e867de *vp90-2-00-quantizer-07.webm +76c429a02b56762e10ee4db88729d8834b3a70f4 *vp90-2-00-quantizer-07.webm.md5 +d2f4e464780bf8b7e647efa18ac777a930e62bc0 *vp90-2-00-quantizer-08.webm +ab94aabf9316111b52d7c531962ed4123313b6ba *vp90-2-00-quantizer-08.webm.md5 +174bc58433936dd79550398d744f1072ce7f5693 *vp90-2-00-quantizer-09.webm +e1f7690cd83ccc56d045e17cce552544a5f03810 *vp90-2-00-quantizer-09.webm.md5 +52bc1dfd3a97b24d922eb8a31d07527891561f2a *vp90-2-00-quantizer-10.webm +9b37bed893b5f6a4e12f2aa40f02dd40f944d0f8 *vp90-2-00-quantizer-10.webm.md5 +10031eecafde1e1d8e6323fe2b2a1d7e77a66869 *vp90-2-00-quantizer-11.webm +fe4620a4bb0e4f5cb9bbfedc4039a22b81b0f5c0 *vp90-2-00-quantizer-11.webm.md5 +78e9f7bb77e8e348155bbdfa12790789d1d50c34 *vp90-2-00-quantizer-12.webm +0961d060cc8dd469c6dac8d7d75f927c0bb971b8 *vp90-2-00-quantizer-12.webm.md5 +133b77a3bbcef652552d74ffc46afbfe3b8a1cba *vp90-2-00-quantizer-13.webm +df29e5e0f95772af482f540d776f6b9dea4bfa29 *vp90-2-00-quantizer-13.webm.md5 +27323afdaf8987e025c27129c74c86502315a206 *vp90-2-00-quantizer-14.webm +ce96a2cc312942f0427a463f15a392870dd69764 *vp90-2-00-quantizer-14.webm.md5 +ab58d0b41037829f6bc993910999f4af0212aafd *vp90-2-00-quantizer-15.webm +40f700db606501aa7cb49049624cbdde6409b122 *vp90-2-00-quantizer-15.webm.md5 +cd948e66448aafb65998815ce37241f95d7c9ee7 *vp90-2-00-quantizer-16.webm +039b742d149c945ed79c7b9a6384352852a1c116 *vp90-2-00-quantizer-16.webm.md5 +62f56e663e13c576764e491cf08f19bd46a71999 *vp90-2-00-quantizer-17.webm +90c5a39bf76e6b3e0a1c0d3e9b68a9fd78be963e *vp90-2-00-quantizer-17.webm.md5 +f26ecad7263cd66a614e53ba5d7c00df181affeb *vp90-2-00-quantizer-18.webm +cda0a1c0fca2ec2976ae55124a8a67305508bae6 *vp90-2-00-quantizer-18.webm.md5 +94bfc4c04fcfe139a63b98c569e8c14ba98c401f *vp90-2-00-quantizer-19.webm +5b8ec169ccf67d8a0a8e46a62eb173f5a1dbaf4f *vp90-2-00-quantizer-19.webm.md5 +0ee88e9318985e1e245de78c2c4a665885ab76a7 *vp90-2-00-quantizer-20.webm +4b26f7edb4fcd3a1b4cce9ba3cb8650e3ee6e063 *vp90-2-00-quantizer-20.webm.md5 +6a995cb2b1db33da8087321df1e646f95c3e32d1 *vp90-2-00-quantizer-21.webm +e216b4a1eceac03efcc433759be54ab8ea87b24b *vp90-2-00-quantizer-21.webm.md5 +aa7722fc427e7180115f3c9cd96bb6b2768e7296 *vp90-2-00-quantizer-22.webm +1aa813bd45ae831bf5e79ace4d73dfd25989a07d *vp90-2-00-quantizer-22.webm.md5 +7677e5b929ed6d142041f19b8a9cd5822ee1504a *vp90-2-00-quantizer-23.webm +0de0af34abd843d5b37e58baf3ed96a6104b64c3 *vp90-2-00-quantizer-23.webm.md5 +b2995cbe1128b2d4926f1b28d01c501ecb6be8c8 *vp90-2-00-quantizer-24.webm +db6033af2ba2f2bca62468fb4b8808e474f93923 *vp90-2-00-quantizer-24.webm.md5 +8135ba35587fd92cd4667be7896323d9b634401c *vp90-2-00-quantizer-25.webm +3499e00c2cc15876f61f07e3d3cfca54ebcd98fd *vp90-2-00-quantizer-25.webm.md5 +af0fa2907746db82d345f6d831fcc1b2862a29fb *vp90-2-00-quantizer-26.webm +cd6fe3d14dab48886ebf65be00e6ed9616ebe5a7 *vp90-2-00-quantizer-26.webm.md5 +bd0002e91323776beb5ff11e06edcf19fc08e9b9 *vp90-2-00-quantizer-27.webm +fe72154ef196067d6c272521012dd79706496cac *vp90-2-00-quantizer-27.webm.md5 +fc15eb606f81455ff03df16bf3432296b002c43c *vp90-2-00-quantizer-28.webm +40b2e24b542206a6bfd746ef199e49ccea07678a *vp90-2-00-quantizer-28.webm.md5 +3090bbf913cad0b2eddca7228f5ed51a58378b8d *vp90-2-00-quantizer-29.webm +eb59745e0912d8ed6c928268bcf265237c9ba93f *vp90-2-00-quantizer-29.webm.md5 +c615abdca9c25e1cb110d908edbedfb3b7c92b91 *vp90-2-00-quantizer-30.webm +ad0f4fe6733e4e7cdfe8ef8722bb341dcc7538c0 *vp90-2-00-quantizer-30.webm.md5 +037d9f242086cfb085518f6416259defa82d5fc2 *vp90-2-00-quantizer-31.webm +4654b40792572f0a790874c6347ef9196d86c1a7 *vp90-2-00-quantizer-31.webm.md5 +505899f3f3515044c5c8b3213d9b9d16f614619d *vp90-2-00-quantizer-32.webm +659a2e6dd02df323f62600626859006640b445df *vp90-2-00-quantizer-32.webm.md5 +8b32ec9c3b7e5ca8ddc6b8aea1c1cb7ca996bccc *vp90-2-00-quantizer-33.webm +5b175ef1120ddeba4feae1247bf381bbc4e816ce *vp90-2-00-quantizer-33.webm.md5 +4d283755d17e287b1d099a80604398f60d7fb6ea *vp90-2-00-quantizer-34.webm +22a739de95acfeb27524e3700b8f678a9ad744d8 *vp90-2-00-quantizer-34.webm.md5 +4296f56a892a412d3d4f64824718dd566c4e6459 *vp90-2-00-quantizer-35.webm +c532c9c8dc7b3506fc6a51e5c20c17ef0ac039e7 *vp90-2-00-quantizer-35.webm.md5 +6f54e11da461e4410dd9075b015e2d9bc1d07dfb *vp90-2-00-quantizer-36.webm +0b3573f5addea4e3eb11a0b85f068299d5bdad78 *vp90-2-00-quantizer-36.webm.md5 +210581682a26c2c4375efc785c36e07539888bc2 *vp90-2-00-quantizer-37.webm +2b4fb6f8ba975237858e61cc8f560bcfc87cb38e *vp90-2-00-quantizer-37.webm.md5 +a15ef31283dfc4860f837fe200eb32a445f59629 *vp90-2-00-quantizer-38.webm +fb76771f3a795054b9936f70da7505c3ac585284 *vp90-2-00-quantizer-38.webm.md5 +1df8433a441412831daae6726df89fa70d21b14d *vp90-2-00-quantizer-39.webm +39e162c09a20e7e684868097766347014371fee6 *vp90-2-00-quantizer-39.webm.md5 +5330e4788ab9129dbb25a7a7d5411104521248b6 *vp90-2-00-quantizer-40.webm +872cc0f2cc9dbf000f89eadb4d8f9940e48e00b1 *vp90-2-00-quantizer-40.webm.md5 +d88d03b982889e399a78d7a06eeb1cf30e6c2da2 *vp90-2-00-quantizer-41.webm +5b4f7217e57fa2a221011d0b32f8d0409496b7b6 *vp90-2-00-quantizer-41.webm.md5 +9e16406e3e26955a6e17d455ef1ef64bbfa26e53 *vp90-2-00-quantizer-42.webm +0219d090cf37daabe19256ba8e932ba4874b92e4 *vp90-2-00-quantizer-42.webm.md5 +a9b15843486fb05f8cd15437ef279782a42b75db *vp90-2-00-quantizer-43.webm +3c9b0b4c607f9579a31726bfcf56729334ddc686 *vp90-2-00-quantizer-43.webm.md5 +1dbc931ac446c91eabe7213efff55b596cccf07c *vp90-2-00-quantizer-44.webm +73bc8f675103abaef3d9f73a2742b3bffd726d23 *vp90-2-00-quantizer-44.webm.md5 +7c6c1be15beb9d6201204b018966c8c4f9777efc *vp90-2-00-quantizer-45.webm +c907b29da821f790c6748de61f592689312e4e36 *vp90-2-00-quantizer-45.webm.md5 +07b434da1a467580f73b32177ee11b3e00f65a0d *vp90-2-00-quantizer-46.webm +7b2b7ce60c50bc970bc0ada46d7a7ce440148da3 *vp90-2-00-quantizer-46.webm.md5 +233d0465fb1a6fa36e9f89bd2193ac79bd4d2809 *vp90-2-00-quantizer-47.webm +527e0a9fb932efe915027ffe077f9e8d3a4fb139 *vp90-2-00-quantizer-47.webm.md5 +719613df7307e205c3fdb6acfb373849c5ab23c7 *vp90-2-00-quantizer-48.webm +65ab6c9d1b682c183b201c7ff42b90343ce3e304 *vp90-2-00-quantizer-48.webm.md5 +3bf04a598325ed0eabae1598ec7f718f715ec672 *vp90-2-00-quantizer-49.webm +ac68c4387ce11fcc998d8ba455ab9b2bb361d240 *vp90-2-00-quantizer-49.webm.md5 +d59238fb3a654931c9b65a11e7321b40d1f702e9 *vp90-2-00-quantizer-50.webm +d0576bfede46fd55659f028f2fd28554ceb3e6cc *vp90-2-00-quantizer-50.webm.md5 +3f579785101d4209360dd96f8c2ffe9beddf3bee *vp90-2-00-quantizer-51.webm +89fcfe04f4457a7f02ab4a2f94aacbb88aee5789 *vp90-2-00-quantizer-51.webm.md5 +28be5836e2fedefe4babf12fc9b79e460ab0a0f4 *vp90-2-00-quantizer-52.webm +f3dd52b70c18345fee740220f35da9c4def2017a *vp90-2-00-quantizer-52.webm.md5 +488ad4058c17170665b6acd1021fade9a02771e4 *vp90-2-00-quantizer-53.webm +1cdcb1d4f3a37cf83ad235eb27ec62ed2a01afc7 *vp90-2-00-quantizer-53.webm.md5 +682978289cb28cc8c9d39bc797300e45d6039de7 *vp90-2-00-quantizer-54.webm +36c35353f2c03cb099bd710d9994de7d9ed88834 *vp90-2-00-quantizer-54.webm.md5 +c398ce49af762a48f10cc4da9fae0769aae5f226 *vp90-2-00-quantizer-55.webm +2cf3570542d984f167ab087f59493c7fb47e0ed2 *vp90-2-00-quantizer-55.webm.md5 +3071f18b2fce261aa82d61f81a7ae4ca9a75d0e3 *vp90-2-00-quantizer-56.webm +d3f93f8272b6de31cffb011a26f11abb514efb12 *vp90-2-00-quantizer-56.webm.md5 +f4e8e14b1f278801a7eb6f11734780a01b1668e9 *vp90-2-00-quantizer-57.webm +6478fdf1d7faf6db5f19dffc5e1363af358699ee *vp90-2-00-quantizer-57.webm.md5 +307dc264f57cc618fff211fa44d7f52767ed9660 *vp90-2-00-quantizer-58.webm +cf231d4a52d492fa692ea4194ec5eb7511fec54e *vp90-2-00-quantizer-58.webm.md5 +1fd7cd596170afce2de0b1441b7674bda5723440 *vp90-2-00-quantizer-59.webm +4681f7ef96f63e085c41bb1a964b0df7e67e0b38 *vp90-2-00-quantizer-59.webm.md5 +34cdcc81c0ba7085aefbb22d7b4aa9bca3dd7c62 *vp90-2-00-quantizer-60.webm +58691ef53b6b623810e2c57ded374c77535df935 *vp90-2-00-quantizer-60.webm.md5 +e6e812406aab81021bb16e772c1db03f75906cb6 *vp90-2-00-quantizer-61.webm +76436eace62f08ff92b61a0845e66667a027db1b *vp90-2-00-quantizer-61.webm.md5 +84d811bceed70c950a6a08e572a6e274866e72b1 *vp90-2-00-quantizer-62.webm +2d937cc011eeddd95222b960982da5cd18db580f *vp90-2-00-quantizer-62.webm.md5 +0912b295ba0ea09359315315ffd67d22d046f883 *vp90-2-00-quantizer-63.webm +5a829031055d70565f57dbcd47a6ac33619952b3 *vp90-2-00-quantizer-63.webm.md5 +0cf9e5ebe0112bdb47b5887ee5d58eb9d4727c00 *vp90-2-01-sharpness-1.webm +5a0476be4448bae8f8ca17ea236c98793a755948 *vp90-2-01-sharpness-1.webm.md5 +51e02d7911810cdf5be8b68ac40aedab479a3179 *vp90-2-01-sharpness-2.webm +a0ca5bc87a5ed7c7051f59078daa0d03be1b45b6 *vp90-2-01-sharpness-2.webm.md5 +0603f8ad239c07a531d948187f4dafcaf51eda8d *vp90-2-01-sharpness-3.webm +3af8000a69c72fe77881e3176f026c2affb78cc7 *vp90-2-01-sharpness-3.webm.md5 +4ca4839f48146252fb261ed88838d80211804841 *vp90-2-01-sharpness-4.webm +08832a1494f84fa9edd40e080bcf2c0e80100c76 *vp90-2-01-sharpness-4.webm.md5 +95099dc8f9cbaf9b9a7dd65311923e441ff70731 *vp90-2-01-sharpness-5.webm +93ceee30c140f0b406726c0d896b9db6031c4c7f *vp90-2-01-sharpness-5.webm.md5 +ceb4116fb7b078d266d153233b6d62a255a34e4c *vp90-2-01-sharpness-6.webm +da83efe59e537ce538e8b03a6eac63cf25849c9a *vp90-2-01-sharpness-6.webm.md5 +b5f7cd19aece3880f9d616a778e5cc24c6b9b505 *vp90-2-01-sharpness-7.webm +2957408d20deac8633941a2169f801bae6f086e1 *vp90-2-01-sharpness-7.webm.md5 +ffc096c2ce1050450ad462b5fabd2a5220846319 *vp90-2-02-size-08x08.webm +e36d2ed6fa2746347710b750586aafa6a01ff3ae *vp90-2-02-size-08x08.webm.md5 +895b986f9fd55cd879472b31c6a06b82094418c8 *vp90-2-02-size-08x10.webm +079157a19137ccaebba606f2871f45a397347150 *vp90-2-02-size-08x10.webm.md5 +1c5992203e62a2b83040ccbecd748b604e19f4c0 *vp90-2-02-size-08x16.webm +9aa45ffdf2078f883bbed01450031b691819c144 *vp90-2-02-size-08x16.webm.md5 +d0a8953da1f85f484487408fee5da9e2a8391901 *vp90-2-02-size-08x18.webm +59a5cc17d354c6a23e5e959d666b1456a5d49c56 *vp90-2-02-size-08x18.webm.md5 +1b13461a9fc65cb041bacfe4ea6f02d363397d61 *vp90-2-02-size-08x32.webm +2bdddd6878f05d37d84cde056a3f5e7f926ba3d6 *vp90-2-02-size-08x32.webm.md5 +2861f0a0daadb62295b0504a1fbe5b50c79a8f59 *vp90-2-02-size-08x34.webm +6b5812cfb8a82d378ea2913bf009e93668020147 *vp90-2-02-size-08x34.webm.md5 +02f948216d4246579dc53c47fe55d8fb264ba251 *vp90-2-02-size-08x64.webm +84b55fdee6d9aa820c7a8c62822446184b191767 *vp90-2-02-size-08x64.webm.md5 +4b011242cbf42516efd2b197baebb61dd34562c9 *vp90-2-02-size-08x66.webm +6b1fa0a885947b3cc0fe58f75f838e662bd9bb8b *vp90-2-02-size-08x66.webm.md5 +4057796be9dd12df48ab607f502ae6aa70eeeab6 *vp90-2-02-size-10x08.webm +71c752c51aec9f48de286b93f4c20e9c11cad7d0 *vp90-2-02-size-10x08.webm.md5 +6583c853fa43fc53d51743eac5f3a43a359d45d0 *vp90-2-02-size-10x10.webm +1da524d24af1944b671d4d3f2b398d6e336584c3 *vp90-2-02-size-10x10.webm.md5 +ba442fc03ccd3a705c64c83b36f5ada67d198874 *vp90-2-02-size-10x16.webm +7cfd960f232c34c641a4a2a9411b6fd0efb2fc50 *vp90-2-02-size-10x16.webm.md5 +cc92ed40eef14f52e4d080cb2c57939dd8326374 *vp90-2-02-size-10x18.webm +db5626275cc55ce970b91c995e74f6838d943aca *vp90-2-02-size-10x18.webm.md5 +3a93d501d22325e9fd4c9d8b82e2a432de33c351 *vp90-2-02-size-10x32.webm +5cae51b0c71cfc131651f345f87583eb2903afaf *vp90-2-02-size-10x32.webm.md5 +50d2f2b15a9a5178153db44a9e03aaf32b227f67 *vp90-2-02-size-10x34.webm +bb0efe058122641e7f73e94497dda2b9e6c21efd *vp90-2-02-size-10x34.webm.md5 +01624ec173e533e0b33fd9bdb91eb7360c7c9175 *vp90-2-02-size-10x64.webm +b9c0e3b054463546356acf5157f9be92fd34732f *vp90-2-02-size-10x64.webm.md5 +2942879baf1c09e96b14d0fc84806abfe129c706 *vp90-2-02-size-10x66.webm +bab5f539c2f91952e187456b4beafbb4c01e25ee *vp90-2-02-size-10x66.webm.md5 +88d2b63ca5e9ee163d8f20e8886f3df3ff301a66 *vp90-2-02-size-16x08.webm +7f48a0fcf8c25963f3057d7f6669c5f2415834b8 *vp90-2-02-size-16x08.webm.md5 +59261eb34c15ea9b5ddd2d416215c1a8b9e6dc1f *vp90-2-02-size-16x10.webm +73a7c209a46dd051c9f7339b6e02ccd5b3b9fc81 *vp90-2-02-size-16x10.webm.md5 +066834fef9cf5b9a72932cf4dea5f253e14a976d *vp90-2-02-size-16x16.webm +faec542f52f37601cb9c480d887ae9355be99372 *vp90-2-02-size-16x16.webm.md5 +195307b4eb3192271ee4a935b0e48deef0c54cc2 *vp90-2-02-size-16x18.webm +5a92e19e624c0376321d4d0e22c0c91995bc23e1 *vp90-2-02-size-16x18.webm.md5 +14f3f884216d7ae16ec521f024a2f2d31bbf9c1a *vp90-2-02-size-16x32.webm +ea622d1c817dd174556f7ee7ccfe4942b34d4845 *vp90-2-02-size-16x32.webm.md5 +2e0501100578a5da9dd47e4beea160f945bdd1ba *vp90-2-02-size-16x34.webm +1b8645ef64239334921c5f56b24ce815e6070b05 *vp90-2-02-size-16x34.webm.md5 +89a6797fbebebe93215f367229a9152277f5dcfe *vp90-2-02-size-16x64.webm +a03d8c1179ca626a8856fb416d635dbf377979cd *vp90-2-02-size-16x64.webm.md5 +0f3a182e0750fcbae0b9eae80c7a53aabafdd18d *vp90-2-02-size-16x66.webm +8cb6736dc2d897c1283919a32068af377d66c59c *vp90-2-02-size-16x66.webm.md5 +68fe70dc7914cc1d8d6dcd97388b79196ba3e7f1 *vp90-2-02-size-18x08.webm +874c7fb505be9db3160c57cb405c4dbd5b990dc2 *vp90-2-02-size-18x08.webm.md5 +0546352dd78496d4dd86c3727ac2ff36c9e72032 *vp90-2-02-size-18x10.webm +1d80eb36557ea5f25a386495a36f93da0f25316b *vp90-2-02-size-18x10.webm.md5 +60fe99e5f5cc99706efa3e0b894e45cbcf0d6330 *vp90-2-02-size-18x16.webm +1ab6cdd89a53662995d103546e6611c84f9292ab *vp90-2-02-size-18x16.webm.md5 +f9a8f5fb749d69fd555db6ca093b7f77800c7b4f *vp90-2-02-size-18x18.webm +ace8a66328f7802b15f9989c2720c029c6abd279 *vp90-2-02-size-18x18.webm.md5 +a197123a527ec25913a9bf52dc8c347749e00045 *vp90-2-02-size-18x32.webm +34fbd7036752232d1663e70d7f7cdc93f7129202 *vp90-2-02-size-18x32.webm.md5 +f219655a639a774a2c9c0a9f45c28dc0b5e75e24 *vp90-2-02-size-18x34.webm +2c4d622a9ea548791c1a07903d3702e9774388bb *vp90-2-02-size-18x34.webm.md5 +5308578da48c677d477a5404e19391d1303033c9 *vp90-2-02-size-18x64.webm +e7fd4462527bac38559518ba80e41847db880f15 *vp90-2-02-size-18x64.webm.md5 +e109a7e013bd179f97e378542e1e81689ed06802 *vp90-2-02-size-18x66.webm +45c04e422fb383c1f3be04beefaa4490e83bdb1a *vp90-2-02-size-18x66.webm.md5 +38844cae5d99caf445f7de33c3ae78494ce36c01 *vp90-2-02-size-32x08.webm +ad018be39e493ca2405225034b1a5b7a42af6f3a *vp90-2-02-size-32x08.webm.md5 +7b57eaad55906f9de9903c8657a3fcb2aaf792ea *vp90-2-02-size-32x10.webm +2294425d4e55d275af5e25a0beac9738a1b4ee73 *vp90-2-02-size-32x10.webm.md5 +f47ca2ced0d47f761bb0a5fdcd911d3f450fdcc1 *vp90-2-02-size-32x16.webm +ae10981d93913f0ab1f28c1146255e01769aa8c0 *vp90-2-02-size-32x16.webm.md5 +08b23ad838b6cf1fbfe3ad7e7775d95573e815fc *vp90-2-02-size-32x18.webm +1ba76f4c4a4ac7aabfa3ce195c1b473535eb7cc8 *vp90-2-02-size-32x18.webm.md5 +d5b88ae6c8c25c53dee74d9f1e6ca64244349a57 *vp90-2-02-size-32x32.webm +e39c067a8ee2da52a51641eb1cb7f8eba935eb6b *vp90-2-02-size-32x32.webm.md5 +529429920dc36bd899059fa75a767f02c8c60874 *vp90-2-02-size-32x34.webm +56888e7834f52b106e8911e3a7fc0f473b609995 *vp90-2-02-size-32x34.webm.md5 +38e848e160391c2b1a55040aadde613b9f4bf15e *vp90-2-02-size-32x64.webm +8950485fb3f68b0e8be234db860e4ec5f5490fd0 *vp90-2-02-size-32x64.webm.md5 +5e8670f0b8ec9cefa8795b8959ffbe1a8e1aea94 *vp90-2-02-size-32x66.webm +225df9d7d72ec711b0b60f4aeb65311c97db054a *vp90-2-02-size-32x66.webm.md5 +695f929e2ce6fb11a1f180322d46c5cb1c97fa61 *vp90-2-02-size-34x08.webm +5bb4262030018dd01883965c6aa6070185924ef6 *vp90-2-02-size-34x08.webm.md5 +5adf74ec906d2ad3f7526e06bd29f5ad7d966a90 *vp90-2-02-size-34x10.webm +71c100b437d3e8701632ae8d65c3555339b1c68f *vp90-2-02-size-34x10.webm.md5 +d0918923c987fba2d00193d83797b21289fe54aa *vp90-2-02-size-34x16.webm +5d5a52f3535b4d2698dd3d87f4a13fdc9b57163d *vp90-2-02-size-34x16.webm.md5 +553ab0042cf87f5e668ec31b2e4b2a4b6ec196fd *vp90-2-02-size-34x18.webm +a164c7f3c424987df2340496e6a8cf76e973f0f1 *vp90-2-02-size-34x18.webm.md5 +baf3e233634f150de81c18ba5d8848068e1c3c54 *vp90-2-02-size-34x32.webm +22a79d3bd1c9b85dfe8c70bb2e19f08a92a8be03 *vp90-2-02-size-34x32.webm.md5 +6d50a533774a7167350e4a7ef43c94a5622179a2 *vp90-2-02-size-34x34.webm +0c099638e79c273546523e06704553e42eb00b00 *vp90-2-02-size-34x34.webm.md5 +698cdd0a5e895cc202c488675e682a8c537ede4f *vp90-2-02-size-34x64.webm +9317b63987cddab8389510a27b86f9f3d46e3fa5 *vp90-2-02-size-34x64.webm.md5 +4b5335ca06f082b6b69f584eb8e7886bdcafefd3 *vp90-2-02-size-34x66.webm +e18d68b35428f46a84a947c646804a51ef1d7cec *vp90-2-02-size-34x66.webm.md5 +a54ae7b494906ec928a876e8290e5574f2f9f6a2 *vp90-2-02-size-64x08.webm +87f9f7087b6489d45e9e4b38ede2c5aef4a4928f *vp90-2-02-size-64x08.webm.md5 +24522c70804a3c23d937df2d829ae63965b23f38 *vp90-2-02-size-64x10.webm +447ce03938ab53bffcb4a841ee0bfaa90462dcb9 *vp90-2-02-size-64x10.webm.md5 +2a5035d035d214ae614af8051930690ef623989b *vp90-2-02-size-64x16.webm +84e355761dd2e0361b904c84c52a0dd0384d89cf *vp90-2-02-size-64x16.webm.md5 +3a293ef4e270a19438e59b817fbe5f43eed4d36b *vp90-2-02-size-64x18.webm +666824e5ba746779eb46079e0631853dcc86d48b *vp90-2-02-size-64x18.webm.md5 +ed32fae837095c9e8fc95d223ec68101812932c2 *vp90-2-02-size-64x32.webm +97086eadedce1d0d9c072b585ba7b49aec69b1e7 *vp90-2-02-size-64x32.webm.md5 +696c7a7250bdfff594f4dfd88af34239092ecd00 *vp90-2-02-size-64x34.webm +253a1d38d452e7826b086846c6f872f829c276bb *vp90-2-02-size-64x34.webm.md5 +fc508e0e3c2e6872c60919a60b812c5232e9c2b0 *vp90-2-02-size-64x64.webm +2cd6ebeca0f82e9f505616825c07950371b905ab *vp90-2-02-size-64x64.webm.md5 +0f8a4fc1d6521187660425c283f08dff8c66e476 *vp90-2-02-size-64x66.webm +5806be11a1d346be235f88d3683e69f73746166c *vp90-2-02-size-64x66.webm.md5 +273b0c36e3658685cde250408a478116d7ae92f1 *vp90-2-02-size-66x08.webm +23c3cd0dca20a2f71f036e77ea92025ff4e7a298 *vp90-2-02-size-66x08.webm.md5 +4844c59c3306d1e671bb0568f00e344bf797e66e *vp90-2-02-size-66x10.webm +e041eaf6841d775f8fde8bbb4949d2733fdaab7f *vp90-2-02-size-66x10.webm.md5 +bdf3f1582b234fcd2805ffec59f9d716a2345302 *vp90-2-02-size-66x16.webm +2ec85ee18119e6798968571ea6e1b93ca386e3af *vp90-2-02-size-66x16.webm.md5 +0acce9af12b13b025d5274013da7ef6f568f075f *vp90-2-02-size-66x18.webm +77c4d53e2a5c96b70af9d575fe6811e0f5ee627b *vp90-2-02-size-66x18.webm.md5 +682b36a25774bbdedcd603f504d18eb63f0167d4 *vp90-2-02-size-66x32.webm +53728fae2a428f16d376a29f341a64ddca97996a *vp90-2-02-size-66x32.webm.md5 +e71b70e901e29eaa6672a6aa4f37f6f5faa02bd6 *vp90-2-02-size-66x34.webm +f69a6a555e3f614b0a35f9bfc313d8ebb35bc725 *vp90-2-02-size-66x34.webm.md5 +4151b8c29452d5c2266397a7b9bf688899a2937b *vp90-2-02-size-66x64.webm +69486e7fd9e380b6c97a03d3e167affc79f73840 *vp90-2-02-size-66x64.webm.md5 +68784a1ecac776fe2a3f230345af32f06f123536 *vp90-2-02-size-66x66.webm +7f008c7f48d55e652fbd6bac405b51e0015c94f2 *vp90-2-02-size-66x66.webm.md5 +7e1bc449231ac1c5c2a11c9a6333b3e828763798 *vp90-2-03-size-196x196.webm +6788a561466dace32d500194bf042e19cccc35e1 *vp90-2-03-size-196x196.webm.md5 +a170c9a88ec1dd854c7a471ff55fb2a97ac31870 *vp90-2-03-size-196x198.webm +6bf9d6a8e2bdc5bf4f8a78071a3fed5ca02ad6f2 *vp90-2-03-size-196x198.webm.md5 +68f861d21c4c8b03d572c3d3fcd9f4fbf1f4503f *vp90-2-03-size-196x200.webm +bbfc260b2bfd872cc6054272bb6b7f959a9e1c6e *vp90-2-03-size-196x200.webm.md5 +fc34889feeca2b7e5b27b4f1ce22d2e2b8e3e4b1 *vp90-2-03-size-196x202.webm +158ee72af578f39aad0c3b8f4cbed2fc78b57e0f *vp90-2-03-size-196x202.webm.md5 +dd28fb7247af534bdf5e6795a3ac429610489a0b *vp90-2-03-size-196x208.webm +7546be847efce2d1c0a23f807bfb03f91b764e1e *vp90-2-03-size-196x208.webm.md5 +41d5cf5ed65b722a1b6dc035e67f978ea8ffecf8 *vp90-2-03-size-196x210.webm +9444fdf632d6a1b6143f4cb10fed8f63c1d67ec1 *vp90-2-03-size-196x210.webm.md5 +5007bc618143437c009d6dde5fc2e86f72d37dc2 *vp90-2-03-size-196x224.webm +858361d8f79b44df5545feabbc9754ec9ede632f *vp90-2-03-size-196x224.webm.md5 +0bcbe357fbc776c3fa68e7117179574ed7564a44 *vp90-2-03-size-196x226.webm +72006a5f42031a43d70a2cd9fc1958962a86628f *vp90-2-03-size-196x226.webm.md5 +000239f048cceaac055558e97ef07078ebf65502 *vp90-2-03-size-198x196.webm +2d6841901b72000c5340f30be602853438c1b787 *vp90-2-03-size-198x196.webm.md5 +ae75b766306a6404c3b3b35a6b6d53633c14fbdb *vp90-2-03-size-198x198.webm +3f2544b4f3b4b643a98f2c3b15ea5826fc702fa1 *vp90-2-03-size-198x198.webm.md5 +95ffd573fa84ccef1cd59e1583e6054f56a5c83d *vp90-2-03-size-198x200.webm +5d537e3c9b9c54418c79677543454c4cda3de1af *vp90-2-03-size-198x200.webm.md5 +ecc845bf574375f469bc91bf5c75c79dc00073d6 *vp90-2-03-size-198x202.webm +1b59f5e111265615a7a459eeda8cc9045178d228 *vp90-2-03-size-198x202.webm.md5 +432fb27144fe421b9f51cf44d2750a26133ed585 *vp90-2-03-size-198x208.webm +a58a67f4fb357c73ca078aeecbc0f782975630b1 *vp90-2-03-size-198x208.webm.md5 +ff5058e7e6a47435046612afc8536f2040989e6f *vp90-2-03-size-198x210.webm +18d3be7935e52217e2e9400b6f2c681a9e45dc89 *vp90-2-03-size-198x210.webm.md5 +a0d55263c1ed2c03817454dd4ec4090d36dbc864 *vp90-2-03-size-198x224.webm +efa366a299817e2da51c00623b165aab9fbb8d91 *vp90-2-03-size-198x224.webm.md5 +ccd142fa2920fc85bb753f049160c1c353ad1574 *vp90-2-03-size-198x226.webm +534524a0b2dbff852e0b92ef09939db072f83243 *vp90-2-03-size-198x226.webm.md5 +0d483b94ed40abc8ab6e49f960432ee54ad9c7f1 *vp90-2-03-size-200x196.webm +41795f548181717906e7a504ba551f06c32102ae *vp90-2-03-size-200x196.webm.md5 +f6c2dc54e0989d50f01333fe40c91661fcbf849a *vp90-2-03-size-200x198.webm +43df5d8c46a40089441392e6d096c588c1079a68 *vp90-2-03-size-200x198.webm.md5 +2f6e9df82e44fc145f0d9212dcccbed3de605e23 *vp90-2-03-size-200x200.webm +757b2ef96b82093255725bab9690bbafe27f3caf *vp90-2-03-size-200x200.webm.md5 +40c5ea60415642a4a2e75c0d127b06309baadfab *vp90-2-03-size-200x202.webm +3022c4a1c625b5dc04fdb1052d17d45b4171cfba *vp90-2-03-size-200x202.webm.md5 +6942ed5b27476bb8506d10e600d6ff60887780ca *vp90-2-03-size-200x208.webm +c4ab8c66f3cf2dc8e8dd7abae9ac21f4d32cd6be *vp90-2-03-size-200x208.webm.md5 +71dbc99b83c49d1da45589b91eabb98e2f4a7b1e *vp90-2-03-size-200x210.webm +3f0b40da7eef7974b9bc326562f251feb67d9c7c *vp90-2-03-size-200x210.webm.md5 +6b6b8489081cfefb377cc5f18eb754ec2383f655 *vp90-2-03-size-200x224.webm +a259df2ac0e294492e3f9d4315baa34cab044f04 *vp90-2-03-size-200x224.webm.md5 +c9adc1c9bb07559349a0b054df4af56f7a6edbb9 *vp90-2-03-size-200x226.webm +714cec61e3575581e4f1a0e3921f4dfdbbd316c5 *vp90-2-03-size-200x226.webm.md5 +f9bdc936bdf53f8be9ce78fecd41a21d31ff3943 *vp90-2-03-size-202x196.webm +5b8e2e50fcea2c43b12fc067b8a9cc117af77bda *vp90-2-03-size-202x196.webm.md5 +c7b66ea3da87613deb47ff24a111247d3c384fec *vp90-2-03-size-202x198.webm +517e91204b25586da943556f4adc5951c9be8bee *vp90-2-03-size-202x198.webm.md5 +935ef56b01cfdb4265a7e24696645209ccb20970 *vp90-2-03-size-202x200.webm +55b8ec4a2513183144a8e27564596c06c7576fce *vp90-2-03-size-202x200.webm.md5 +849acf75e4f1d8d90046704e1103a18c64f30e35 *vp90-2-03-size-202x202.webm +c79afc6660df2824e7df314e5bfd71f0d8acf76b *vp90-2-03-size-202x202.webm.md5 +17b3a4d55576b770626ccb856b9f1a6c8f6ae476 *vp90-2-03-size-202x208.webm +0b887ff30409c58f2ccdc3bfacd6be7c69f8997a *vp90-2-03-size-202x208.webm.md5 +032d0ade4230fb2eef6d19915a7a1c9aa4a52617 *vp90-2-03-size-202x210.webm +f78f8e79533c0c88dd2bfdcec9b1c07848568ece *vp90-2-03-size-202x210.webm.md5 +915a38c31fe425d5b93c837121cfa8082f5ea5bc *vp90-2-03-size-202x224.webm +bf52a104074d0c5942aa7a5b31e11db47e43d48e *vp90-2-03-size-202x224.webm.md5 +be5cfde35666fa435e47d544d9258215beb1cf29 *vp90-2-03-size-202x226.webm +2fa2f87502fda756b319389c8975204e130a2e3f *vp90-2-03-size-202x226.webm.md5 +15d908e97862b5b4bf295610df011fb9aa09909b *vp90-2-03-size-208x196.webm +50c60792305d6a99be376dd596a6ff979325e6cc *vp90-2-03-size-208x196.webm.md5 +a367c7bc9fde56d6f4848cc573c7d4c1ce75e348 *vp90-2-03-size-208x198.webm +be85fb2c8d435a75484231356f07d06ebddd13cd *vp90-2-03-size-208x198.webm.md5 +05fd46deb7288e7253742091f56e54a9a441a187 *vp90-2-03-size-208x200.webm +74f8ec3b3a2fe81767ed1ab36a47bc0062d6223c *vp90-2-03-size-208x200.webm.md5 +d8985c4b386513a7385a4b3639bf91e469f1378b *vp90-2-03-size-208x202.webm +0614a1e8d92048852adcf605a51333f5fabc7f03 *vp90-2-03-size-208x202.webm.md5 +28b002242238479165ba4fb87ee6b442c64b32e4 *vp90-2-03-size-208x208.webm +37de5aca59bb900228400b0e115d3229edb9dcc0 *vp90-2-03-size-208x208.webm.md5 +c545be0050c2fad7c68427dbf86c62a739e94ab3 *vp90-2-03-size-208x210.webm +d646eccb3cd578f94b54777e32b88898bef6e17a *vp90-2-03-size-208x210.webm.md5 +63a0cfe295b661026dd7b1bebb67acace1db766f *vp90-2-03-size-208x224.webm +85c0361d93bf85a335248fef2767ff43eeef23db *vp90-2-03-size-208x224.webm.md5 +f911cc718d66e4fe8a865226088939c9eb1b7825 *vp90-2-03-size-208x226.webm +a6d583a57876e7b7ec48625b2b2cdbcf70cab837 *vp90-2-03-size-208x226.webm.md5 +5bbb0f36da9a4683cf04e724124d8696332911bf *vp90-2-03-size-210x196.webm +a3580fc7816d7fbcfb54fdba501cabbd06ba2f1d *vp90-2-03-size-210x196.webm.md5 +8db64d6f9ce36dd382013b42ae4e292deba697bc *vp90-2-03-size-210x198.webm +eda20f8268c7f4147bead4059e9c4897e09140a9 *vp90-2-03-size-210x198.webm.md5 +ce391505eeaf1d12406563101cd6b2dbbbb44bfc *vp90-2-03-size-210x200.webm +79d73b7f623082d2a00aa33e95c79d11c7d9c3a8 *vp90-2-03-size-210x200.webm.md5 +852db6fdc206e72391fc69b807f1954934679949 *vp90-2-03-size-210x202.webm +f69414c5677ed2f2b8b37ae76429e509a92276a5 *vp90-2-03-size-210x202.webm.md5 +c424cc3edd2308da7d33f27acb36b54db5bf2595 *vp90-2-03-size-210x208.webm +27b18562faa1b3184256f4eae8114b539b3e9d3e *vp90-2-03-size-210x208.webm.md5 +dd029eba719d50a2851592fa8b9b2efe88904930 *vp90-2-03-size-210x210.webm +c853a1670465eaa04ca31b3511995f1b6ed4f58f *vp90-2-03-size-210x210.webm.md5 +d962e8ae676c54d0c3ea04ec7c04b37ae6a786e3 *vp90-2-03-size-210x224.webm +93b793e79d987065b39ad8e2e71244368435fc25 *vp90-2-03-size-210x224.webm.md5 +3d0825fe83bcc125be1f78145ff43ca6d7588784 *vp90-2-03-size-210x226.webm +5230f31a57ca3b5311698a12035d2644533b3ec4 *vp90-2-03-size-210x226.webm.md5 +6622f8bd9279e1ce45509a58a31a990052d45e14 *vp90-2-03-size-224x196.webm +65411da07f60113f2be05c807879072b161d561e *vp90-2-03-size-224x196.webm.md5 +6744ff2ee2c41eb08c62ff30880833b6d77b585b *vp90-2-03-size-224x198.webm +46ea3641d41acd4bff347b224646c060d5620385 *vp90-2-03-size-224x198.webm.md5 +8eb91f3416a1404705f370caecd74b2b458351b1 *vp90-2-03-size-224x200.webm +196aefb854c8b95b9330263d6690b7ee15693ecf *vp90-2-03-size-224x200.webm.md5 +256a5a23ef4e6d5ef2871af5afb8cd13d28cec00 *vp90-2-03-size-224x202.webm +840ad8455dcf2be378c14b007e66fa642fc8196d *vp90-2-03-size-224x202.webm.md5 +db4606480ab48b96c9a6ff5e639f1f1aea2a12e4 *vp90-2-03-size-224x208.webm +40b9801d5620467499ac70fa6b7c40aaa5e1c331 *vp90-2-03-size-224x208.webm.md5 +e37159e687fe1cb24cffddfae059301adbaf4212 *vp90-2-03-size-224x210.webm +1e4acd4b6334ae260c3eed08652d0ba8122073f2 *vp90-2-03-size-224x210.webm.md5 +0de1eb4bb6285ae621e4f2b613d2aa4a8c95a130 *vp90-2-03-size-224x224.webm +37db449ad86fb286c2c02d94aa8fe0379c05044a *vp90-2-03-size-224x224.webm.md5 +32ebbf903a7d7881bcfe59639f1d472371f3bf27 *vp90-2-03-size-224x226.webm +5cc3ac5dc9f6912491aa2ddac863f8187f34c569 *vp90-2-03-size-224x226.webm.md5 +9480ff5c2c32b1870ac760c87514912616e6cf01 *vp90-2-03-size-226x196.webm +fe83655c0f1888f0af7b047785f01ba7ca9f1324 *vp90-2-03-size-226x196.webm.md5 +09cad4221996315cdddad4e502dbfabf53ca1d6a *vp90-2-03-size-226x198.webm +e3ddfdc650acb95adb45abd9b634e1f09ea8ac96 *vp90-2-03-size-226x198.webm.md5 +c34f49d55fe39e3f0b607e3cc95e30244225cecb *vp90-2-03-size-226x200.webm +abb83edc868a3523ccd4e5523fac2efbe7c3df1f *vp90-2-03-size-226x200.webm.md5 +d17bc08eedfc60c4c23d576a6c964a21bf854d1f *vp90-2-03-size-226x202.webm +1d22d2d0f375251c2d5a1acb4714bc35d963865b *vp90-2-03-size-226x202.webm.md5 +9bd537c4f92a25596ccd29fedfe181feac948b92 *vp90-2-03-size-226x208.webm +6feb0e7325386275719f3511ada9e248a2ae7df4 *vp90-2-03-size-226x208.webm.md5 +4487067f6cedd495b93696b44b37fe0a3e7eda14 *vp90-2-03-size-226x210.webm +49a8fa87945f47208168d541c068e78d878075d5 *vp90-2-03-size-226x210.webm.md5 +559fea2f8da42b33c1aa1dbc34d1d6781009847a *vp90-2-03-size-226x224.webm +83c6d8f2969b759e10e5c6542baca1265c874c29 *vp90-2-03-size-226x224.webm.md5 +fe0af2ee47b1e5f6a66db369e2d7e9d870b38dce *vp90-2-03-size-226x226.webm +94ad19b8b699cea105e2ff18f0df2afd7242bcf7 *vp90-2-03-size-226x226.webm.md5 +52bc1dfd3a97b24d922eb8a31d07527891561f2a *vp90-2-03-size-352x288.webm +3084d6d0a1eec22e85a394422fbc8faae58930a5 *vp90-2-03-size-352x288.webm.md5 +b6524e4084d15b5d0caaa3d3d1368db30cbee69c *vp90-2-03-deltaq.webm +65f45ec9a55537aac76104818278e0978f94a678 *vp90-2-03-deltaq.webm.md5 +4dbb87494c7f565ffc266c98d17d0d8c7a5c5aba *vp90-2-05-resize.ivf +7f6d8879336239a43dbb6c9f13178cb11cf7ed09 *vp90-2-05-resize.ivf.md5 +bf61ddc1f716eba58d4c9837d4e91031d9ce4ffe *vp90-2-06-bilinear.webm +f6235f937552e11d8eb331ec55da6b3aa596b9ac *vp90-2-06-bilinear.webm.md5 +0c83a1e414fde3bccd6dc451bbaee68e59974c76 *vp90-2-07-frame_parallel.webm +e5c2c9fb383e5bf3b563480adaeba5b7e3475ecd *vp90-2-07-frame_parallel.webm.md5 +086c7edcffd699ae7d99d710fd7e53b18910ca5b *vp90-2-08-tile_1x2_frame_parallel.webm +e981ecaabb29a80e0cbc1f4002384965ce8e95bb *vp90-2-08-tile_1x2_frame_parallel.webm.md5 +ed79be026a6f28646c5825da1c12d1fbc70f96a4 *vp90-2-08-tile_1x2.webm +45b404e025841c9750895fc1a9f6bd384fe6a315 *vp90-2-08-tile_1x2.webm.md5 +cf8ea970c776797aae71dac8317ea926d9431cab *vp90-2-08-tile_1x4_frame_parallel.webm +a481fbea465010b57af5a19ebf6d4a5cfe5b9278 *vp90-2-08-tile_1x4_frame_parallel.webm.md5 +0203ec456277a01aec401e7fb6c72c9a7e5e3f9d *vp90-2-08-tile_1x4.webm +c9b237dfcc01c1b414fbcaa481d014a906ef7998 *vp90-2-08-tile_1x4.webm.md5 +20c75157e91ab41f82f70ffa73d5d01df8469287 *vp90-2-08-tile-4x4.webm +ae7451810247fd13975cc257aa0301ff17102255 *vp90-2-08-tile-4x4.webm.md5 +2ec6e15422ac7a61af072dc5f27fcaf1942ce116 *vp90-2-08-tile-4x1.webm +0094f5ee5e46345017c30e0aa4835b550212d853 *vp90-2-08-tile-4x1.webm.md5 +edea45dac4a3c2e5372339f8851d24c9bef803d6 *vp90-2-09-subpixel-00.ivf +5428efc4bf92191faedf4a727fcd1d94966a7abc *vp90-2-09-subpixel-00.ivf.md5 +8cdd435d89029987ee196896e21520e5f879f04d *vp90-2-bbb_1280x720_tile_1x4_1310kbps.webm +091b373aa2ecb59aa5c647affd5bcafcc7547364 *vp90-2-bbb_1920x1080_tile_1x1_2581kbps.webm +87ee28032b0963a44b73a850fcc816a6dc83efbb *vp90-2-bbb_1920x1080_tile_1x4_2586kbps.webm +c6ce25c4bfd4bdfc2932b70428e3dfe11210ec4f *vp90-2-bbb_1920x1080_tile_1x4_fpm_2304kbps.webm +2064bdb22aa71c2691e0469fb62e8087a43f08f8 *vp90-2-bbb_426x240_tile_1x1_180kbps.webm +8080eda22694910162f0996e8a962612f381a57f *vp90-2-bbb_640x360_tile_1x2_337kbps.webm +a484b335c27ea189c0f0d77babea4a510ce12d50 *vp90-2-bbb_854x480_tile_1x2_651kbps.webm +3eacf1f006250be4cc5c92a7ef146e385ee62653 *vp90-2-sintel_1280x546_tile_1x4_1257kbps.webm +217f089a16447490823127b36ce0d945522accfd *vp90-2-sintel_1920x818_tile_1x4_fpm_2279kbps.webm +eedb3c641e60dacbe082491a16df529a5c9187df *vp90-2-sintel_426x182_tile_1x1_171kbps.webm +cb7e4955af183dff33bcba0c837f0922ab066400 *vp90-2-sintel_640x272_tile_1x2_318kbps.webm +48613f9380e2580002f8a09d6e412ea4e89a52b9 *vp90-2-sintel_854x364_tile_1x2_621kbps.webm +990a91f24dd284562d21d714ae773dff5452cad8 *vp90-2-tos_1280x534_tile_1x4_1306kbps.webm +aa402217577a659cfc670157735b4b8e9aa670fe *vp90-2-tos_1280x534_tile_1x4_fpm_952kbps.webm +b6dd558c90bca466b4bcbd03b3371648186465a7 *vp90-2-tos_1920x800_tile_1x4_fpm_2335kbps.webm +1a9c2914ba932a38f0a143efc1ad0e318e78888b *vp90-2-tos_426x178_tile_1x1_181kbps.webm +a3d2b09f24debad4747a1b3066f572be4273bced *vp90-2-tos_640x266_tile_1x2_336kbps.webm +c64b03b5c090e6888cb39685c31f00a6b79fa45c *vp90-2-tos_854x356_tile_1x2_656kbps.webm +94b533dbcf94292001e27cc51fec87f9e8c90c0b *vp90-2-tos_854x356_tile_1x2_fpm_546kbps.webm +0e7cd4135b231c9cea8d76c19f9e84b6fd77acec *vp90-2-08-tile_1x8_frame_parallel.webm +c9b6850af28579b031791066457f4cb40df6e1c7 *vp90-2-08-tile_1x8_frame_parallel.webm.md5 +e448b6e83490bca0f8d58b4f4b1126a17baf4b0c *vp90-2-08-tile_1x8.webm +5e524165f0397e6141d914f4f0a66267d7658376 *vp90-2-08-tile_1x8.webm.md5 +a34e14923d6d17b1144254d8187d7f85b700a63c *vp90-2-02-size-lf-1920x1080.webm +e3b28ddcfaeb37fb4d132b93f92642a9ad17c22d *vp90-2-02-size-lf-1920x1080.webm.md5 +d48c5db1b0f8e60521a7c749696b8067886033a3 *vp90-2-09-aq2.webm +84c1599298aac78f2fc05ae2274575d10569dfa0 *vp90-2-09-aq2.webm.md5 +55fc55ed73d578ed60fad05692579873f8bad758 *vp90-2-09-lf_deltas.webm +54638c38009198c38c8f3b25c182b709b6c1fd2e *vp90-2-09-lf_deltas.webm.md5 +510d95f3beb3b51c572611fdaeeece12277dac30 *vp90-2-10-show-existing-frame.webm +14d631096f4bfa2d71f7f739aec1448fb3c33bad *vp90-2-10-show-existing-frame.webm.md5 +d2feea7728e8d2c615981d0f47427a4a5a45d881 *vp90-2-10-show-existing-frame2.webm +5f7c7811baa3e4f03be1dd78c33971b727846821 *vp90-2-10-show-existing-frame2.webm.md5 +b4318e75f73a6a08992c7326de2fb589c2a794c7 *vp90-2-11-size-351x287.webm +b3c48382cf7d0454e83a02497c229d27720f9e20 *vp90-2-11-size-351x287.webm.md5 +8e0096475ea2535bac71d3e2fc09e0c451c444df *vp90-2-11-size-351x288.webm +19e003804ec1dfc5464813b32339a15d5ba7b42f *vp90-2-11-size-351x288.webm.md5 +40cd1d6a188d7a88b21ebac1e573d3f270ab261e *vp90-2-11-size-352x287.webm +68f515abe3858fc1eded46c8e6b2f727d43b5331 *vp90-2-11-size-352x287.webm.md5 +9a510769ff23db410880ec3029d433e87d17f7fc *vp90-2-12-droppable_1.ivf +952eaac6eefa6f62179ed1db3e922fd42fecc624 *vp90-2-12-droppable_1.ivf.md5 +9a510769ff23db410880ec3029d433e87d17f7fc *vp90-2-12-droppable_2.ivf +92a756469fa438220524e7fa6ac1d38c89514d17 *vp90-2-12-droppable_2.ivf.md5 +c21e97e4ba486520118d78b01a5cb6e6dc33e190 *vp90-2-12-droppable_3.ivf +601abc9e4176c70f82ac0381365e9b151fdd24cd *vp90-2-12-droppable_3.ivf.md5 +61c640dad23cd4f7ad811b867e7b7e3521f4e3ba *vp90-2-13-largescaling.webm +bca1b02eebdb088fa3f389fe0e7571e75a71f523 *vp90-2-13-largescaling.webm.md5 +c740708fa390806eebaf669909c1285ab464f886 *vp90-2-14-resize-fp-tiles-1-2.webm +c7b85ffd8e11500f73f52e7dc5a47f57c393d47f *vp90-2-14-resize-fp-tiles-1-2.webm.md5 +ec8faa352a08f7033c60f29f80d505e2d7daa103 *vp90-2-14-resize-fp-tiles-1-4.webm +6852c783fb421bda5ded3d4c5a3ffc46de03fbc1 *vp90-2-14-resize-fp-tiles-1-4.webm.md5 +8af61853ac0d07c4cb5bf7c2016661ba350b3497 *vp90-2-14-resize-fp-tiles-1-8.webm +571353bac89fea60b5706073409aa3c0d42aefe9 *vp90-2-14-resize-fp-tiles-1-8.webm.md5 +b1c187ed69931496b82ec194017a79831bafceef *vp90-2-14-resize-fp-tiles-1-16.webm +1c199a41afe42ce303944d70089eaaa2263b4a09 *vp90-2-14-resize-fp-tiles-1-16.webm.md5 +8eaae5a6f2dff934610b0c7a917d7f583ba74aa5 *vp90-2-14-resize-fp-tiles-2-1.webm +db18fcf915f7ffaea6c39feab8bda6c1688af011 *vp90-2-14-resize-fp-tiles-2-1.webm.md5 +bc3046d138941e2a20e9ceec0ff6d25c25d12af3 *vp90-2-14-resize-fp-tiles-4-1.webm +393211b808030d09a79927b17a4374b2f68a60ae *vp90-2-14-resize-fp-tiles-4-1.webm.md5 +6e8f8e31721a0f7f68a2964e36e0e698c2e276b1 *vp90-2-14-resize-fp-tiles-8-1.webm +491fd3cd78fb0577bfe905bb64bbf64bd7d29140 *vp90-2-14-resize-fp-tiles-8-1.webm.md5 +cc5958da2a7edf739cd2cfeb18bd05e77903087e *vp90-2-14-resize-fp-tiles-16-1.webm +0b58daf55aaf9063bf5b4fb33393d18b417dc428 *vp90-2-14-resize-fp-tiles-16-1.webm.md5 +821eeecc9d8c6a316134dd42d1ff057787d8047b *vp90-2-14-resize-fp-tiles-2-4.webm +374c549f2839a3d0b732c4e3650700144037e76c *vp90-2-14-resize-fp-tiles-2-4.webm.md5 +dff8c8e49aacea9f4c7f22cb882da984e2a1b405 *vp90-2-14-resize-fp-tiles-2-8.webm +e5b8820a7c823b21297d6e889e57ec401882c210 *vp90-2-14-resize-fp-tiles-2-8.webm.md5 +77629e4b23e32896aadf6e994c78bd4ffa1c7797 *vp90-2-14-resize-fp-tiles-2-16.webm +1937f5df032664ac345d4613ad4417b4967b1230 *vp90-2-14-resize-fp-tiles-2-16.webm.md5 +380ba5702bb1ec7947697314ab0300b5c56a1665 *vp90-2-14-resize-fp-tiles-4-2.webm +fde7b30d2aa64c1e851a4852f655d79fc542cf66 *vp90-2-14-resize-fp-tiles-4-2.webm.md5 +dc784b258ffa2abc2ae693d11792acf0bb9cb74f *vp90-2-14-resize-fp-tiles-8-2.webm +edf26f0130aeee8342d49c2c8f0793ad008782d9 *vp90-2-14-resize-fp-tiles-8-2.webm.md5 +8e575789fd63ebf69e8eff1b9a4351a249a73bee *vp90-2-14-resize-fp-tiles-16-2.webm +b6415318c1c589a1f64b9d569ce3cabbec2e0d52 *vp90-2-14-resize-fp-tiles-16-2.webm.md5 +e3adc944a11c4c5517e63664c84ebb0847b64d81 *vp90-2-14-resize-fp-tiles-4-8.webm +03cba0532bc90a05b1990db830bf5701e24e7982 *vp90-2-14-resize-fp-tiles-4-8.webm.md5 +3b27a991eb6d78dce38efab35b7db682e8cbbee3 *vp90-2-14-resize-fp-tiles-4-16.webm +5d16b7f82bf59f802724ddfd97abb487150b1c9d *vp90-2-14-resize-fp-tiles-4-16.webm.md5 +d5fed8c28c1d4c7e232ebbd25cf758757313ed96 *vp90-2-14-resize-fp-tiles-8-4.webm +5a8ff8a52cbbde7bfab569beb6d971c5f8b904f7 *vp90-2-14-resize-fp-tiles-8-4.webm.md5 +17a5faa023d77ee9dad423a4e0d3145796bbc500 *vp90-2-14-resize-fp-tiles-16-4.webm +2ef8daa3c3e750fd745130d0a76a39fe86f0448f *vp90-2-14-resize-fp-tiles-16-4.webm.md5 +9361e031f5cc990d8740863e310abb5167ae351e *vp90-2-14-resize-fp-tiles-8-16.webm +57f13a2197486584f4e1a4f82ad969f3abc5a1a2 *vp90-2-14-resize-fp-tiles-8-16.webm.md5 +5803fc6fcbfb47b7661f3fcc6499158a32b56675 *vp90-2-14-resize-fp-tiles-16-8.webm +be0fe64a1a4933696ff92d93f9bdecdbd886dc13 *vp90-2-14-resize-fp-tiles-16-8.webm.md5 +0ac0f6d20a0afed77f742a3b9acb59fd7b9cb093 *vp90-2-14-resize-fp-tiles-1-2-4-8-16.webm +1765315acccfe6cd12230e731369fcb15325ebfa *vp90-2-14-resize-fp-tiles-1-2-4-8-16.webm.md5 +4a2b7a683576fe8e330c7d1c4f098ff4e70a43a8 *vp90-2-14-resize-fp-tiles-16-8-4-2-1.webm +1ef480392112b3509cb190afbb96f9a38dd9fbac *vp90-2-14-resize-fp-tiles-16-8-4-2-1.webm.md5 +e615575ded499ea1d992f3b38e3baa434509cdcd *vp90-2-15-segkey.webm +e3ab35d4316c5e81325c50f5236ceca4bc0d35df *vp90-2-15-segkey.webm.md5 +9b7ca2cac09d34c4a5d296c1900f93b1e2f69d0d *vp90-2-15-segkey_adpq.webm +8f46ba5f785d0c2170591a153e0d0d146a7c8090 *vp90-2-15-segkey_adpq.webm.md5 +698a6910a97486b833073ef0c0b18d75dce57ee8 *vp90-2-16-intra-only.webm +5661b0168752969f055eec37b05fa9fa947dc7eb *vp90-2-16-intra-only.webm.md5 +c01bb7938f9a9f25e0c37afdec2f2fb73b6cc7fa *vp90-2-17-show-existing-frame.webm +cc75f351818b9a619818f5cc77b9bc013d0c1e11 *vp90-2-17-show-existing-frame.webm.md5 +013708bd043f0821a3e56fb8404d82e7a0c7af6c *vp91-2-04-yuv422.webm +1e58a7d23adad830a672f1733c9d2ae17890d59c *vp91-2-04-yuv422.webm.md5 +25d78f28948789d159a9453ebc13048b818251b1 *vp91-2-04-yuv440.webm +81b3870b27a7f695ef6a43e87ab04bbdb5aee2f5 *vp91-2-04-yuv440.webm.md5 +0321d507ce62dedc8a51b4e9011f7a19aed9c3dc *vp91-2-04-yuv444.webm +367e423dd41fdb49aa028574a2cfec5c2f325c5c *vp91-2-04-yuv444.webm.md5 +f77673b566f686853adefe0c578ad251b7241281 *vp92-2-20-10bit-yuv420.webm +abdedfaddacbbe1a15ac7a54e86360f03629fb7a *vp92-2-20-10bit-yuv420.webm.md5 +0c2c355a1b17b28537c5a3b19997c8783b69f1af *vp92-2-20-12bit-yuv420.webm +afb2c2798703e039189b0a15c8ac5685aa51d33f *vp92-2-20-12bit-yuv420.webm.md5 +0d661bc6e83da33238981481efd1b1802d323d88 *vp93-2-20-10bit-yuv422.webm +10318907063db22eb02fad332556edbbecd443cc *vp93-2-20-10bit-yuv422.webm.md5 +ebc6be2f7511a0bdeac0b18c67f84ba7168839c7 *vp93-2-20-12bit-yuv422.webm +235232267c6a1dc8a11e45d600f1c99d2f8b42d4 *vp93-2-20-12bit-yuv422.webm.md5 +f76b11b26d4beaceac7a7e7729dd5054d095164f *vp93-2-20-10bit-yuv440.webm +757b33b5ac969c5999999488a731a3d1e6d9fb88 *vp93-2-20-10bit-yuv440.webm.md5 +df8807dbd29bec795c2db9c3c18e511fbb988101 *vp93-2-20-12bit-yuv440.webm +ea4100930c3f59a1c23fbb33ab0ea01151cae159 *vp93-2-20-12bit-yuv440.webm.md5 +189c1b5f404ff41a50a7fc96341085ad541314a9 *vp93-2-20-10bit-yuv444.webm +2dd0177c2f9d970b6e698892634c653630f91f40 *vp93-2-20-10bit-yuv444.webm.md5 +bd44cf6e1c27343e3639df9ac21346aedd5d6973 *vp93-2-20-12bit-yuv444.webm +f36e5bdf5ec3213f32c0ddc82f95d82c5133bf27 *vp93-2-20-12bit-yuv444.webm.md5 +eb438c6540eb429f74404eedfa3228d409c57874 *desktop_640_360_30.yuv +89e70ebd22c27d275fe14dc2f1a41841a6d8b9ab *kirland_640_480_30.yuv +33c533192759e5bb4f07abfbac389dc259db4686 *macmarcomoving_640_480_30.yuv +8bfaab121080821b8f03b23467911e59ec59b8fe *macmarcostationary_640_480_30.yuv +70894878d916a599842d9ad0dcd24e10c13e5467 *niklas_640_480_30.yuv +8784b6df2d8cc946195a90ac00540500d2e522e4 *tacomanarrows_640_480_30.yuv +edd86a1f5e62fd9da9a9d46078247759c2638009 *tacomasmallcameramovement_640_480_30.yuv +9a70e8b7d14fba9234d0e51dce876635413ce444 *thaloundeskmtg_640_480_30.yuv +e7d315dbf4f3928779e0dc624311196d44491d32 *niklas_1280_720_30.yuv +c77e4a26616add298a05dd5d12397be22c0e40c5 *vp90-2-18-resize.ivf +c12918cf0a716417fba2de35c3fc5ab90e52dfce *vp90-2-18-resize.ivf.md5 +717da707afcaa1f692ff1946f291054eb75a4f06 *screendata.y4m +b7c1296630cdf1a7ef493d15ff4f9eb2999202f6 *invalid-vp90-2-08-tile_1x2_frame_parallel.webm.ivf.s47039_r01-05_b6-.ivf +0a3884edb3fd8f9d9b500223e650f7de257b67d8 *invalid-vp90-2-08-tile_1x2_frame_parallel.webm.ivf.s47039_r01-05_b6-.ivf.res +359e138dfb66863828397b77000ea7a83c844d02 *invalid-vp90-2-08-tile_1x8_frame_parallel.webm.ivf.s288_r01-05_b6-.ivf +bbd33de01c17b165b4ce00308e8a19a942023ab8 *invalid-vp90-2-08-tile_1x8_frame_parallel.webm.ivf.s288_r01-05_b6-.ivf.res +fac89b5735be8a86b0dc05159f996a5c3208ae32 *invalid-vp90-2-09-aq2.webm.ivf.s3984_r01-05_b6-.v2.ivf +0a3884edb3fd8f9d9b500223e650f7de257b67d8 *invalid-vp90-2-09-aq2.webm.ivf.s3984_r01-05_b6-.v2.ivf.res +4506dfdcdf8ee4250924b075a0dcf1f070f72e5a *invalid-vp90-2-09-subpixel-00.ivf.s19552_r01-05_b6-.v2.ivf +bcdedaf168ac225575468fda77502d2dc9fd5baa *invalid-vp90-2-09-subpixel-00.ivf.s19552_r01-05_b6-.v2.ivf.res +65e93f9653bcf65b022f7d225268d1a90a76e7bb *vp90-2-19-skip.webm +368dccdde5288c13c25695d2eacdc7402cadf613 *vp90-2-19-skip.webm.md5 +ffe460282df2b0e7d4603c2158653ad96f574b02 *vp90-2-19-skip-01.webm +bd21bc9eda4a4a36b221d71ede3a139fc3c7bd85 *vp90-2-19-skip-01.webm.md5 +178f5bd239e38cc1cc2657a7a5e1a9f52ad2d3fe *vp90-2-19-skip-02.webm +9020d5e260bd7df08e2b3d4b86f8623cee3daea2 *vp90-2-19-skip-02.webm.md5 +b03c408cf23158638da18dbc3323b99a1635c68a *invalid-vp90-2-12-droppable_1.ivf.s3676_r01-05_b6-.ivf +0a3884edb3fd8f9d9b500223e650f7de257b67d8 *invalid-vp90-2-12-droppable_1.ivf.s3676_r01-05_b6-.ivf.res +5e67e24e7f53fd189e565513cef8519b1bd6c712 *invalid-vp90-2-05-resize.ivf.s59293_r01-05_b6-.ivf +741158f67c0d9d23726624d06bdc482ad368afc9 *invalid-vp90-2-05-resize.ivf.s59293_r01-05_b6-.ivf.res +8b1f7bf7e86c0976d277f60e8fcd9539e75a079a *invalid-vp90-2-09-subpixel-00.ivf.s20492_r01-05_b6-.v2.ivf +9c6bdf048fb2e66f07d4b4db5b32e6f303bd6109 *invalid-vp90-2-09-subpixel-00.ivf.s20492_r01-05_b6-.v2.ivf.res +552e372e9b78127389fb06b34545df2cec15ba6d *invalid-vp91-2-mixedrefcsp-444to420.ivf +a61774cf03fc584bd9f0904fc145253bb8ea6c4c *invalid-vp91-2-mixedrefcsp-444to420.ivf.res +812d05a64a0d83c1b504d0519927ddc5a2cdb273 *invalid-vp90-2-12-droppable_1.ivf.s73804_r01-05_b6-.ivf +1e472baaf5f6113459f0399a38a5a5e68d17799d *invalid-vp90-2-12-droppable_1.ivf.s73804_r01-05_b6-.ivf.res +f97088c7359fc8d3d5aa5eafe57bc7308b3ee124 *vp90-2-20-big_superframe-01.webm +47d7d409785afa33b123376de0c907336e6c7bd7 *vp90-2-20-big_superframe-01.webm.md5 +65ade6d2786209582c50d34cfe22b3cdb033abaf *vp90-2-20-big_superframe-02.webm +7c0ed8d04c4d06c5411dd2e5de2411d37f092db5 *vp90-2-20-big_superframe-02.webm.md5 +667ec8718c982aef6be07eb94f083c2efb9d2d16 *vp90-2-07-frame_parallel-1.webm +bfc82bf848e9c05020d61e3ffc1e62f25df81d19 *vp90-2-07-frame_parallel-1.webm.md5 +efd5a51d175cfdacd169ed23477729dc558030dc *invalid-vp90-2-07-frame_parallel-1.webm +9f912712ec418be69adb910e2ca886a63c4cec08 *invalid-vp90-2-07-frame_parallel-2.webm +445f5a53ca9555341852997ccdd480a51540bd14 *invalid-vp90-2-07-frame_parallel-3.webm +d18c90709a0d03c82beadf10898b27d88fff719c *invalid-vp90-2-03-size-224x196.webm.ivf.s44156_r01-05_b6-.ivf +d06285d109ecbaef63b0cbcc44d70a129186f51c *invalid-vp90-2-03-size-224x196.webm.ivf.s44156_r01-05_b6-.ivf.res +e60d859b0ef2b331b21740cf6cb83fabe469b079 *invalid-vp90-2-03-size-202x210.webm.ivf.s113306_r01-05_b6-.ivf +0ae808dca4d3c1152a9576e14830b6faa39f1b4a *invalid-vp90-2-03-size-202x210.webm.ivf.s113306_r01-05_b6-.ivf.res +9cfc855459e7549fd015c79e8eca512b2f2cb7e3 *niklas_1280_720_30.y4m +5b5763b388b1b52a81bb82b39f7ec25c4bd3d0e1 *desktop_credits.y4m +85771f6ab44e4a0226e206c0cde8351dd5918953 *vp90-2-02-size-130x132.webm +512dad5eabbed37b4bbbc64ce153f1a5484427b8 *vp90-2-02-size-130x132.webm.md5 +01f7127d40360289db63b27f61cb9afcda350e95 *vp90-2-02-size-132x130.webm +4a94275328ae076cf60f966c097a8721010fbf5a *vp90-2-02-size-132x130.webm.md5 +f41c0400b5716b4b70552c40dd03d44be131e1cc *vp90-2-02-size-132x132.webm +1a69e989f697e424bfe3e3e8a77bb0c0992c8e47 *vp90-2-02-size-132x132.webm.md5 +94a5cbfacacba100e0c5f7861c72a1b417feca0f *vp90-2-02-size-178x180.webm +dedfecf1d784bcf70629592fa5e6f01d5441ccc9 *vp90-2-02-size-178x180.webm.md5 +4828b62478c04014bba3095a83106911a71cf387 *vp90-2-02-size-180x178.webm +423da2b861050c969d78ed8e8f8f14045d1d8199 *vp90-2-02-size-180x178.webm.md5 +338f7c9282f43e29940f5391118aadd17e4f9234 *vp90-2-02-size-180x180.webm +6c2ef013392310778dca5dd5351160eca66b0a60 *vp90-2-02-size-180x180.webm.md5 +679fa7d6807e936ff937d7b282e7dbd8ac76447e *vp90-2-14-resize-10frames-fp-tiles-1-2-4-8.webm +fc7267ab8fc2bf5d6c234e34ee6c078a967b4888 *vp90-2-14-resize-10frames-fp-tiles-1-2-4-8.webm.md5 +9d33a137c819792209c5ce4e4e1ee5da73d574fe *vp90-2-14-resize-10frames-fp-tiles-1-2.webm +0c78a154956a8605d050bdd75e0dcc4d39c040a6 *vp90-2-14-resize-10frames-fp-tiles-1-2.webm.md5 +d6a8d8c57f66a91d23e8e7df480f9ae841e56c37 *vp90-2-14-resize-10frames-fp-tiles-1-4.webm +e9b4e8c7b33b5fda745d340c3f47e6623ae40cf2 *vp90-2-14-resize-10frames-fp-tiles-1-4.webm.md5 +aa6fe043a0c4a42b49c87ebbe812d4afd9945bec *vp90-2-14-resize-10frames-fp-tiles-1-8.webm +028520578994c2d013d4c0129033d4f2ff31bbe0 *vp90-2-14-resize-10frames-fp-tiles-1-8.webm.md5 +d1d5463c9ea7b5cc5f609ddedccddf656f348d1a *vp90-2-14-resize-10frames-fp-tiles-2-1.webm +92d5872f5bdffbed721703b7e959b4f885e3d77a *vp90-2-14-resize-10frames-fp-tiles-2-1.webm.md5 +677cb29de1215d97346015af5807a9b1faad54cf *vp90-2-14-resize-10frames-fp-tiles-2-4.webm +a5db19f977094ec3fd60b4f7671b3e6740225e12 *vp90-2-14-resize-10frames-fp-tiles-2-4.webm.md5 +cdd3c52ba21067efdbb2de917fe2a965bf27332e *vp90-2-14-resize-10frames-fp-tiles-2-8.webm +db17ec5d894ea8b8d0b7f32206d0dd3d46dcfa6d *vp90-2-14-resize-10frames-fp-tiles-2-8.webm.md5 +0f6093c472125d05b764d7d1965c1d56771c0ea2 *vp90-2-14-resize-10frames-fp-tiles-4-1.webm +bc7c79e1bee07926dd970462ce6f64fc30eec3e1 *vp90-2-14-resize-10frames-fp-tiles-4-1.webm.md5 +c5142e2bff4091338196c8ea8bc9266e64f548bc *vp90-2-14-resize-10frames-fp-tiles-4-2.webm +22aa3dd430b69fd3d92f6561bac86deeed90486d *vp90-2-14-resize-10frames-fp-tiles-4-2.webm.md5 +ede8b1466d2f26e1b1bd9602addb9cd1017e1d8c *vp90-2-14-resize-10frames-fp-tiles-4-8.webm +508d5ebb9c0eac2a4100281a3ee052ec2fc19217 *vp90-2-14-resize-10frames-fp-tiles-4-8.webm.md5 +2b292e3392854cd1d76ae597a6f53656cf741cfa *vp90-2-14-resize-10frames-fp-tiles-8-1.webm +1c24e54fa19e94e1722f24676404444e941c3d31 *vp90-2-14-resize-10frames-fp-tiles-8-1.webm.md5 +61beda21064e09634564caa6697ab90bd53c9af7 *vp90-2-14-resize-10frames-fp-tiles-8-2.webm +9c0657b4d9e1d0e4c9d28a90e5a8630a65519124 *vp90-2-14-resize-10frames-fp-tiles-8-2.webm.md5 +1758c50a11a7c92522749b4a251664705f1f0d4b *vp90-2-14-resize-10frames-fp-tiles-8-4-2-1.webm +4f454a06750614314ae15a44087b79016fe2db97 *vp90-2-14-resize-10frames-fp-tiles-8-4-2-1.webm.md5 +3920c95ba94f1f048a731d9d9b416043b44aa4bd *vp90-2-14-resize-10frames-fp-tiles-8-4.webm +4eb347a0456d2c49a1e1d8de5aa1c51acc39887e *vp90-2-14-resize-10frames-fp-tiles-8-4.webm.md5 +4b95a74c032a473b6683d7ad5754db1b0ec378e9 *vp90-2-21-resize_inter_1280x720_5_1-2.webm +a7826dd386bedfe69d02736969bfb47fb6a40a5e *vp90-2-21-resize_inter_1280x720_5_1-2.webm.md5 +5cfff79e82c4d69964ccb8e75b4f0c53b9295167 *vp90-2-21-resize_inter_1280x720_5_3-4.webm +a18f57db4a25e1f543a99f2ceb182e00db0ee22f *vp90-2-21-resize_inter_1280x720_5_3-4.webm.md5 +d26db0811bf30eb4131d928669713e2485f8e833 *vp90-2-21-resize_inter_1280x720_7_1-2.webm +fd6f9f332cd5bea4c0f0d57be4297bea493cc5a1 *vp90-2-21-resize_inter_1280x720_7_1-2.webm.md5 +5c7d73d4d268e2ba9593b31cb091fd339505c7fd *vp90-2-21-resize_inter_1280x720_7_3-4.webm +7bbb949cabc1e70dadcc74582739f63b833034e0 *vp90-2-21-resize_inter_1280x720_7_3-4.webm.md5 +f2d2a41a60eb894aff0c5854afca15931f1445a8 *vp90-2-21-resize_inter_1920x1080_5_1-2.webm +66d7789992613ac9d678ff905ff1059daa1b89e4 *vp90-2-21-resize_inter_1920x1080_5_1-2.webm.md5 +764edb75fe7dd64e73a1b4f3b4b2b1bf237a4dea *vp90-2-21-resize_inter_1920x1080_5_3-4.webm +f78bea1075983fd990e7f25d4f31438f9b5efa34 *vp90-2-21-resize_inter_1920x1080_5_3-4.webm.md5 +96496f2ade764a5de9f0c27917c7df1f120fb2ef *vp90-2-21-resize_inter_1920x1080_7_1-2.webm +2632b635135ed5ecd67fd22dec7990d29c4f4cb5 *vp90-2-21-resize_inter_1920x1080_7_1-2.webm.md5 +74889ea42001bf41428cb742ca74e65129c886dc *vp90-2-21-resize_inter_1920x1080_7_3-4.webm +d2cf3b25956415bb579d368e7098097e482dd73a *vp90-2-21-resize_inter_1920x1080_7_3-4.webm.md5 +4658986a8ce36ebfcc80a1903e446eaab3985336 *vp90-2-21-resize_inter_320x180_5_1-2.webm +8a3d8cf325109ffa913cc9426c32eea8c202a09a *vp90-2-21-resize_inter_320x180_5_1-2.webm.md5 +16303aa45176520ee42c2c425247aadc1506b881 *vp90-2-21-resize_inter_320x180_5_3-4.webm +41cab1ddf7715b680a4dbce42faa9bcd72af4e5c *vp90-2-21-resize_inter_320x180_5_3-4.webm.md5 +56648adcee66dd0e5cb6ac947f5ee1b9cc8ba129 *vp90-2-21-resize_inter_320x180_7_1-2.webm +70047377787003cc03dda7b2394e6d7eaa666d9e *vp90-2-21-resize_inter_320x180_7_1-2.webm.md5 +d2ff99165488499cc55f75929f1ce5ca9c9e359b *vp90-2-21-resize_inter_320x180_7_3-4.webm +e69019e378114a4643db283b66d1a7e304761a56 *vp90-2-21-resize_inter_320x180_7_3-4.webm.md5 +4834d129bed0f4289d3a88f2ae3a1736f77621b0 *vp90-2-21-resize_inter_320x240_5_1-2.webm +a75653c53d22b623c1927fc0088da21dafef21f4 *vp90-2-21-resize_inter_320x240_5_1-2.webm.md5 +19818e1b7fd1c1e63d8873c31b0babe29dd33ba6 *vp90-2-21-resize_inter_320x240_5_3-4.webm +8d89814ff469a186312111651b16601dfbce4336 *vp90-2-21-resize_inter_320x240_5_3-4.webm.md5 +ac8057bae52498f324ce92a074d5f8207cc4a4a7 *vp90-2-21-resize_inter_320x240_7_1-2.webm +2643440898c83c08cc47bc744245af696b877c24 *vp90-2-21-resize_inter_320x240_7_1-2.webm.md5 +cf4a4cd38ac8b18c42d8c25a3daafdb39132256b *vp90-2-21-resize_inter_320x240_7_3-4.webm +70ba8ec9120b26e9b0ffa2c79b432f16cbcb50ec *vp90-2-21-resize_inter_320x240_7_3-4.webm.md5 +669f10409fe1c4a054010162ca47773ea1fdbead *vp90-2-21-resize_inter_640x360_5_1-2.webm +6355a04249004a35fb386dd1024214234f044383 *vp90-2-21-resize_inter_640x360_5_1-2.webm.md5 +c23763b950b8247c1775d1f8158d93716197676c *vp90-2-21-resize_inter_640x360_5_3-4.webm +59e6fc381e3ec3b7bdaac586334e0bc944d18fb6 *vp90-2-21-resize_inter_640x360_5_3-4.webm.md5 +71b45cbfdd068baa1f679a69e5e6f421d256a85f *vp90-2-21-resize_inter_640x360_7_1-2.webm +1416fc761b690c54a955c4cf017fa078520e8c18 *vp90-2-21-resize_inter_640x360_7_1-2.webm.md5 +6c409903279448a697e4db63bab1061784bcd8d2 *vp90-2-21-resize_inter_640x360_7_3-4.webm +60de1299793433a630b71130cf76c9f5965758e2 *vp90-2-21-resize_inter_640x360_7_3-4.webm.md5 +852b597b8af096d90c80bf0ed6ed3b336b851f19 *vp90-2-21-resize_inter_640x480_5_1-2.webm +f6856f19236ee46ed462bd0a2e7e72b9c3b9cea6 *vp90-2-21-resize_inter_640x480_5_1-2.webm.md5 +792a16c6f60043bd8dceb515f0b95b8891647858 *vp90-2-21-resize_inter_640x480_5_3-4.webm +68ffe59877e9a7863805e1c0a3ce18ce037d7c9d *vp90-2-21-resize_inter_640x480_5_3-4.webm.md5 +61e044c4759972a35ea3db8c1478a988910a4ef4 *vp90-2-21-resize_inter_640x480_7_1-2.webm +7739bfca167b1b43fea72f807f01e097b7cb98d8 *vp90-2-21-resize_inter_640x480_7_1-2.webm.md5 +7291af354b4418917eee00e3a7e366086a0b7a10 *vp90-2-21-resize_inter_640x480_7_3-4.webm +4a18b09ccb36564193f0215f599d745d95bb558c *vp90-2-21-resize_inter_640x480_7_3-4.webm.md5
diff --git a/src/third_party/libvpx/test/test.mk b/src/third_party/libvpx/test/test.mk new file mode 100644 index 0000000..04acd96 --- /dev/null +++ b/src/third_party/libvpx/test/test.mk
@@ -0,0 +1,190 @@ +LIBVPX_TEST_SRCS-yes += acm_random.h +LIBVPX_TEST_SRCS-yes += clear_system_state.h +LIBVPX_TEST_SRCS-yes += codec_factory.h +LIBVPX_TEST_SRCS-yes += md5_helper.h +LIBVPX_TEST_SRCS-yes += register_state_check.h +LIBVPX_TEST_SRCS-yes += test.mk +LIBVPX_TEST_SRCS-yes += test_libvpx.cc +LIBVPX_TEST_SRCS-yes += test_vectors.cc +LIBVPX_TEST_SRCS-yes += test_vectors.h +LIBVPX_TEST_SRCS-yes += util.h +LIBVPX_TEST_SRCS-yes += video_source.h + +## +## BLACK BOX TESTS +## +## Black box tests only use the public API. +## +LIBVPX_TEST_SRCS-yes += ../md5_utils.h ../md5_utils.c +LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += ivf_video_source.h +LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += ../y4minput.h ../y4minput.c +LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += altref_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += aq_segment_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += datarate_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += encode_api_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += error_resilience_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += i420_video_source.h +LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += realtime_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += resize_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += y4m_video_source.h +LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += yuv_video_source.h + +LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += config_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += cq_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += keyframe_test.cc + +LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += byte_alignment_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += external_frame_buffer_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += invalid_file_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += user_priv_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += vp9_frame_parallel_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += active_map_refresh_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += active_map_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += borders_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += cpu_speed_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += frame_size_tests.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_lossless_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_end_to_end_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_ethread_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += level_test.cc + +LIBVPX_TEST_SRCS-yes += decode_test_driver.cc +LIBVPX_TEST_SRCS-yes += decode_test_driver.h +LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += encode_test_driver.cc +LIBVPX_TEST_SRCS-yes += encode_test_driver.h + +## IVF writing. +LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += ../ivfenc.c ../ivfenc.h + +## Y4m parsing. +LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += y4m_test.cc ../y4menc.c ../y4menc.h + +## WebM Parsing +ifeq ($(CONFIG_WEBM_IO), yes) +LIBWEBM_PARSER_SRCS += ../third_party/libwebm/mkvparser/mkvparser.cc +LIBWEBM_PARSER_SRCS += ../third_party/libwebm/mkvparser/mkvreader.cc +LIBWEBM_PARSER_SRCS += ../third_party/libwebm/mkvparser/mkvparser.h +LIBWEBM_PARSER_SRCS += ../third_party/libwebm/mkvparser/mkvreader.h +LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += $(LIBWEBM_PARSER_SRCS) +LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += ../tools_common.h +LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += ../webmdec.cc +LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += ../webmdec.h +LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += webm_video_source.h +LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += vp9_skip_loopfilter_test.cc +endif + +LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += decode_api_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += test_vector_test.cc + +# Currently we only support decoder perf tests for vp9. Also they read from WebM +# files, so WebM IO is required. +ifeq ($(CONFIG_DECODE_PERF_TESTS)$(CONFIG_VP9_DECODER)$(CONFIG_WEBM_IO), \ + yesyesyes) +LIBVPX_TEST_SRCS-yes += decode_perf_test.cc +endif + +# encode perf tests are vp9 only +ifeq ($(CONFIG_ENCODE_PERF_TESTS)$(CONFIG_VP9_ENCODER), yesyes) +LIBVPX_TEST_SRCS-yes += encode_perf_test.cc +endif + +## +## WHITE BOX TESTS +## +## Whitebox tests invoke functions not exposed via the public API. Certain +## shared library builds don't make these functions accessible. +## +ifeq ($(CONFIG_SHARED),) + +## VP8 +ifeq ($(CONFIG_VP8),yes) + +# These tests require both the encoder and decoder to be built. +ifeq ($(CONFIG_VP8_ENCODER)$(CONFIG_VP8_DECODER),yesyes) +LIBVPX_TEST_SRCS-yes += vp8_boolcoder_test.cc +LIBVPX_TEST_SRCS-yes += vp8_fragments_test.cc +endif + +LIBVPX_TEST_SRCS-$(CONFIG_POSTPROC) += add_noise_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_POSTPROC) += pp_filter_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP8_DECODER) += vp8_decrypt_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += quantize_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += set_roi.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += variance_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += vp8_fdct4x4_test.cc + +LIBVPX_TEST_SRCS-yes += idct_test.cc +LIBVPX_TEST_SRCS-yes += sixtap_predict_test.cc +LIBVPX_TEST_SRCS-yes += vpx_scale_test.cc + +ifeq ($(CONFIG_VP8_ENCODER)$(CONFIG_TEMPORAL_DENOISING),yesyes) +LIBVPX_TEST_SRCS-$(HAVE_SSE2) += vp8_denoiser_sse2_test.cc +endif + +endif # VP8 + +## VP9 +ifeq ($(CONFIG_VP9),yes) + +# These tests require both the encoder and decoder to be built. +ifeq ($(CONFIG_VP9_ENCODER)$(CONFIG_VP9_DECODER),yesyes) +# IDCT test currently depends on FDCT function +LIBVPX_TEST_SRCS-yes += idct8x8_test.cc +LIBVPX_TEST_SRCS-yes += partial_idct_test.cc +LIBVPX_TEST_SRCS-yes += superframe_test.cc +LIBVPX_TEST_SRCS-yes += tile_independence_test.cc +LIBVPX_TEST_SRCS-yes += vp9_boolcoder_test.cc +LIBVPX_TEST_SRCS-yes += vp9_encoder_parms_get_to_decoder.cc +endif + +LIBVPX_TEST_SRCS-yes += convolve_test.cc +LIBVPX_TEST_SRCS-yes += lpf_8_test.cc +LIBVPX_TEST_SRCS-yes += vp9_intrapred_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += vp9_decrypt_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += vp9_thread_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += dct16x16_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += dct32x32_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += fdct4x4_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += fdct8x8_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += hadamard_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += minmax_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += variance_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_error_block_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_quantize_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_subtract_test.cc + +ifeq ($(CONFIG_VP9_ENCODER),yes) +LIBVPX_TEST_SRCS-$(CONFIG_SPATIAL_SVC) += svc_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_INTERNAL_STATS) += blockiness_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_INTERNAL_STATS) += consistency_test.cc +endif + +ifeq ($(CONFIG_VP9_ENCODER)$(CONFIG_VP9_TEMPORAL_DENOISING),yesyes) +LIBVPX_TEST_SRCS-$(HAVE_SSE2) += vp9_denoiser_sse2_test.cc +endif +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_arf_freq_test.cc + +endif # VP9 + +## VP10 +ifeq ($(CONFIG_VP10),yes) + +LIBVPX_TEST_SRCS-yes += vp10_inv_txfm_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP10_ENCODER) += vp10_dct_test.cc + +endif # VP10 + +## Multi-codec / unconditional whitebox tests. + +ifeq ($(findstring yes,$(CONFIG_VP9_ENCODER)$(CONFIG_VP10_ENCODER)),yes) +LIBVPX_TEST_SRCS-yes += avg_test.cc +endif + +LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += sad_test.cc + +TEST_INTRA_PRED_SPEED_SRCS-yes := test_intra_pred_speed.cc +TEST_INTRA_PRED_SPEED_SRCS-yes += ../md5_utils.h ../md5_utils.c + +endif # CONFIG_SHARED + +include $(SRC_PATH_BARE)/test/test-data.mk
diff --git a/src/third_party/libvpx/test/test_intra_pred_speed.cc b/src/third_party/libvpx/test/test_intra_pred_speed.cc new file mode 100644 index 0000000..2acf744 --- /dev/null +++ b/src/third_party/libvpx/test/test_intra_pred_speed.cc
@@ -0,0 +1,373 @@ +/* + * Copyright (c) 2015 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +// Test and time VPX intra-predictor functions + +#include <stdio.h> +#include <string.h> + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "./vpx_dsp_rtcd.h" +#include "test/acm_random.h" +#include "test/clear_system_state.h" +#include "test/md5_helper.h" +#include "vpx/vpx_integer.h" +#include "vpx_ports/mem.h" +#include "vpx_ports/vpx_timer.h" + +// ----------------------------------------------------------------------------- + +namespace { + +typedef void (*VpxPredFunc)(uint8_t *dst, ptrdiff_t y_stride, + const uint8_t *above, const uint8_t *left); + +const int kNumVp9IntraPredFuncs = 13; +const char *kVp9IntraPredNames[kNumVp9IntraPredFuncs] = { + "DC_PRED", "DC_LEFT_PRED", "DC_TOP_PRED", "DC_128_PRED", "V_PRED", "H_PRED", + "D45_PRED", "D135_PRED", "D117_PRED", "D153_PRED", "D207_PRED", "D63_PRED", + "TM_PRED" +}; + +void TestIntraPred(const char name[], VpxPredFunc const *pred_funcs, + const char *const pred_func_names[], int num_funcs, + const char *const signatures[], int block_size, + int num_pixels_per_test) { + libvpx_test::ACMRandom rnd(libvpx_test::ACMRandom::DeterministicSeed()); + const int kBPS = 32; + const int kTotalPixels = 32 * kBPS; + DECLARE_ALIGNED(16, uint8_t, src[kTotalPixels]); + DECLARE_ALIGNED(16, uint8_t, ref_src[kTotalPixels]); + DECLARE_ALIGNED(16, uint8_t, left[kBPS]); + DECLARE_ALIGNED(16, uint8_t, above_mem[2 * kBPS + 16]); + uint8_t *const above = above_mem + 16; + for (int i = 0; i < kTotalPixels; ++i) ref_src[i] = rnd.Rand8(); + for (int i = 0; i < kBPS; ++i) left[i] = rnd.Rand8(); + for (int i = -1; i < kBPS; ++i) above[i] = rnd.Rand8(); + const int kNumTests = static_cast<int>(2.e10 / num_pixels_per_test); + + // some code assumes the top row has been extended: + // d45/d63 C-code, for instance, but not the assembly. + // TODO(jzern): this style of extension isn't strictly necessary. + ASSERT_LE(block_size, kBPS); + memset(above + block_size, above[block_size - 1], 2 * kBPS - block_size); + + for (int k = 0; k < num_funcs; ++k) { + if (pred_funcs[k] == NULL) continue; + memcpy(src, ref_src, sizeof(src)); + vpx_usec_timer timer; + vpx_usec_timer_start(&timer); + for (int num_tests = 0; num_tests < kNumTests; ++num_tests) { + pred_funcs[k](src, kBPS, above, left); + } + libvpx_test::ClearSystemState(); + vpx_usec_timer_mark(&timer); + const int elapsed_time = + static_cast<int>(vpx_usec_timer_elapsed(&timer) / 1000); + libvpx_test::MD5 md5; + md5.Add(src, sizeof(src)); + printf("Mode %s[%12s]: %5d ms MD5: %s\n", name, pred_func_names[k], + elapsed_time, md5.Get()); + EXPECT_STREQ(signatures[k], md5.Get()); + } +} + +void TestIntraPred4(VpxPredFunc const *pred_funcs) { + static const int kNumVp9IntraFuncs = 13; + static const char *const kSignatures[kNumVp9IntraFuncs] = { + "4334156168b34ab599d9b5b30f522fe9", + "bc4649d5ba47c7ff178d92e475960fb0", + "8d316e5933326dcac24e1064794b5d12", + "a27270fed024eafd762c95de85f4da51", + "c33dff000d4256c2b8f3bf9e9bab14d2", + "44d8cddc2ad8f79b8ed3306051722b4f", + "eb54839b2bad6699d8946f01ec041cd0", + "ecb0d56ae5f677ea45127ce9d5c058e4", + "0b7936841f6813da818275944895b574", + "9117972ef64f91a58ff73e1731c81db2", + "c56d5e8c729e46825f46dd5d3b5d508a", + "c0889e2039bcf7bcb5d2f33cdca69adc", + "309a618577b27c648f9c5ee45252bc8f", + }; + TestIntraPred("Intra4", pred_funcs, kVp9IntraPredNames, kNumVp9IntraFuncs, + kSignatures, 4, 4 * 4 * kNumVp9IntraFuncs); +} + +void TestIntraPred8(VpxPredFunc const *pred_funcs) { + static const int kNumVp9IntraFuncs = 13; + static const char *const kSignatures[kNumVp9IntraFuncs] = { + "7694ddeeefed887faf9d339d18850928", + "7d726b1213591b99f736be6dec65065b", + "19c5711281357a485591aaf9c96c0a67", + "ba6b66877a089e71cd938e3b8c40caac", + "802440c93317e0f8ba93fab02ef74265", + "9e09a47a15deb0b9d8372824f9805080", + "b7c2d8c662268c0c427da412d7b0311d", + "78339c1c60bb1d67d248ab8c4da08b7f", + "5c97d70f7d47de1882a6cd86c165c8a9", + "8182bf60688b42205acd95e59e967157", + "08323400005a297f16d7e57e7fe1eaac", + "95f7bfc262329a5849eda66d8f7c68ce", + "815b75c8e0d91cc1ae766dc5d3e445a3", + }; + TestIntraPred("Intra8", pred_funcs, kVp9IntraPredNames, kNumVp9IntraFuncs, + kSignatures, 8, 8 * 8 * kNumVp9IntraFuncs); +} + +void TestIntraPred16(VpxPredFunc const *pred_funcs) { + static const int kNumVp9IntraFuncs = 13; + static const char *const kSignatures[kNumVp9IntraFuncs] = { + "b40dbb555d5d16a043dc361e6694fe53", + "fb08118cee3b6405d64c1fd68be878c6", + "6c190f341475c837cc38c2e566b64875", + "db5c34ccbe2c7f595d9b08b0dc2c698c", + "a62cbfd153a1f0b9fed13e62b8408a7a", + "143df5b4c89335e281103f610f5052e4", + "d87feb124107cdf2cfb147655aa0bb3c", + "7841fae7d4d47b519322e6a03eeed9dc", + "f6ebed3f71cbcf8d6d0516ce87e11093", + "3cc480297dbfeed01a1c2d78dd03d0c5", + "b9f69fa6532b372c545397dcb78ef311", + "a8fe1c70432f09d0c20c67bdb6432c4d", + "b8a41aa968ec108af447af4217cba91b", + }; + TestIntraPred("Intra16", pred_funcs, kVp9IntraPredNames, kNumVp9IntraFuncs, + kSignatures, 16, 16 * 16 * kNumVp9IntraFuncs); +} + +void TestIntraPred32(VpxPredFunc const *pred_funcs) { + static const int kNumVp9IntraFuncs = 13; + static const char *const kSignatures[kNumVp9IntraFuncs] = { + "558541656d84f9ae7896db655826febe", + "b3587a1f9a01495fa38c8cd3c8e2a1bf", + "4c6501e64f25aacc55a2a16c7e8f0255", + "b3b01379ba08916ef6b1b35f7d9ad51c", + "0f1eb38b6cbddb3d496199ef9f329071", + "911c06efb9ed1c3b4c104b232b55812f", + "9225beb0ddfa7a1d24eaa1be430a6654", + "0a6d584a44f8db9aa7ade2e2fdb9fc9e", + "b01c9076525216925f3456f034fb6eee", + "d267e20ad9e5cd2915d1a47254d3d149", + "ed012a4a5da71f36c2393023184a0e59", + "f162b51ed618d28b936974cff4391da5", + "9e1370c6d42e08d357d9612c93a71cfc", + }; + TestIntraPred("Intra32", pred_funcs, kVp9IntraPredNames, kNumVp9IntraFuncs, + kSignatures, 32, 32 * 32 * kNumVp9IntraFuncs); +} + +} // namespace + +// Defines a test case for |arch| (e.g., C, SSE2, ...) passing the predictors +// to |test_func|. The test name is 'arch.test_func', e.g., C.TestIntraPred4. +#define INTRA_PRED_TEST(arch, test_func, dc, dc_left, dc_top, dc_128, v, h, \ + d45, d135, d117, d153, d207, d63, tm) \ + TEST(arch, test_func) { \ + static const VpxPredFunc vpx_intra_pred[] = { \ + dc, dc_left, dc_top, dc_128, v, h, d45, \ + d135, d117, d153, d207, d63, tm}; \ + test_func(vpx_intra_pred); \ + } + +// ----------------------------------------------------------------------------- +// 4x4 + +INTRA_PRED_TEST(C, TestIntraPred4, vpx_dc_predictor_4x4_c, + vpx_dc_left_predictor_4x4_c, vpx_dc_top_predictor_4x4_c, + vpx_dc_128_predictor_4x4_c, vpx_v_predictor_4x4_c, + vpx_h_predictor_4x4_c, vpx_d45_predictor_4x4_c, + vpx_d135_predictor_4x4_c, vpx_d117_predictor_4x4_c, + vpx_d153_predictor_4x4_c, vpx_d207_predictor_4x4_c, + vpx_d63_predictor_4x4_c, vpx_tm_predictor_4x4_c) + +#if HAVE_SSE2 && CONFIG_USE_X86INC +INTRA_PRED_TEST(SSE2, TestIntraPred4, vpx_dc_predictor_4x4_sse2, + vpx_dc_left_predictor_4x4_sse2, vpx_dc_top_predictor_4x4_sse2, + vpx_dc_128_predictor_4x4_sse2, vpx_v_predictor_4x4_sse2, + vpx_h_predictor_4x4_sse2, vpx_d45_predictor_4x4_sse2, NULL, + NULL, NULL, vpx_d207_predictor_4x4_sse2, NULL, + vpx_tm_predictor_4x4_sse2) +#endif // HAVE_SSE2 && CONFIG_USE_X86INC + +#if HAVE_SSSE3 && CONFIG_USE_X86INC +INTRA_PRED_TEST(SSSE3, TestIntraPred4, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + vpx_d153_predictor_4x4_ssse3, NULL, + vpx_d63_predictor_4x4_ssse3, NULL) +#endif // HAVE_SSSE3 && CONFIG_USE_X86INC + +#if HAVE_DSPR2 +INTRA_PRED_TEST(DSPR2, TestIntraPred4, vpx_dc_predictor_4x4_dspr2, NULL, NULL, + NULL, NULL, vpx_h_predictor_4x4_dspr2, NULL, NULL, NULL, NULL, + NULL, NULL, vpx_tm_predictor_4x4_dspr2) +#endif // HAVE_DSPR2 + +#if HAVE_NEON +INTRA_PRED_TEST(NEON, TestIntraPred4, vpx_dc_predictor_4x4_neon, + vpx_dc_left_predictor_4x4_neon, vpx_dc_top_predictor_4x4_neon, + vpx_dc_128_predictor_4x4_neon, vpx_v_predictor_4x4_neon, + vpx_h_predictor_4x4_neon, vpx_d45_predictor_4x4_neon, + vpx_d135_predictor_4x4_neon, NULL, NULL, NULL, NULL, + vpx_tm_predictor_4x4_neon) +#endif // HAVE_NEON + +#if HAVE_MSA +INTRA_PRED_TEST(MSA, TestIntraPred4, vpx_dc_predictor_4x4_msa, + vpx_dc_left_predictor_4x4_msa, vpx_dc_top_predictor_4x4_msa, + vpx_dc_128_predictor_4x4_msa, vpx_v_predictor_4x4_msa, + vpx_h_predictor_4x4_msa, NULL, NULL, NULL, NULL, NULL, + NULL, vpx_tm_predictor_4x4_msa) +#endif // HAVE_MSA + +// ----------------------------------------------------------------------------- +// 8x8 + +INTRA_PRED_TEST(C, TestIntraPred8, vpx_dc_predictor_8x8_c, + vpx_dc_left_predictor_8x8_c, vpx_dc_top_predictor_8x8_c, + vpx_dc_128_predictor_8x8_c, vpx_v_predictor_8x8_c, + vpx_h_predictor_8x8_c, vpx_d45_predictor_8x8_c, + vpx_d135_predictor_8x8_c, vpx_d117_predictor_8x8_c, + vpx_d153_predictor_8x8_c, vpx_d207_predictor_8x8_c, + vpx_d63_predictor_8x8_c, vpx_tm_predictor_8x8_c) + +#if HAVE_SSE2 && CONFIG_USE_X86INC +INTRA_PRED_TEST(SSE2, TestIntraPred8, vpx_dc_predictor_8x8_sse2, + vpx_dc_left_predictor_8x8_sse2, vpx_dc_top_predictor_8x8_sse2, + vpx_dc_128_predictor_8x8_sse2, vpx_v_predictor_8x8_sse2, + vpx_h_predictor_8x8_sse2, vpx_d45_predictor_8x8_sse2, NULL, + NULL, NULL, NULL, NULL, vpx_tm_predictor_8x8_sse2) +#endif // HAVE_SSE2 && CONFIG_USE_X86INC + +#if HAVE_SSSE3 && CONFIG_USE_X86INC +INTRA_PRED_TEST(SSSE3, TestIntraPred8, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + vpx_d153_predictor_8x8_ssse3, vpx_d207_predictor_8x8_ssse3, + vpx_d63_predictor_8x8_ssse3, NULL) +#endif // HAVE_SSSE3 && CONFIG_USE_X86INC + +#if HAVE_DSPR2 +INTRA_PRED_TEST(DSPR2, TestIntraPred8, vpx_dc_predictor_8x8_dspr2, NULL, NULL, + NULL, NULL, vpx_h_predictor_8x8_dspr2, NULL, NULL, NULL, NULL, + NULL, NULL, vpx_tm_predictor_8x8_c) +#endif // HAVE_DSPR2 + +#if HAVE_NEON +INTRA_PRED_TEST(NEON, TestIntraPred8, vpx_dc_predictor_8x8_neon, + vpx_dc_left_predictor_8x8_neon, vpx_dc_top_predictor_8x8_neon, + vpx_dc_128_predictor_8x8_neon, vpx_v_predictor_8x8_neon, + vpx_h_predictor_8x8_neon, vpx_d45_predictor_8x8_neon, NULL, + NULL, NULL, NULL, NULL, vpx_tm_predictor_8x8_neon) + +#endif // HAVE_NEON + +#if HAVE_MSA +INTRA_PRED_TEST(MSA, TestIntraPred8, vpx_dc_predictor_8x8_msa, + vpx_dc_left_predictor_8x8_msa, vpx_dc_top_predictor_8x8_msa, + vpx_dc_128_predictor_8x8_msa, vpx_v_predictor_8x8_msa, + vpx_h_predictor_8x8_msa, NULL, NULL, NULL, NULL, NULL, + NULL, vpx_tm_predictor_8x8_msa) +#endif // HAVE_MSA + +// ----------------------------------------------------------------------------- +// 16x16 + +INTRA_PRED_TEST(C, TestIntraPred16, vpx_dc_predictor_16x16_c, + vpx_dc_left_predictor_16x16_c, vpx_dc_top_predictor_16x16_c, + vpx_dc_128_predictor_16x16_c, vpx_v_predictor_16x16_c, + vpx_h_predictor_16x16_c, vpx_d45_predictor_16x16_c, + vpx_d135_predictor_16x16_c, vpx_d117_predictor_16x16_c, + vpx_d153_predictor_16x16_c, vpx_d207_predictor_16x16_c, + vpx_d63_predictor_16x16_c, vpx_tm_predictor_16x16_c) + +#if HAVE_SSE2 && CONFIG_USE_X86INC +INTRA_PRED_TEST(SSE2, TestIntraPred16, vpx_dc_predictor_16x16_sse2, + vpx_dc_left_predictor_16x16_sse2, + vpx_dc_top_predictor_16x16_sse2, + vpx_dc_128_predictor_16x16_sse2, vpx_v_predictor_16x16_sse2, + vpx_h_predictor_16x16_sse2, NULL, NULL, NULL, NULL, NULL, NULL, + vpx_tm_predictor_16x16_sse2) +#endif // HAVE_SSE2 && CONFIG_USE_X86INC + +#if HAVE_SSSE3 && CONFIG_USE_X86INC +INTRA_PRED_TEST(SSSE3, TestIntraPred16, NULL, NULL, NULL, NULL, NULL, + NULL, vpx_d45_predictor_16x16_ssse3, + NULL, NULL, vpx_d153_predictor_16x16_ssse3, + vpx_d207_predictor_16x16_ssse3, vpx_d63_predictor_16x16_ssse3, + NULL) +#endif // HAVE_SSSE3 && CONFIG_USE_X86INC + +#if HAVE_DSPR2 +INTRA_PRED_TEST(DSPR2, TestIntraPred16, vpx_dc_predictor_16x16_dspr2, NULL, + NULL, NULL, NULL, vpx_h_predictor_16x16_dspr2, NULL, NULL, NULL, + NULL, NULL, NULL, NULL) +#endif // HAVE_DSPR2 + +#if HAVE_NEON +INTRA_PRED_TEST(NEON, TestIntraPred16, vpx_dc_predictor_16x16_neon, + vpx_dc_left_predictor_16x16_neon, + vpx_dc_top_predictor_16x16_neon, + vpx_dc_128_predictor_16x16_neon, vpx_v_predictor_16x16_neon, + vpx_h_predictor_16x16_neon, vpx_d45_predictor_16x16_neon, NULL, + NULL, NULL, NULL, NULL, vpx_tm_predictor_16x16_neon) +#endif // HAVE_NEON + +#if HAVE_MSA +INTRA_PRED_TEST(MSA, TestIntraPred16, vpx_dc_predictor_16x16_msa, + vpx_dc_left_predictor_16x16_msa, vpx_dc_top_predictor_16x16_msa, + vpx_dc_128_predictor_16x16_msa, vpx_v_predictor_16x16_msa, + vpx_h_predictor_16x16_msa, NULL, NULL, NULL, NULL, NULL, + NULL, vpx_tm_predictor_16x16_msa) +#endif // HAVE_MSA + +// ----------------------------------------------------------------------------- +// 32x32 + +INTRA_PRED_TEST(C, TestIntraPred32, vpx_dc_predictor_32x32_c, + vpx_dc_left_predictor_32x32_c, vpx_dc_top_predictor_32x32_c, + vpx_dc_128_predictor_32x32_c, vpx_v_predictor_32x32_c, + vpx_h_predictor_32x32_c, vpx_d45_predictor_32x32_c, + vpx_d135_predictor_32x32_c, vpx_d117_predictor_32x32_c, + vpx_d153_predictor_32x32_c, vpx_d207_predictor_32x32_c, + vpx_d63_predictor_32x32_c, vpx_tm_predictor_32x32_c) + +#if HAVE_SSE2 && CONFIG_USE_X86INC +INTRA_PRED_TEST(SSE2, TestIntraPred32, vpx_dc_predictor_32x32_sse2, + vpx_dc_left_predictor_32x32_sse2, + vpx_dc_top_predictor_32x32_sse2, + vpx_dc_128_predictor_32x32_sse2, vpx_v_predictor_32x32_sse2, + vpx_h_predictor_32x32_sse2, NULL, NULL, NULL, NULL, NULL, + NULL, vpx_tm_predictor_32x32_sse2) +#endif // HAVE_SSE2 && CONFIG_USE_X86INC + +#if HAVE_SSSE3 && CONFIG_USE_X86INC +INTRA_PRED_TEST(SSSE3, TestIntraPred32, NULL, NULL, NULL, NULL, NULL, + NULL, vpx_d45_predictor_32x32_ssse3, NULL, NULL, + vpx_d153_predictor_32x32_ssse3, vpx_d207_predictor_32x32_ssse3, + vpx_d63_predictor_32x32_ssse3, NULL) +#endif // HAVE_SSSE3 && CONFIG_USE_X86INC + +#if HAVE_NEON +INTRA_PRED_TEST(NEON, TestIntraPred32, vpx_dc_predictor_32x32_neon, + vpx_dc_left_predictor_32x32_neon, + vpx_dc_top_predictor_32x32_neon, + vpx_dc_128_predictor_32x32_neon, vpx_v_predictor_32x32_neon, + vpx_h_predictor_32x32_neon, NULL, NULL, NULL, NULL, NULL, NULL, + vpx_tm_predictor_32x32_neon) +#endif // HAVE_NEON + +#if HAVE_MSA +INTRA_PRED_TEST(MSA, TestIntraPred32, vpx_dc_predictor_32x32_msa, + vpx_dc_left_predictor_32x32_msa, vpx_dc_top_predictor_32x32_msa, + vpx_dc_128_predictor_32x32_msa, vpx_v_predictor_32x32_msa, + vpx_h_predictor_32x32_msa, NULL, NULL, NULL, NULL, NULL, + NULL, vpx_tm_predictor_32x32_msa) +#endif // HAVE_MSA + +#include "test/test_libvpx.cc"
diff --git a/src/third_party/libvpx/test/test_libvpx.cc b/src/third_party/libvpx/test/test_libvpx.cc new file mode 100644 index 0000000..005ea8d --- /dev/null +++ b/src/third_party/libvpx/test/test_libvpx.cc
@@ -0,0 +1,77 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include <string> + +#include "third_party/googletest/src/include/gtest/gtest.h" + +#include "./vpx_config.h" +#if ARCH_X86 || ARCH_X86_64 +#include "vpx_ports/x86.h" +#endif +extern "C" { +#if CONFIG_VP8 +extern void vp8_rtcd(); +#endif // CONFIG_VP8 +#if CONFIG_VP9 +extern void vp9_rtcd(); +#endif // CONFIG_VP9 +extern void vpx_dsp_rtcd(); +extern void vpx_scale_rtcd(); +} + +#if ARCH_X86 || ARCH_X86_64 +static void append_negative_gtest_filter(const char *str) { + std::string filter = ::testing::FLAGS_gtest_filter; + // Negative patterns begin with one '-' followed by a ':' separated list. + if (filter.find('-') == std::string::npos) filter += '-'; + filter += str; + ::testing::FLAGS_gtest_filter = filter; +} +#endif // ARCH_X86 || ARCH_X86_64 + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + +#if ARCH_X86 || ARCH_X86_64 + const int simd_caps = x86_simd_caps(); + if (!(simd_caps & HAS_MMX)) + append_negative_gtest_filter(":MMX.*:MMX/*"); + if (!(simd_caps & HAS_SSE)) + append_negative_gtest_filter(":SSE.*:SSE/*"); + if (!(simd_caps & HAS_SSE2)) + append_negative_gtest_filter(":SSE2.*:SSE2/*"); + if (!(simd_caps & HAS_SSE3)) + append_negative_gtest_filter(":SSE3.*:SSE3/*"); + if (!(simd_caps & HAS_SSSE3)) + append_negative_gtest_filter(":SSSE3.*:SSSE3/*"); + if (!(simd_caps & HAS_SSE4_1)) + append_negative_gtest_filter(":SSE4_1.*:SSE4_1/*"); + if (!(simd_caps & HAS_AVX)) + append_negative_gtest_filter(":AVX.*:AVX/*"); + if (!(simd_caps & HAS_AVX2)) + append_negative_gtest_filter(":AVX2.*:AVX2/*"); +#endif // ARCH_X86 || ARCH_X86_64 + +#if !CONFIG_SHARED +// Shared library builds don't support whitebox tests +// that exercise internal symbols. + +#if CONFIG_VP8 + vp8_rtcd(); +#endif // CONFIG_VP8 +#if CONFIG_VP9 + vp9_rtcd(); +#endif // CONFIG_VP9 + vpx_dsp_rtcd(); + vpx_scale_rtcd(); +#endif // !CONFIG_SHARED + + return RUN_ALL_TESTS(); +}
diff --git a/src/third_party/libvpx/test/test_vector_test.cc b/src/third_party/libvpx/test/test_vector_test.cc new file mode 100644 index 0000000..f1aa4d7 --- /dev/null +++ b/src/third_party/libvpx/test/test_vector_test.cc
@@ -0,0 +1,192 @@ +/* + * Copyright (c) 2013 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <cstdio> +#include <cstdlib> +#include <set> +#include <string> +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "../tools_common.h" +#include "./vpx_config.h" +#include "test/codec_factory.h" +#include "test/decode_test_driver.h" +#include "test/ivf_video_source.h" +#include "test/md5_helper.h" +#include "test/test_vectors.h" +#include "test/util.h" +#if CONFIG_WEBM_IO +#include "test/webm_video_source.h" +#endif +#include "vpx_mem/vpx_mem.h" + +namespace { + +enum DecodeMode { + kSerialMode, + kFrameParallelMode +}; + +const int kDecodeMode = 0; +const int kThreads = 1; +const int kFileName = 2; + +typedef std::tr1::tuple<int, int, const char*> DecodeParam; + +class TestVectorTest : public ::libvpx_test::DecoderTest, + public ::libvpx_test::CodecTestWithParam<DecodeParam> { + protected: + TestVectorTest() + : DecoderTest(GET_PARAM(0)), + md5_file_(NULL) { +#if CONFIG_VP9_DECODER + resize_clips_.insert( + ::libvpx_test::kVP9TestVectorsResize, + ::libvpx_test::kVP9TestVectorsResize + + ::libvpx_test::kNumVP9TestVectorsResize); +#endif + } + + virtual ~TestVectorTest() { + if (md5_file_) + fclose(md5_file_); + } + + void OpenMD5File(const std::string& md5_file_name_) { + md5_file_ = libvpx_test::OpenTestDataFile(md5_file_name_); + ASSERT_TRUE(md5_file_ != NULL) << "Md5 file open failed. Filename: " + << md5_file_name_; + } + + virtual void DecompressedFrameHook(const vpx_image_t& img, + const unsigned int frame_number) { + ASSERT_TRUE(md5_file_ != NULL); + char expected_md5[33]; + char junk[128]; + + // Read correct md5 checksums. + const int res = fscanf(md5_file_, "%s %s", expected_md5, junk); + ASSERT_NE(res, EOF) << "Read md5 data failed"; + expected_md5[32] = '\0'; + + ::libvpx_test::MD5 md5_res; + md5_res.Add(&img); + const char *actual_md5 = md5_res.Get(); + + // Check md5 match. + ASSERT_STREQ(expected_md5, actual_md5) + << "Md5 checksums don't match: frame number = " << frame_number; + } + +#if CONFIG_VP9_DECODER + std::set<std::string> resize_clips_; +#endif + + private: + FILE *md5_file_; +}; + +// This test runs through the whole set of test vectors, and decodes them. +// The md5 checksums are computed for each frame in the video file. If md5 +// checksums match the correct md5 data, then the test is passed. Otherwise, +// the test failed. +TEST_P(TestVectorTest, MD5Match) { + const DecodeParam input = GET_PARAM(1); + const std::string filename = std::tr1::get<kFileName>(input); + const int threads = std::tr1::get<kThreads>(input); + const int mode = std::tr1::get<kDecodeMode>(input); + libvpx_test::CompressedVideoSource *video = NULL; + vpx_codec_flags_t flags = 0; + vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t(); + char str[256]; + + if (mode == kFrameParallelMode) { + flags |= VPX_CODEC_USE_FRAME_THREADING; +#if CONFIG_VP9_DECODER + // TODO(hkuang): Fix frame parallel decode bug. See issue 1086. + if (resize_clips_.find(filename) != resize_clips_.end()) { + printf("Skipping the test file: %s, due to frame parallel decode bug.\n", + filename.c_str()); + return; + } +#endif + } + + cfg.threads = threads; + + snprintf(str, sizeof(str) / sizeof(str[0]) - 1, + "file: %s mode: %s threads: %d", + filename.c_str(), mode == 0 ? "Serial" : "Parallel", threads); + SCOPED_TRACE(str); + + // Open compressed video file. + if (filename.substr(filename.length() - 3, 3) == "ivf") { + video = new libvpx_test::IVFVideoSource(filename); + } else if (filename.substr(filename.length() - 4, 4) == "webm") { +#if CONFIG_WEBM_IO + video = new libvpx_test::WebMVideoSource(filename); +#else + fprintf(stderr, "WebM IO is disabled, skipping test vector %s\n", + filename.c_str()); + return; +#endif + } + video->Init(); + + // Construct md5 file name. + const std::string md5_filename = filename + ".md5"; + OpenMD5File(md5_filename); + + // Set decode config and flags. + set_cfg(cfg); + set_flags(flags); + + // Decode frame, and check the md5 matching. + ASSERT_NO_FATAL_FAILURE(RunLoop(video, cfg)); + delete video; +} + +// Test VP8 decode in serial mode with single thread. +// NOTE: VP8 only support serial mode. +#if CONFIG_VP8_DECODER +VP8_INSTANTIATE_TEST_CASE( + TestVectorTest, + ::testing::Combine( + ::testing::Values(0), // Serial Mode. + ::testing::Values(1), // Single thread. + ::testing::ValuesIn(libvpx_test::kVP8TestVectors, + libvpx_test::kVP8TestVectors + + libvpx_test::kNumVP8TestVectors))); +#endif // CONFIG_VP8_DECODER + +// Test VP9 decode in serial mode with single thread. +#if CONFIG_VP9_DECODER +VP9_INSTANTIATE_TEST_CASE( + TestVectorTest, + ::testing::Combine( + ::testing::Values(0), // Serial Mode. + ::testing::Values(1), // Single thread. + ::testing::ValuesIn(libvpx_test::kVP9TestVectors, + libvpx_test::kVP9TestVectors + + libvpx_test::kNumVP9TestVectors))); + +// Test VP9 decode in frame parallel mode with different number of threads. +INSTANTIATE_TEST_CASE_P( + VP9MultiThreadedFrameParallel, TestVectorTest, + ::testing::Combine( + ::testing::Values( + static_cast<const libvpx_test::CodecFactory *>(&libvpx_test::kVP9)), + ::testing::Combine( + ::testing::Values(1), // Frame Parallel mode. + ::testing::Range(2, 9), // With 2 ~ 8 threads. + ::testing::ValuesIn(libvpx_test::kVP9TestVectors, + libvpx_test::kVP9TestVectors + + libvpx_test::kNumVP9TestVectors)))); +#endif +} // namespace
diff --git a/src/third_party/libvpx/test/test_vectors.cc b/src/third_party/libvpx/test/test_vectors.cc new file mode 100644 index 0000000..c822479 --- /dev/null +++ b/src/third_party/libvpx/test/test_vectors.cc
@@ -0,0 +1,251 @@ +/* + * Copyright (c) 2013 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "test/test_vectors.h" + +namespace libvpx_test { + +#define NELEMENTS(x) static_cast<int>(sizeof(x) / sizeof(x[0])) + +#if CONFIG_VP8_DECODER +const char *const kVP8TestVectors[] = { + "vp80-00-comprehensive-001.ivf", + "vp80-00-comprehensive-002.ivf", "vp80-00-comprehensive-003.ivf", + "vp80-00-comprehensive-004.ivf", "vp80-00-comprehensive-005.ivf", + "vp80-00-comprehensive-006.ivf", "vp80-00-comprehensive-007.ivf", + "vp80-00-comprehensive-008.ivf", "vp80-00-comprehensive-009.ivf", + "vp80-00-comprehensive-010.ivf", "vp80-00-comprehensive-011.ivf", + "vp80-00-comprehensive-012.ivf", "vp80-00-comprehensive-013.ivf", + "vp80-00-comprehensive-014.ivf", "vp80-00-comprehensive-015.ivf", + "vp80-00-comprehensive-016.ivf", "vp80-00-comprehensive-017.ivf", + "vp80-00-comprehensive-018.ivf", "vp80-01-intra-1400.ivf", + "vp80-01-intra-1411.ivf", "vp80-01-intra-1416.ivf", + "vp80-01-intra-1417.ivf", "vp80-02-inter-1402.ivf", + "vp80-02-inter-1412.ivf", "vp80-02-inter-1418.ivf", + "vp80-02-inter-1424.ivf", "vp80-03-segmentation-01.ivf", + "vp80-03-segmentation-02.ivf", "vp80-03-segmentation-03.ivf", + "vp80-03-segmentation-04.ivf", "vp80-03-segmentation-1401.ivf", + "vp80-03-segmentation-1403.ivf", "vp80-03-segmentation-1407.ivf", + "vp80-03-segmentation-1408.ivf", "vp80-03-segmentation-1409.ivf", + "vp80-03-segmentation-1410.ivf", "vp80-03-segmentation-1413.ivf", + "vp80-03-segmentation-1414.ivf", "vp80-03-segmentation-1415.ivf", + "vp80-03-segmentation-1425.ivf", "vp80-03-segmentation-1426.ivf", + "vp80-03-segmentation-1427.ivf", "vp80-03-segmentation-1432.ivf", + "vp80-03-segmentation-1435.ivf", "vp80-03-segmentation-1436.ivf", + "vp80-03-segmentation-1437.ivf", "vp80-03-segmentation-1441.ivf", + "vp80-03-segmentation-1442.ivf", "vp80-04-partitions-1404.ivf", + "vp80-04-partitions-1405.ivf", "vp80-04-partitions-1406.ivf", + "vp80-05-sharpness-1428.ivf", "vp80-05-sharpness-1429.ivf", + "vp80-05-sharpness-1430.ivf", "vp80-05-sharpness-1431.ivf", + "vp80-05-sharpness-1433.ivf", "vp80-05-sharpness-1434.ivf", + "vp80-05-sharpness-1438.ivf", "vp80-05-sharpness-1439.ivf", + "vp80-05-sharpness-1440.ivf", "vp80-05-sharpness-1443.ivf", + "vp80-06-smallsize.ivf" +}; +const int kNumVP8TestVectors = NELEMENTS(kVP8TestVectors); +#endif // CONFIG_VP8_DECODER +#if CONFIG_VP9_DECODER +#define RESIZE_TEST_VECTORS "vp90-2-21-resize_inter_320x180_5_1-2.webm", \ + "vp90-2-21-resize_inter_320x180_5_3-4.webm", \ + "vp90-2-21-resize_inter_320x180_7_1-2.webm", \ + "vp90-2-21-resize_inter_320x180_7_3-4.webm", \ + "vp90-2-21-resize_inter_320x240_5_1-2.webm", \ + "vp90-2-21-resize_inter_320x240_5_3-4.webm", \ + "vp90-2-21-resize_inter_320x240_7_1-2.webm", \ + "vp90-2-21-resize_inter_320x240_7_3-4.webm", \ + "vp90-2-21-resize_inter_640x360_5_1-2.webm", \ + "vp90-2-21-resize_inter_640x360_5_3-4.webm", \ + "vp90-2-21-resize_inter_640x360_7_1-2.webm", \ + "vp90-2-21-resize_inter_640x360_7_3-4.webm", \ + "vp90-2-21-resize_inter_640x480_5_1-2.webm", \ + "vp90-2-21-resize_inter_640x480_5_3-4.webm", \ + "vp90-2-21-resize_inter_640x480_7_1-2.webm", \ + "vp90-2-21-resize_inter_640x480_7_3-4.webm", \ + "vp90-2-21-resize_inter_1280x720_5_1-2.webm", \ + "vp90-2-21-resize_inter_1280x720_5_3-4.webm", \ + "vp90-2-21-resize_inter_1280x720_7_1-2.webm", \ + "vp90-2-21-resize_inter_1280x720_7_3-4.webm", \ + "vp90-2-21-resize_inter_1920x1080_5_1-2.webm", \ + "vp90-2-21-resize_inter_1920x1080_5_3-4.webm", \ + "vp90-2-21-resize_inter_1920x1080_7_1-2.webm", \ + "vp90-2-21-resize_inter_1920x1080_7_3-4.webm", + +const char *const kVP9TestVectors[] = { + "vp90-2-00-quantizer-00.webm", "vp90-2-00-quantizer-01.webm", + "vp90-2-00-quantizer-02.webm", "vp90-2-00-quantizer-03.webm", + "vp90-2-00-quantizer-04.webm", "vp90-2-00-quantizer-05.webm", + "vp90-2-00-quantizer-06.webm", "vp90-2-00-quantizer-07.webm", + "vp90-2-00-quantizer-08.webm", "vp90-2-00-quantizer-09.webm", + "vp90-2-00-quantizer-10.webm", "vp90-2-00-quantizer-11.webm", + "vp90-2-00-quantizer-12.webm", "vp90-2-00-quantizer-13.webm", + "vp90-2-00-quantizer-14.webm", "vp90-2-00-quantizer-15.webm",