Import Cobalt 6.14838

Change-Id: I49864fe26f7f6fca3777d185823aa31251e8ae57
diff --git a/src/starboard/README.md b/src/starboard/README.md
index 3d35ee3..5e81034 100644
--- a/src/starboard/README.md
+++ b/src/starboard/README.md
@@ -160,7 +160,7 @@
 
 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
+`starboard_platform.gyp` in their own directory for each binary variant, plus
 the header files `configuration_public.h`, `atomic_public.h`, and
 `thread_types_public.h`. `gyp_cobalt` will scan your directories for these
 files, and then calculate a port name based on the directories between
diff --git a/src/starboard/atomic.h b/src/starboard/atomic.h
index e47391f..243c4ea 100644
--- a/src/starboard/atomic.h
+++ b/src/starboard/atomic.h
@@ -12,12 +12,13 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+// Module Overview: Starboard Atomic API
+//
 // Defines a set of atomic integer operations that can be used as lightweight
-// synchronization or as building blocks for heavier synchronization
-// primitives. Their use is very subtle and requires detailed understanding of
-// the behavior of supported architectures, so their direct use is not
-// recommended except when rigorously deemed absolutely necessary for
-// performance reasons.
+// synchronization or as building blocks for heavier synchronization primitives.
+// Their use is very subtle and requires detailed understanding of the behavior
+// of supported architectures, so their direct use is not recommended except
+// when rigorously deemed absolutely necessary for performance reasons.
 
 #ifndef STARBOARD_ATOMIC_H_
 #define STARBOARD_ATOMIC_H_
diff --git a/src/starboard/blitter.h b/src/starboard/blitter.h
index d183475..e807f63 100644
--- a/src/starboard/blitter.h
+++ b/src/starboard/blitter.h
@@ -12,14 +12,20 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Starboard Blitter API.  The Blitter API provides support for issuing simple
-// blit-style draw commands to either an offscreen surface or to a Starboard
-// SbWindow object.  This API is designed to allow implementations make use
-// of GPU hardware acceleration, if it is available.  Draw commands exist for
-// solid-color rectangles and rasterization/blitting of rectangular images onto
+// Module Overview: Starboard Blitter API
+//
+// The Blitter API provides support for issuing simple blit-style draw
+// commands to either an offscreen surface or to a Starboard SbWindow object.
+// Blitter is jargon that means "BLock Transfer," which might be abbreviated
+// as BLT and, hence, the word "blit."
+//
+// This API is designed to allow implementations make use of GPU hardware
+// acceleration, if it is available.  Draw commands exist for solid-color
+// rectangles and rasterization/blitting of rectangular images onto
 // rectangular target patches.
-
-// Threading Concerns:
+//
+// #### Threading Concerns
+//
 // Note that in general the Blitter API is not thread safe, except for all
 // SbBlitterDevice-related functions.  All functions that are not required to
 // internally ensure any thread safety guarantees are prefaced with a comment
@@ -97,12 +103,16 @@
 #define kSbBlitterInvalidSurface ((SbBlitterSurface)NULL)
 
 // SbBlitterContext objects represent a stateful communications channel with
-// a device.  All state changes and draw calls will be made through a specific
-// SbBlitterContext object.  Every draw call made on a SbBlitterContext will
-// be submitted to the device with the SbBlitterContext's current state applied
-// to it.  Draw calls may be submitted to the device as they are made on the
-// SbBlitterContext, however they are not guaranteed to be submitted until
-// the SbBlitterContext object is flushed.
+// a device.  All state changes and draw calls are made through a specific
+// SbBlitterContext object.  Every draw call made on a SbBlitterContext is
+// submitted to the device with the SbBlitterContext's current state applied
+// to it.
+//
+// Draw calls may be submitted to the device as they are made on the
+// SbBlitterContext. However, they are not guaranteed to be submitted until
+// the SbBlitterContext object is flushed. That is, until you call
+// SbBlitterFlushContext, you are not guaranteed that any API calls you have
+// made have been received or acted on by the graphics device.
 typedef struct SbBlitterContextPrivate SbBlitterContextPrivate;
 typedef SbBlitterContextPrivate* SbBlitterContext;
 #define kSbBlitterInvalidContext ((SbBlitterContext)NULL)
@@ -283,66 +293,84 @@
   return context != kSbBlitterInvalidContext;
 }
 
-// Creates and returns a SbBlitterDevice object based on the Blitter API
-// implementation's decision of which device should be default.  The
-// SbBlitterDevice object represents a connection to a device (like a GPU).  On
-// many platforms there is always one single obvious choice for a device to use,
-// and that is the one that this function will return.  For example, if this is
-// called on a platform that has a single GPU, a device representing that GPU
-// should be returned by this call.  On a platform that has no GPU, a device
-// representing a software CPU implementation may be returned.  Only one
-// default device can exist within a process at a time.
-// This function is thread safe.
+// Creates and returns an SbBlitterDevice based on the Blitter API
+// implementation's decision of which device should be the default. The
+// returned SbBlitterDevice represents a connection to a device (like a GPU).
+//
+// On many platforms there is always one single obvious choice for a device
+// to use, and that is the one that this function will return. For example,
+// if this is called on a platform that has a single GPU, this call should
+// return an object that represents that GPU. On a platform that has no GPU,
+// an object representing a software CPU implementation may be returned.
+//
+// Only one default device can exist within a process at a time.
+// This function is thread-safe.
 // Returns kSbBlitterInvalidDevice on failure.
 SB_EXPORT SbBlitterDevice SbBlitterCreateDefaultDevice();
 
 // Destroys |device|, cleaning up all resources associated with it.
-// Returns whether the destruction succeeded.
-// This function is thread safe, though of course it should not be called if
-// |device| is still being accessed elsewhere.
+// This function is thread-safe, but it should not be called if |device| is
+// still being accessed elsewhere.
+//
+// The return value indicates whether the destruction succeeded.
+//
+// |device|: The SbBlitterDevice object to be destroyed.
 SB_EXPORT bool SbBlitterDestroyDevice(SbBlitterDevice device);
 
-// Creates and returns a SbBlitterSwapChain object that can be used to send
-// graphics to the display.  By calling this function, |device| will be linked
-// to |window|'s output and drawing to the returned swap chain will result in
-// |device| being used to render to |window|.  kSbBlitterInvalidSwapChain is
-// returned on failure.
+// Creates and returns an SbBlitterSwapChain that can then be used to send
+// graphics to the display. This function links |device| to |window|'s output,
+// and drawing to the returned swap chain will result in |device| being used
+// to render to |window|.
+//
 // This function must be called from the thread that called SbWindowCreate()
 // to create |window|.
+//
+// Returns kSbBlitterInvalidSwapChain on failure.
 SB_EXPORT SbBlitterSwapChain
 SbBlitterCreateSwapChainFromWindow(SbBlitterDevice device, SbWindow window);
 
 // Destroys |swap_chain|, cleaning up all resources associated with it.
-// This function must be called on the same thread that called
-// SbBlitterCreateSwapChainFromWindow().
-// This function is not thread safe.
-// Returns the destruction succeeded.
+// This function is not thread-safe and must be called on the same thread
+// that called SbBlitterCreateSwapChainFromWindow().
+//
+// The return value indicates whether the destruction succeeded.
+//
+// |swap_chain|: The SbBlitterSwapChain to be destroyed.
 SB_EXPORT bool SbBlitterDestroySwapChain(SbBlitterSwapChain swap_chain);
 
 // Returns the |SbBlitterRenderTarget| object that is owned by |swap_chain|.
 // The returned object can be used to provide a target to blitter draw calls
-// wishing to draw directly to the display buffer.
-// This function is not thread safe.
-// kSbBlitterInvalidRenderTarget is returned on failure.
+// that draw directly to the display buffer. This function is not thread-safe.
+//
+// Returns kSbBlitterInvalidRenderTarget on failure.
+//
+// |swap_chain|: The SbBlitterSwapChain for which the target object is being
+// retrieved.
 SB_EXPORT SbBlitterRenderTarget
 SbBlitterGetRenderTargetFromSwapChain(SbBlitterSwapChain swap_chain);
 
-// Returns whether |device| supports calls to SbBlitterCreatePixelData()
-// with |pixel_format|.
-// This function is thread safe.
+// Indicates whether |device| supports calls to SbBlitterCreatePixelData
+// with the specified |pixel_format|. This function is thread-safe.
+//
+// |device|: The device for which compatibility is being checked.
+// |pixel_format|: The SbBlitterPixelDataFormat for which compatibility is
+// being checked.
 SB_EXPORT bool SbBlitterIsPixelFormatSupportedByPixelData(
     SbBlitterDevice device,
     SbBlitterPixelDataFormat pixel_format);
 
-// Allocates a SbBlitterPixelData object through |device| with |width|, |height|
-// and |pixel_format|.  |pixel_format| must be supported by |device| (see
-// SbBlitterIsPixelFormatSupportedByPixelData()).  Calling this function will
-// result in the allocation of CPU-accessible (though perhaps
-// blitter-device-resident) memory to store pixel data of the requested
-// size/format. A SbBlitterPixelData object should either eventually be passed
-// into a call to SbBlitterCreateSurfaceFromPixelData(), or passed into a call
-// to SbBlitterDestroyPixelData().
-// This function is thread safe.
+// Allocates an SbBlitterPixelData object through |device| with |width|,
+// |height| and |pixel_format|. |pixel_format| must be supported by |device|
+// (see SbBlitterIsPixelFormatSupportedByPixelData()). This function is
+// thread-safe.
+//
+// Calling this function results in the allocation of CPU-accessible
+// (though perhaps blitter-device-resident) memory to store pixel data
+// of the requested size/format. An SbBlitterPixelData object should
+// eventually be passed either into a call to
+// SbBlitterCreateSurfaceFromPixelData() or into a call to
+// SbBlitterDestroyPixelData().
+//
 // Returns kSbBlitterInvalidPixelData upon failure.
 SB_EXPORT SbBlitterPixelData
 SbBlitterCreatePixelData(SbBlitterDevice device,
@@ -350,57 +378,74 @@
                          int height,
                          SbBlitterPixelDataFormat pixel_format);
 
-// Destroys the |pixel_data| object.  Note that
-// if SbBlitterCreateSurfaceFromPixelData() has been called on |pixel_data|
-// before, this function does not need to be and should not be called.
-// This function is thread safe.
-// Returns whether the destruction succeeded.
+// Destroys |pixel_data|. Note that this function does not need to be called
+// and should not be called if SbBlitterCreateSurfaceFromPixelData() has been
+// called on |pixel_data| before. This function is thread-safe.
+//
+// The return value indicates whether the destruction succeeded.
+//
+// |pixel_data|: The object to be destroyed.
 SB_EXPORT bool SbBlitterDestroyPixelData(SbBlitterPixelData pixel_data);
 
-// Getter method to return the pitch (in bytes) for |pixel_data|.  This
-// indicates the number of bytes per row of pixel data in the image.  -1 is
-// returned in case of an error.
-// This function is not thread safe.
+// Retrieves the pitch (in bytes) for |pixel_data|. This indicates the number of
+// bytes per row of pixel data in the image. This function is not thread-safe.
+//
+// Returns |-1| in the event of an error.
+//
+// |pixel_data|: The object for which you are retrieving the pitch.
 SB_EXPORT int SbBlitterGetPixelDataPitchInBytes(SbBlitterPixelData pixel_data);
 
-// Getter method to return a CPU-accessible pointer to the pixel data
-// represented by |pixel_data|.  This pixel data can be modified by the CPU
-// in order to initialize it on the CPU before calling
-// SbBlitterCreateSurfaceFromPixelData().  Note that the pointe returned here
-// is valid as long as |pixel_data| is valid, i.e. until either
+// Retrieves a CPU-accessible pointer to the pixel data represented by
+// |pixel_data|. This pixel data can be modified by the CPU to initialize it
+// on the CPU before calling SbBlitterCreateSurfaceFromPixelData().
+//
+// Note that the pointer returned here is valid as long as |pixel_data| is
+// valid, which means it is valid until either
 // SbBlitterCreateSurfaceFromPixelData() or SbBlitterDestroyPixelData() is
 // called.
-// This function is not thread safe.
-// If there is an error, NULL is returned.
+//
+// This function is not thread-safe.
+//
+// Returns |NULL| in the event of an error.
 SB_EXPORT void* SbBlitterGetPixelDataPointer(SbBlitterPixelData pixel_data);
 
-// Creates a SbBlitterSurface object on |device| (which must match the device
-// used to create the input SbBlitterPixelData object, |pixel_format|).
-// This function will destroy the input |pixel_data| object and so
-// |pixel_data| should not be accessed again after this function is called.
-// The returned surface cannot be used as a render target (e.g. calling
+// Creates an SbBlitterSurface object on |device|. Note that |device| must
+// match the device that was used to create the SbBlitterPixelData object
+// provided via the |pixel_data| parameter.
+//
+// This function also destroys the input |pixel_data| object. As a result,
+// |pixel_data| should not be accessed again after a call to this function.
+//
+// The returned object cannot be used as a render target (e.g. calling
 // SbBlitterGetRenderTargetFromSurface() on it will return
 // SbBlitterInvalidRenderTarget).
-// This function is thread safe with respect to |device|, however
-// |pixel_data| should not be modified on another thread while this function
-// is called.
-// kSbBlitterInvalidSurface is returned if there was an error.
+//
+// This function is thread-safe with respect to |device|, but |pixel_data|
+// should not be modified on another thread while this function is called.
+//
+// Returns kSbBlitterInvalidSurface in the event of an error.
 SB_EXPORT SbBlitterSurface
 SbBlitterCreateSurfaceFromPixelData(SbBlitterDevice device,
                                     SbBlitterPixelData pixel_data);
 
-// Returns whether the |device| supports calls to
-// SbBlitterCreateRenderTargetSurface() with |pixel_format|.
-// This function is thread safe.
+// Indicates whether the |device| supports calls to
+// SbBlitterCreateRenderTargetSurface() with |surface_format|.
+//
+// This function is thread-safe.
+//
+// |device|: The device being checked for compatibility.
+// |surface_format|: The surface format being checked for compatibility.
 SB_EXPORT bool SbBlitterIsSurfaceFormatSupportedByRenderTargetSurface(
     SbBlitterDevice device,
     SbBlitterSurfaceFormat surface_format);
 
 // Creates a new surface with undefined pixel data on |device| with the
-// specified |width|, |height| and |pixel_format|.  One can set the pixel data
+// specified |width|, |height| and |surface_format|. One can set the pixel data
 // on the resulting surface by getting its associated SbBlitterRenderTarget
-// object by calling SbBlitterGetRenderTargetFromSurface().
-// This function is thread safe.
+// object and then calling SbBlitterGetRenderTargetFromSurface().
+//
+// This function is thread-safe.
+//
 // Returns kSbBlitterInvalidSurface upon failure.
 SB_EXPORT SbBlitterSurface
 SbBlitterCreateRenderTargetSurface(SbBlitterDevice device,
@@ -408,195 +453,278 @@
                                    int height,
                                    SbBlitterSurfaceFormat surface_format);
 
-// Destroys |surface|, cleaning up all resources associated with it.
+// Destroys the |surface| object, cleaning up all resources associated with it.
 // This function is not thread safe.
-// Returns whether the destruction succeeded.
+//
+// The return value indicates whether the destruction succeeded.
+//
+// |surface|: The object to be destroyed.
 SB_EXPORT bool SbBlitterDestroySurface(SbBlitterSurface surface);
 
 // Returns the SbBlitterRenderTarget object owned by |surface|.  The returned
 // object can be used as a target for draw calls.
-// This function is not thread safe.
-// Returns kSbBlitterInvalidRenderTarget if |surface| is not able to provide a
-// render target, or on any other error.
+//
+// This function returns kSbBlitterInvalidRenderTarget if |surface| is not
+// able to provide a render target or on any other error.
+//
+// This function is not thread-safe.
 SB_EXPORT SbBlitterRenderTarget
 SbBlitterGetRenderTargetFromSurface(SbBlitterSurface surface);
 
-// Returns a SbBlitterSurfaceInfo structure describing immutable parameters of
-// |surface|, such as width, height and pixel format.  The results will be
-// set on the output parameter |surface_info| which cannot be NULL.
-// This function is not thread safe.
-// Returns whether the information was retrieved successfully.
+// Retrieves an SbBlitterSurfaceInfo structure, which describes immutable
+// parameters of the |surface|, such as its width, height and pixel format.
+// The results are set on the output parameter |surface_info|, which cannot
+// be NULL.
+//
+// The return value indicates whether the information was retrieved
+// successfully.
+//
+// This function is not thread-safe.
 SB_EXPORT bool SbBlitterGetSurfaceInfo(SbBlitterSurface surface,
                                        SbBlitterSurfaceInfo* surface_info);
 
-// Returns whether the combination of parameters (|surface|, |pixel_format|) are
-// valid for calls to SbBlitterDownloadSurfacePixels().
-// This function is not thread safe.
+// Indicates whether the combination of parameter values is valid for calls
+// to SbBlitterDownloadSurfacePixels().
+//
+// This function is not thread-safe.
+//
+// |surface|: The surface being checked.
+// |pixel_format|: The pixel format that would be used on the surface.
 SB_EXPORT bool SbBlitterIsPixelFormatSupportedByDownloadSurfacePixels(
     SbBlitterSurface surface,
     SbBlitterPixelDataFormat pixel_format);
 
 // Downloads |surface| pixel data into CPU memory pointed to by
 // |out_pixel_data|, formatted according to the requested |pixel_format| and
-// the requested |pitch_in_bytes|.  Thus, |out_pixel_data| must point to a
-// region of memory with a size of surface_height * |pitch_in_bytes| *
-// SbBlitterBytesPerPixelForFormat(pixel_format) bytes.  The function
-// SbBlitterIsPixelFormatSupportedByDownloadSurfacePixels() can be called first
-// to check that your requested |pixel_format| is valid for |surface|.  When
-// this function is called, it will first wait for all previously flushed
+// the requested |pitch_in_bytes|. Before calling this function, you can call
+// SbBlitterIsPixelFormatSupportedByDownloadSurfacePixels() to confirm that
+// |pixel_format| is, in fact, valid for |surface|.
+//
+// When this function is called, it first waits for all previously flushed
 // graphics commands to be executed by the device before downloading the data.
 // Since this function waits for the pipeline to empty, it should be used
-// sparingly, such as within in debug or test environments.  The returned
-// alpha format will be premultiplied.
-// This function is not thread safe.
-// Returns whether the pixel data was downloaded successfully or not.
+// sparingly, such as within in debug or test environments.
+//
+// The return value indicates whether the pixel data was downloaded
+// successfully.
+//
+// The returned alpha format is premultiplied.
+//
+// This function is not thread-safe.
+//
+// |out_pixel_data|: A pointer to a region of memory with a size of
+//                   (surface_height * |pitch_in_bytes| *
+//                   SbBlitterBytesPerPixelForFormat(pixel_format) bytes.
 SB_EXPORT bool SbBlitterDownloadSurfacePixels(
     SbBlitterSurface surface,
     SbBlitterPixelDataFormat pixel_format,
     int pitch_in_bytes,
     void* out_pixel_data);
 
-// Flips |swap_chain|, making the buffer that was previously accessible to
-// draw commands via SbBlitterGetRenderTargetFromSwapChain() now visible on the
-// display, while another buffer in an initially undefined state is setup as the
-// draw command target.  Note that you do not need to call
+// Flips the |swap_chain| by making the buffer previously accessible to
+// draw commands via SbBlitterGetRenderTargetFromSwapChain() visible on the
+// display, while another buffer in an initially undefined state is set up
+// as the new draw command target. Note that you do not need to call
 // SbBlitterGetRenderTargetFromSwapChain() again after flipping, the swap
-// chain's render target will always refer to its current back buffer.  This
-// function will stall the calling thread until the next vertical refresh.
-// Note that to ensure consistency with the Starboard Player API when rendering
-// punch-out video, calls to SbPlayerSetBounds() will not take effect until
-// this method is called.
-// This function is not thread safe.
-// Returns whether the flip succeeded.
+// chain's render target always refers to its current back buffer.
+//
+// This function stalls the calling thread until the next vertical refresh.
+// In addition, to ensure consistency with the Starboard Player API when
+// rendering punch-out video, calls to SbPlayerSetBounds() do not take effect
+// until this method is called.
+//
+// The return value indicates whether the flip succeeded.
+//
+// This function is not thread-safe.
+//
+// |swap_chain|: The SbBlitterSwapChain to be flipped.
 SB_EXPORT bool SbBlitterFlipSwapChain(SbBlitterSwapChain swap_chain);
 
-// Returns the maximum number of contexts that |device| can support in parallel.
-// In many cases, devices support only a single context.  If
-// SbBlitterCreateContext() has been used to create the maximum number of
-// contexts, all subsequent calls to SbBlitterCreateContext() will fail.
-// This function is thread safe.
-// This function returns -1 upon failure.
+// Returns the maximum number of contexts that |device| can support in
+// parallel. Note that devices often support only a single context.
+//
+// This function is thread-safe.
+//
+// This function returns |-1| upon failure.
+//
+// |device|: The SbBlitterDevice for which the maximum number of contexts is
+// returned.
 SB_EXPORT int SbBlitterGetMaxContexts(SbBlitterDevice device);
 
-// Creates a SbBlitterContext object on the specified |device|.  The returned
-// context can be used to setup draw state and issue draw calls.  Note that
-// there is a limit on the number of contexts that can exist at the same time
-// (in many cases this is 1), and this can be queried by calling
-// SbBlitterGetMaxContexts().  SbBlitterContext objects keep track of draw
-// state between a series of draw calls.  Please refer to the documentation
-// around the definition of SbBlitterContext for more information about
-// contexts.
-// This function is thread safe.
-// This function returns kSbBlitterInvalidContext upon failure.
+// Creates an SbBlitterContext object on |device|. The returned context can be
+// used to set up draw state and issue draw calls.
+//
+// Note that there is a limit on the number of contexts that can exist
+// simultaneously, which can be queried by calling SbBlitterGetMaxContexts().
+// (The limit is often |1|.)
+//
+// SbBlitterContext objects keep track of draw state between a series of draw
+// calls. Please refer to the SbBlitterContext() definition for more
+// information about contexts.
+//
+// This function is thread-safe.
+//
+// This function returns kSbBlitterInvalidContext upon failure. Note that the
+// function fails if it has already been used to create the maximum number
+// of contexts.
+//
+// |device|: The SbBlitterDevice for which the SbBlitterContext object is
+// created.
 SB_EXPORT SbBlitterContext SbBlitterCreateContext(SbBlitterDevice device);
 
-// Destroys the specified |context| created by |device|, freeing all its
-// resources.
-// This function is not thread safe.
-// Returns whether the destruction succeeded.
+// Destroys the specified |context|, freeing all its resources. This function
+// is not thread-safe.
+//
+// The return value indicates whether the destruction succeeded.
+//
+// |context|: The object to be destroyed.
 SB_EXPORT bool SbBlitterDestroyContext(SbBlitterContext context);
 
-// Flushes all draw calls previously issued to |context|.  After this call,
-// all subsequent draw calls (on any context) are guaranteed to be processed
-// by the device after all previous draw calls issued on this |context|.
-// In many cases you will want to call this before calling
-// SbBlitterFlipSwapChain(), to ensure that all draw calls are submitted before
-// the flip occurs.
-// This function is not thread safe.
-// Returns whether the flush succeeded.
+// Flushes all draw calls previously issued to |context|. Calling this function
+// guarantees that the device processes all draw calls issued to this point on
+// this |context| before processing any subsequent draw calls on any context.
+//
+// Before calling SbBlitterFlipSwapChain(), it is often prudent to call this
+// function to ensure that all draw calls are submitted before the flip occurs.
+//
+// This function is not thread-safe.
+//
+// The return value indicates whether the flush succeeded.
+//
+// |context|: The context for which draw calls are being flushed.
 SB_EXPORT bool SbBlitterFlushContext(SbBlitterContext context);
 
 // Sets up |render_target| as the render target that all subsequent draw calls
-// made on |context| will draw to.
-// This function is not thread safe.
-// Returns whether the render target was successfully set.
+// made on |context| will use.
+//
+// This function is not thread-safe.
+//
+// The return value indicates whether the render target was set successfully.
+//
+// |context|: The object for which the render target is being set.
+// |render_target|: The target that the |context| should use for draw calls.
 SB_EXPORT bool SbBlitterSetRenderTarget(SbBlitterContext context,
                                         SbBlitterRenderTarget render_target);
 
-// Sets blending state on the specified |context|.  If |blending| is true, the
-// source alpha of subsequent draw calls will be used to blend with the
-// destination color.  In particular, Fc = Sc * Sa + Dc * (1 - Sa), where
-// Fc is the final color, Sc is the source color, Sa is the source alpha, and
-// Dc is the destination color.  If |blending| is false, the source color and
-// alpha will overwrite the destination color and alpha.  By default blending
+// Sets the blending state for the specified |context|. By default, blending
 // is disabled on a SbBlitterContext.
-// This function is not thread safe.
-// Returns whether the blending state was succcessfully set.
+//
+// This function is not thread-safe.
+//
+// The return value indicates whether the blending state was set successfully.
+//
+// |context|: The context for which the blending state is being set.
+// |blending|: The blending state for the |context|.
+// If |blending| is |true|, the source alpha of subsequent draw calls
+// is used to blend with the destination color. In particular,
+// (|Fc = Sc * Sa + Dc * (1 - Sa)|), where:
+// - |Fc| is the final color.
+// - |Sc| is the source color.
+// - |Sa| is the source alpha.
+// - |Dc| is the destination color.
+// If |blending| is |false|, the source color and source alpha overwrite
+// the destination color and alpha.
 SB_EXPORT bool SbBlitterSetBlending(SbBlitterContext context, bool blending);
 
 // Sets the context's current color.  The current color's default value is
-// SbBlitterColorFromRGBA(255, 255, 255 255).  The current color affects the
-// fill rectangle's color in calls to SbBlitterFillRect(), and if
-// SbBlitterSetModulateBlitsWithColor() has been called to enable blit color
-// modulation, the source blit surface pixel color will also be modulated by
-// the color before being output.  The color is specified in unpremultiplied
-// alpha format.
-// This function is not thread safe.
-// Returns whether the color was successfully set.
+// |SbBlitterColorFromRGBA(255, 255, 255 255)|.
+//
+// The current color affects the fill rectangle's color in calls to
+// SbBlitterFillRect(). If SbBlitterSetModulateBlitsWithColor() has been called
+// to enable blit color modulation, the source blit surface pixel color is also
+// modulated by the color before being output.
+//
+// This function is not thread-safe.
+//
+// The return value indicates whether the color was set successfully.
+//
+// |context|: The context for which the color is being set.
+// |color|: The context's new color, specified in unpremultiplied alpha format.
 SB_EXPORT bool SbBlitterSetColor(SbBlitterContext context,
                                  SbBlitterColor color);
 
 // Sets whether or not blit calls should have their source pixels modulated by
-// the current color (set via a call to SbBlitterSetColor()) before being
-// output.  This can be used to apply opacity to blit calls, as well as for
-// coloring alpha-only surfaces, and other effects.
-// This function is not thread safe.
-// Returns whether the state was successfully set.
+// the current color, which is set using SbBlitterSetColor(), before being
+// output. This function can apply opacity to blit calls, color alpha-only
+// surfaces, and apply other effects.
+//
+// This function is not thread-safe.
+//
+// The return value indicates whether the state was set successfully.
+//
+// |modulate_blits_with_color|: Indicates whether to modulate source pixels
+// in blit calls.
 SB_EXPORT bool SbBlitterSetModulateBlitsWithColor(
     SbBlitterContext context,
     bool modulate_blits_with_color);
 
-// Sets the scissor rectangle.  The scissor rectangle dictates a rectangle of
-// visibility that affects all draw calls.  Only pixels within the scissor
-// rectangle will be rendered, all drawing outside of the scissor rectangle will
-// be clipped.  When SbBlitterSetRenderTarget() is called, the scissor rectangle
-// is automatically set to the extents of the specified render target.  If a
+// Sets the scissor rectangle, which dictates a visibility area that affects
+// all draw calls. Only pixels within the scissor rectangle are rendered, and
+// all drawing outside of that area is clipped.
+//
+// When SbBlitterSetRenderTarget() is called, that function automatically sets
+// the scissor rectangle to the size of the specified render target. If a
 // scissor rectangle is specified outside of the extents of the current render
-// target bounds, it will be intersected with the render target boudns.  It is
-// an error to call this function before a render target has been specified for
-// the context.
-// This function is not thread safe.
-// Returns whether the scissor was successfully set.
+// target bounds, it will be intersected with the render target bounds.
+//
+// This function is not thread-safe.
+//
+// Returns whether the scissor was successfully set. It returns an error if
+// it is called before a render target has been specified for the context.
 SB_EXPORT bool SbBlitterSetScissor(SbBlitterContext context,
                                    SbBlitterRect rect);
 
-// Issues a draw call on |context| that fills a rectangle |rect|.  The color
-// of the rectangle is specified by the last call to SbBlitterSetColor().
-// This function is not thread safe.
-// Returns whether the draw call succeeded.
+// Issues a draw call on |context| that fills the specified rectangle |rect|.
+// The rectangle's color is determined by the last call to SbBlitterSetColor().
+//
+// This function is not thread-safe.
+//
+// The return value indicates whether the draw call succeeded.
+//
+// |context|: The context on which the draw call will operate.
+// |rect|: The rectangle to be filled.
 SB_EXPORT bool SbBlitterFillRect(SbBlitterContext context, SbBlitterRect rect);
 
-// Issues a draw call on |context| that blits an area of |source_surface|
-// specified by a |src_rect| to |context|'s current render target at |dst_rect|.
-// The source rectangle must lie within the dimensions of |source_surface|.  The
-// |source_surface|'s alpha will be modulated by |opacity| before being drawn.
-// For |opacity|, a value of 0 implies complete invisibility and a value of
-// 255 implies complete opaqueness.
-// This function is not thread safe.
-// Returns whether the draw call succeeded.
+// Issues a draw call on |context| that blits the area of |source_surface|
+// specified by |src_rect| to |context|'s current render target at |dst_rect|.
+// The source rectangle must lie within the dimensions of |source_surface|.
+// Note that the |source_surface|'s alpha is modulated by |opacity| before
+// being drawn. For |opacity|, a value of 0 implies complete invisibility,
+// and a value of 255 implies complete opacity.
+//
+// This function is not thread-safe.
+//
+// The return value indicates whether the draw call succeeded.
+//
+// |src_rect|: The area to be block transferred (blitted).
 SB_EXPORT bool SbBlitterBlitRectToRect(SbBlitterContext context,
                                        SbBlitterSurface source_surface,
                                        SbBlitterRect src_rect,
                                        SbBlitterRect dst_rect);
 
-// This function does the exact same as SbBlitterBlitRectToRect(), except
-// it permits values of |src_rect| outside of the dimensions of
-// |source_surface| and in these regions the pixel data from |source_surface|
-// will be wrapped.  Negative values for |src_rect.x| and |src_rect.y| are
-// allowed.  The output will all be stretched to fit inside of |dst_rect|.
-// This function is not thread safe.
-// Returns whether the draw call succeeded.
+// This function functions identically to SbBlitterBlitRectToRect(), except
+// it permits values of |src_rect| outside the dimensions of |source_surface|.
+// In those regions, the pixel data from |source_surface| will be wrapped.
+// Negative values for |src_rect.x| and |src_rect.y| are allowed.
+//
+// The output is all stretched to fit inside of |dst_rect|.
+//
+// This function is not thread-safe.
+//
+// The return value indicates whether the draw call succeeded.
 SB_EXPORT bool SbBlitterBlitRectToRectTiled(SbBlitterContext context,
                                             SbBlitterSurface source_surface,
                                             SbBlitterRect src_rect,
                                             SbBlitterRect dst_rect);
 
 // This function achieves the same effect as calling SbBlitterBlitRectToRect()
-// |num_rects| time with each of the |num_rects| values of |src_rects| and
-// |dst_rects|.  Using this function allows for greater efficiency than calling
-// SbBlitterBlitRectToRect() in a loop.
-// This function is not thread safe.
-// Returns whether the draw call succeeded.
+// |num_rects| times with each of the |num_rects| values of |src_rects| and
+// |dst_rects|. This function allows for greater efficiency than looped calls
+// to SbBlitterBlitRectToRect().
+//
+// This function is not thread-safe.
+//
+// The return value indicates whether the draw call succeeded.
 SB_EXPORT bool SbBlitterBlitRectsToRects(SbBlitterContext context,
                                          SbBlitterSurface source_surface,
                                          const SbBlitterRect* src_rects,
diff --git a/src/starboard/byte_swap.h b/src/starboard/byte_swap.h
index 7c2e968..9fbd1fa 100644
--- a/src/starboard/byte_swap.h
+++ b/src/starboard/byte_swap.h
@@ -12,8 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Functions for swapping byte order, used to deal with endianness when
-// performing I/O
+// Module Overview: Starboard Byte Swap module
+//
+// Specifies functions for swapping byte order. These functions are used to
+// deal with endianness when performing I/O.
 
 #ifndef STARBOARD_BYTE_SWAP_H_
 #define STARBOARD_BYTE_SWAP_H_
@@ -53,21 +55,27 @@
 // and then act on that determination somehow.
 
 // Unconditionally swaps the byte order in signed 16-bit |value|.
+// |value|: The value for which the byte order will be swapped.
 SB_EXPORT int16_t SbByteSwapS16(int16_t value);
 
 // Unconditionally swaps the byte order in unsigned 16-bit |value|.
+// |value|: The value for which the byte order will be swapped.
 SB_EXPORT uint16_t SbByteSwapU16(uint16_t value);
 
 // Unconditionally swaps the byte order in signed 32-bit |value|.
+// |value|: The value for which the byte order will be swapped.
 SB_EXPORT int32_t SbByteSwapS32(int32_t value);
 
 // Unconditionally swaps the byte order in unsigned 32-bit |value|.
+// |value|: The value for which the byte order will be swapped.
 SB_EXPORT uint32_t SbByteSwapU32(uint32_t value);
 
 // Unconditionally swaps the byte order in signed 64-bit |value|.
+// |value|: The value for which the byte order will be swapped.
 SB_EXPORT int64_t SbByteSwapS64(int64_t value);
 
 // Unconditionally swaps the byte order in unsigned 64-bit |value|.
+// |value|: The value for which the byte order will be swapped.
 SB_EXPORT uint64_t SbByteSwapU64(uint64_t value);
 
 #ifdef __cplusplus
diff --git a/src/starboard/character.h b/src/starboard/character.h
index f4d064f..f7758c7 100644
--- a/src/starboard/character.h
+++ b/src/starboard/character.h
@@ -12,7 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Functions for interacting with characters.
+// Module Overview: Starboard Character module
+//
+// Provides functions for interacting with characters.
 
 #ifndef STARBOARD_CHARACTER_H_
 #define STARBOARD_CHARACTER_H_
@@ -26,36 +28,50 @@
 #endif
 
 // Converts the given 8-bit character (as an int) to uppercase in the current
-// locale, returning the result, also an 8-bit character. If there is no
-// uppercase version of the character, or the character is already uppercase, it
-// will just return the character as-is.
-int SbCharacterToUpper(int c);
+// locale and returns an 8-bit character. If there is no uppercase version of
+// the character, or the character is already uppercase, the function just
+// returns the character as-is.
+//
+// |c|: The character to be converted.
+SB_EXPORT int SbCharacterToUpper(int c);
 
 // Converts the given 8-bit character (as an int) to lowercase in the current
-// locale, returning the result, also an 8-bit character. If there is no
-// lowercase version of the character, or the character is already lowercase, it
-// will just return the character as-is.
-int SbCharacterToLower(int c);
+// locale and returns an 8-bit character. If there is no lowercase version of
+// the character, or the character is already lowercase, the function just
+// returns the character as-is.
+//
+// |c|: The character to be converted.
+SB_EXPORT int SbCharacterToLower(int c);
 
-// Returns whether the given 8-bit character |c| (as an int) is a space in the
-// current locale.
-bool SbCharacterIsSpace(int c);
-
-// Returns whether the given 8-bit character |c| (as an int) is uppercase in the
-// current locale.
-bool SbCharacterIsUpper(int c);
-
-// Returns whether the given 8-bit character |c| (as an int) is a decimal digit
-// in the current locale.
-bool SbCharacterIsDigit(int c);
-
-// Returns whether the given 8-bit character |c| (as an int) is a hexidecimal
-// digit in the current locale.
-bool SbCharacterIsHexDigit(int c);
-
-// Returns whether the given 8-bit character |c| (as an int) is alphanumeric in
+// Indicates whether the given 8-bit character |c| (as an int) is a space in
 // the current locale.
-bool SbCharacterIsAlphanumeric(int c);
+//
+// |c|: The character to be evaluated.
+SB_EXPORT bool SbCharacterIsSpace(int c);
+
+// Indicates whether the given 8-bit character |c| (as an int) is uppercase
+// in the current locale.
+//
+// |c|: The character to be evaluated.
+SB_EXPORT bool SbCharacterIsUpper(int c);
+
+// Indicates whether the given 8-bit character |c| (as an int) is a
+// decimal digit in the current locale.
+//
+// |c|: The character to be evaluated.
+SB_EXPORT bool SbCharacterIsDigit(int c);
+
+// Indicates whether the given 8-bit character |c| (as an int) is a hexadecimal
+// in the current locale.
+//
+// |c|: The character to be evaluated.
+SB_EXPORT bool SbCharacterIsHexDigit(int c);
+
+// Indicates whether the given 8-bit character |c| (as an int) is alphanumeric
+// in the current locale.
+//
+// |c|: The character to be evaluated.
+SB_EXPORT bool SbCharacterIsAlphanumeric(int c);
 
 #ifdef __cplusplus
 }  // extern "C"
diff --git a/src/starboard/client_porting/eztime/eztime.h b/src/starboard/client_porting/eztime/eztime.h
index 8402006..8221c2f 100644
--- a/src/starboard/client_porting/eztime/eztime.h
+++ b/src/starboard/client_porting/eztime/eztime.h
@@ -15,7 +15,9 @@
 #ifndef STARBOARD_CLIENT_PORTING_EZTIME_EZTIME_H_
 #define STARBOARD_CLIENT_PORTING_EZTIME_EZTIME_H_
 
+#include "starboard/log.h"
 #include "starboard/time.h"
+#include "starboard/types.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -119,7 +121,12 @@
 // Converts SbTime to EzTimeValue.
 static SB_C_FORCE_INLINE EzTimeValue EzTimeValueFromSbTime(SbTime in_time) {
   EzTimeT sec = EzTimeTFromSbTime(in_time);
-  EzTimeValue value = {sec, in_time - EzTimeTToSbTime(sec)};
+  SbTime diff = in_time - EzTimeTToSbTime(sec);
+  SB_DCHECK(diff >= INT_MIN);
+  SB_DCHECK(diff <= INT_MAX);
+  EzTimeValue value = {sec, (int)diff};  // Some compilers do not support
+                                         // returning the initializer list
+                                         // directly.
   return value;
 }
 
diff --git a/src/starboard/common/common.gyp b/src/starboard/common/common.gyp
index e354d5e..c6a509b 100644
--- a/src/starboard/common/common.gyp
+++ b/src/starboard/common/common.gyp
@@ -28,8 +28,12 @@
         'decode_target_provider.cc',
         'memory.cc',
         'move.h',
+        'ref_counted.cc',
+        'ref_counted.h',
         'reset_and_return.h',
         'scoped_ptr.h',
+        'thread_collision_warner.cc',
+        'thread_collision_warner.h',
       ],
       'defines': [
         # This must be defined when building Starboard, and must not when
diff --git a/src/starboard/common/memory.cc b/src/starboard/common/memory.cc
index 6067214..4ed3362 100644
--- a/src/starboard/common/memory.cc
+++ b/src/starboard/common/memory.cc
@@ -12,32 +12,87 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include "starboard/atomic.h"
+#include "starboard/log.h"
 #include "starboard/memory.h"
+#include "starboard/memory_reporter.h"
+#include "starboard/shared/starboard/memory_reporter_internal.h"
 
+namespace {
 inline void* SbMemoryAllocateImpl(size_t size);
 inline void* SbMemoryAllocateAlignedImpl(size_t alignment, size_t size);
 inline void* SbMemoryReallocateImpl(void* memory, size_t size);
+inline void SbReportAllocation(const void* memory, size_t size);
+inline void SbReportDeallocation(const void* memory);
+
+SbMemoryReporter* s_memory_reporter = NULL;
+
+bool LeakTraceEnabled();               // True when leak tracing enabled.
+bool StarboardAllowsMemoryTracking();  // True when build enabled.
+}  // namespace.
+
+bool SbMemorySetReporter(SbMemoryReporter* reporter) {
+  // TODO: We should run a runtime test here with a test memory
+  // reporter that determines whether global operator new/delete are properly
+  // overridden. This problem appeared with address sanitizer and given
+  // how tricky operator new/delete are in general (see a google search)
+  // it's reasonable to assume that the likely hood of this happening again
+  // is high. To allow the QA/developer to take corrective action, this
+  // condition needs to be detected at runtime with a simple error message so
+  // that corrective action (i.e. running a different build) can be applied.
+  //
+  // RunOperatorNewDeleteRuntimeTest();  // Implement me.
+
+  // Flush local memory to main so that other threads don't
+  // see a partially constructed reporter due to memory
+  // re-ordering.
+  SbAtomicMemoryBarrier();
+  s_memory_reporter = reporter;
+
+  // These are straight forward error messages. We use the build settings to
+  // predict whether the MemoryReporter is likely to fail.
+  if (!StarboardAllowsMemoryTracking()) {
+    SbLogRaw("\nMemory Reporting is disabled because this build does "
+             "not support it. Try a QA, devel or debug build.\n");
+    return false;
+  } else if (LeakTraceEnabled()) {
+    SbLogRaw("\nMemory Reporting might be disabled because leak trace "
+             "(from address sanitizer?) is active.\n");
+    return false;
+  }
+  return true;
+}
 
 void* SbMemoryAllocate(size_t size) {
   void* memory = SbMemoryAllocateImpl(size);
+  SbReportAllocation(memory, size);
   return memory;
 }
 
 void* SbMemoryAllocateAligned(size_t alignment, size_t size) {
   void* memory = SbMemoryAllocateAlignedImpl(alignment, size);
+  SbReportAllocation(memory, size);
   return memory;
 }
 
 void* SbMemoryReallocate(void* memory, size_t size) {
+  SbReportDeallocation(memory);
   void* new_memory = SbMemoryReallocateImpl(memory, size);
+  SbReportAllocation(new_memory, size);
   return new_memory;
 }
 
 void SbMemoryDeallocate(void* memory) {
+  // Report must happen first or else a race condition allows the memory to
+  // be freed and then reported as allocated, before the allocation is removed.
+  SbReportDeallocation(memory);
   SbMemoryFree(memory);
 }
 
 void SbMemoryDeallocateAligned(void* memory) {
+  // Report must happen first or else a race condition allows the memory to
+  // be freed and then reported as allocated, before the allocation is removed.
+  SbReportDeallocation(memory);
   SbMemoryFreeAligned(memory);
 }
 
@@ -63,6 +118,63 @@
   return address;
 }
 
+void SbMemoryReporterReportMappedMemory(const void* memory, size_t size) {
+#if !defined(STARBOARD_ALLOWS_MEMORY_TRACKING)
+  return;
+#else
+  if (SB_LIKELY(!s_memory_reporter)) {
+    return;
+  }
+  s_memory_reporter->on_mapmem_cb(
+      s_memory_reporter->context,
+      memory,
+      size);
+#endif  // STARBOARD_ALLOWS_MEMORY_TRACKING
+}
+
+void SbMemoryReporterReportUnmappedMemory(const void* memory, size_t size) {
+#if !defined(STARBOARD_ALLOWS_MEMORY_TRACKING)
+  return;
+#else
+  if (SB_LIKELY(!s_memory_reporter)) {
+    return;
+  }
+  s_memory_reporter->on_unmapmem_cb(
+      s_memory_reporter->context,
+      memory,
+      size);
+#endif  // STARBOARD_ALLOWS_MEMORY_TRACKING
+}
+
+namespace {  // anonymous namespace.
+
+inline void SbReportAllocation(const void* memory, size_t size) {
+#if !defined(STARBOARD_ALLOWS_MEMORY_TRACKING)
+  return;
+#else
+  if (SB_LIKELY(!s_memory_reporter)) {
+    return;
+  }
+  s_memory_reporter->on_alloc_cb(
+      s_memory_reporter->context,
+      memory,
+      size);
+#endif  // STARBOARD_ALLOWS_MEMORY_TRACKING
+}
+
+inline void SbReportDeallocation(const void* memory) {
+#if !defined(STARBOARD_ALLOWS_MEMORY_TRACKING)
+  return;
+#else
+  if (SB_LIKELY(!s_memory_reporter)) {
+    return;
+  }
+  s_memory_reporter->on_dealloc_cb(
+      s_memory_reporter->context,
+      memory);
+#endif  // STARBOARD_ALLOWS_MEMORY_TRACKING
+}
+
 inline void* SbMemoryAllocateImpl(size_t size) {
 #if SB_ABORT_ON_ALLOCATION_FAILURE
   return SbMemoryAllocateChecked(size);
@@ -86,3 +198,25 @@
   return SbMemoryReallocateUnchecked(memory, size);
 #endif
 }
+
+bool LeakTraceEnabled() {
+#if defined(HAS_LEAK_SANITIZER) && (0 == HAS_LEAK_SANITIZER)
+  // In this build the leak tracer is specifically disabled. This
+  // build condition is typical for some builds of address sanitizer.
+  return true;
+#elif defined(ADDRESS_SANITIZER)
+  // Leak tracer is not specifically disabled and address sanitizer is running.
+  return true;
+#else
+  return false;
+#endif
+}
+
+bool StarboardAllowsMemoryTracking() {
+#if defined(STARBOARD_ALLOWS_MEMORY_TRACKING)
+  return true;
+#else
+  return false;
+#endif
+}
+}  // namespace
diff --git a/src/starboard/common/ref_counted.cc b/src/starboard/common/ref_counted.cc
new file mode 100644
index 0000000..32f67d5
--- /dev/null
+++ b/src/starboard/common/ref_counted.cc
@@ -0,0 +1,95 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "starboard/common/ref_counted.h"
+
+#include "starboard/log.h"
+
+namespace starboard {
+
+namespace subtle {
+
+RefCountedBase::RefCountedBase()
+    : ref_count_(0)
+#ifndef NDEBUG
+      ,
+      in_dtor_(false)
+#endif
+{
+}
+
+RefCountedBase::~RefCountedBase() {
+#ifndef NDEBUG
+  SB_DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()";
+#endif
+}
+
+void RefCountedBase::AddRef() const {
+// TODO(maruel): Add back once it doesn't assert 500 times/sec.
+// Current thread books the critical section "AddRelease" without release it.
+// DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
+#ifndef NDEBUG
+  SB_DCHECK(!in_dtor_);
+#endif
+  ++ref_count_;
+}
+
+bool RefCountedBase::Release() const {
+// TODO(maruel): Add back once it doesn't assert 500 times/sec.
+// Current thread books the critical section "AddRelease" without release it.
+// DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
+#ifndef NDEBUG
+  SB_DCHECK(!in_dtor_);
+#endif
+  if (--ref_count_ == 0) {
+#ifndef NDEBUG
+    in_dtor_ = true;
+#endif
+    return true;
+  }
+  return false;
+}
+
+bool RefCountedThreadSafeBase::HasOneRef() const {
+  return (SbAtomicAcquire_Load(
+              &const_cast<RefCountedThreadSafeBase*>(this)->ref_count_) == 1);
+}
+
+RefCountedThreadSafeBase::RefCountedThreadSafeBase() : ref_count_(0) {
+#ifndef NDEBUG
+  in_dtor_ = false;
+#endif
+}
+
+RefCountedThreadSafeBase::~RefCountedThreadSafeBase() {
+#ifndef NDEBUG
+  SB_DCHECK(in_dtor_) << "RefCountedThreadSafe object deleted without "
+                         "calling Release()";
+#endif
+}
+
+void RefCountedThreadSafeBase::AddRef() const {
+#ifndef NDEBUG
+  SB_DCHECK(!in_dtor_);
+#endif
+  SbAtomicNoBarrier_Increment(&ref_count_, 1);
+}
+
+bool RefCountedThreadSafeBase::Release() const {
+#ifndef NDEBUG
+  SB_DCHECK(!in_dtor_);
+  SB_DCHECK(!(SbAtomicAcquire_Load(&ref_count_) == 0));
+#endif
+  if (SbAtomicBarrier_Increment(&ref_count_, -1) == 0) {
+#ifndef NDEBUG
+    in_dtor_ = true;
+#endif
+    return true;
+  }
+  return false;
+}
+
+}  // namespace subtle
+
+}  // namespace starboard
diff --git a/src/starboard/common/ref_counted.h b/src/starboard/common/ref_counted.h
new file mode 100644
index 0000000..0ab74db
--- /dev/null
+++ b/src/starboard/common/ref_counted.h
@@ -0,0 +1,288 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef STARBOARD_COMMON_REF_COUNTED_H_
+#define STARBOARD_COMMON_REF_COUNTED_H_
+
+#include "starboard/atomic.h"
+#include "starboard/common/thread_collision_warner.h"
+#include "starboard/log.h"
+
+namespace starboard {
+
+namespace subtle {
+
+class RefCountedBase {
+ public:
+  bool HasOneRef() const { return ref_count_ == 1; }
+
+ protected:
+  RefCountedBase();
+  ~RefCountedBase();
+
+  void AddRef() const;
+
+  // Returns true if the object should self-delete.
+  bool Release() const;
+
+ private:
+  mutable int ref_count_;
+#ifndef NDEBUG
+  mutable bool in_dtor_;
+#endif
+
+  DFAKE_MUTEX(add_release_);
+};
+
+class RefCountedThreadSafeBase {
+ public:
+  bool HasOneRef() const;
+
+ protected:
+  RefCountedThreadSafeBase();
+  ~RefCountedThreadSafeBase();
+
+  void AddRef() const;
+
+  // Returns true if the object should self-delete.
+  bool Release() const;
+
+ private:
+  mutable SbAtomic32 ref_count_;
+#ifndef NDEBUG
+  mutable bool in_dtor_;
+#endif
+};
+
+}  // namespace subtle
+
+//
+// A base class for reference counted classes.  Otherwise, known as a cheap
+// knock-off of WebKit's RefCounted<T> class.  To use this guy just extend your
+// class from it like so:
+//
+//   class MyFoo : public starboard::RefCounted<MyFoo> {
+//    ...
+//    private:
+//     friend class starboard::RefCounted<MyFoo>;
+//     ~MyFoo();
+//   };
+//
+// You should always make your destructor private, to avoid any code deleting
+// the object accidently while there are references to it.
+template <class T>
+class RefCounted : public subtle::RefCountedBase {
+ public:
+  RefCounted() {}
+
+  void AddRef() const { subtle::RefCountedBase::AddRef(); }
+
+  void Release() const {
+    if (subtle::RefCountedBase::Release()) {
+      delete static_cast<const T*>(this);
+    }
+  }
+
+ protected:
+  ~RefCounted() {}
+};
+
+// Forward declaration.
+template <class T, typename Traits>
+class RefCountedThreadSafe;
+
+// Default traits for RefCountedThreadSafe<T>.  Deletes the object when its ref
+// count reaches 0.  Overload to delete it on a different thread etc.
+template <typename T>
+struct DefaultRefCountedThreadSafeTraits {
+  static void Destruct(const T* x) {
+    // Delete through RefCountedThreadSafe to make child classes only need to be
+    // friend with RefCountedThreadSafe instead of this struct, which is an
+    // implementation detail.
+    RefCountedThreadSafe<T, DefaultRefCountedThreadSafeTraits>::DeleteInternal(
+        x);
+  }
+};
+
+//
+// A thread-safe variant of RefCounted<T>
+//
+//   class MyFoo : public starboard::RefCountedThreadSafe<MyFoo> {
+//    ...
+//   };
+//
+// If you're using the default trait, then you should add compile time
+// asserts that no one else is deleting your object.  i.e.
+//    private:
+//     friend class starboard::RefCountedThreadSafe<MyFoo>;
+//     ~MyFoo();
+template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> >
+class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase {
+ public:
+  RefCountedThreadSafe() {}
+
+  void AddRef() const { subtle::RefCountedThreadSafeBase::AddRef(); }
+
+  void Release() const {
+    if (subtle::RefCountedThreadSafeBase::Release()) {
+      Traits::Destruct(static_cast<const T*>(this));
+    }
+  }
+
+ protected:
+  ~RefCountedThreadSafe() {}
+
+ private:
+  friend struct DefaultRefCountedThreadSafeTraits<T>;
+  static void DeleteInternal(const T* x) { delete x; }
+};
+
+//
+// A thread-safe wrapper for some piece of data so we can place other
+// things in scoped_refptrs<>.
+//
+template <typename T>
+class RefCountedData : public starboard::RefCountedThreadSafe<starboard::RefCountedData<T> > {
+ public:
+  RefCountedData() : data() {}
+  RefCountedData(const T& in_value) : data(in_value) {}
+
+  T data;
+
+ private:
+  friend class starboard::RefCountedThreadSafe<starboard::RefCountedData<T> >;
+  ~RefCountedData() {}
+};
+
+//
+// A smart pointer class for reference counted objects.  Use this class instead
+// of calling AddRef and Release manually on a reference counted object to
+// avoid common memory leaks caused by forgetting to Release an object
+// reference.  Sample usage:
+//
+//   class MyFoo : public RefCounted<MyFoo> {
+//    ...
+//   };
+//
+//   void some_function() {
+//     scoped_refptr<MyFoo> foo = new MyFoo();
+//     foo->Method(param);
+//     // |foo| is released when this function returns
+//   }
+//
+//   void some_other_function() {
+//     scoped_refptr<MyFoo> foo = new MyFoo();
+//     ...
+//     foo = NULL;  // explicitly releases |foo|
+//     ...
+//     if (foo)
+//       foo->Method(param);
+//   }
+//
+// The above examples show how scoped_refptr<T> acts like a pointer to T.
+// Given two scoped_refptr<T> classes, it is also possible to exchange
+// references between the two objects, like so:
+//
+//   {
+//     scoped_refptr<MyFoo> a = new MyFoo();
+//     scoped_refptr<MyFoo> b;
+//
+//     b.swap(a);
+//     // now, |b| references the MyFoo object, and |a| references NULL.
+//   }
+//
+// To make both |a| and |b| in the above example reference the same MyFoo
+// object, simply use the assignment operator:
+//
+//   {
+//     scoped_refptr<MyFoo> a = new MyFoo();
+//     scoped_refptr<MyFoo> b;
+//
+//     b = a;
+//     // now, |a| and |b| each own a reference to the same MyFoo object.
+//   }
+//
+template <class T>
+class scoped_refptr {
+ public:
+  typedef T element_type;
+
+  scoped_refptr() : ptr_(NULL) {}
+
+  scoped_refptr(T* p) : ptr_(p) {
+    if (ptr_)
+      ptr_->AddRef();
+  }
+
+  scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
+    if (ptr_)
+      ptr_->AddRef();
+  }
+
+  template <typename U>
+  scoped_refptr(const scoped_refptr<U>& r)
+      : ptr_(r.get()) {
+    if (ptr_)
+      ptr_->AddRef();
+  }
+
+  ~scoped_refptr() {
+    if (ptr_)
+      ptr_->Release();
+  }
+
+  T* get() const { return ptr_; }
+  operator T*() const { return ptr_; }
+  T* operator->() const {
+    SB_DCHECK(ptr_ != NULL);
+    return ptr_;
+  }
+
+  T& operator*() const {
+    SB_DCHECK(ptr_ != NULL);
+    return *ptr_;
+  }
+
+  scoped_refptr<T>& operator=(T* p) {
+    // AddRef first so that self assignment should work
+    if (p)
+      p->AddRef();
+    T* old_ptr = ptr_;
+    ptr_ = p;
+    if (old_ptr)
+      old_ptr->Release();
+    return *this;
+  }
+
+  scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
+    return * this = r.ptr_;
+  }
+
+  template <typename U>
+  scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
+    return * this = r.get();
+  }
+
+  void swap(T** pp) {
+    T* p = ptr_;
+    ptr_ = *pp;
+    *pp = p;
+  }
+
+  void swap(scoped_refptr<T>& r) { swap(&r.ptr_); }
+
+ protected:
+  T* ptr_;
+};
+
+// Handy utility for creating a scoped_refptr<T> out of a T* explicitly without
+// having to retype all the template arguments
+template <typename T>
+scoped_refptr<T> make_scoped_refptr(T* t) {
+  return scoped_refptr<T>(t);
+}
+
+}  // namespace starboard
+
+#endif  // STARBOARD_COMMON_REF_COUNTED_H_
diff --git a/src/starboard/common/thread_collision_warner.cc b/src/starboard/common/thread_collision_warner.cc
new file mode 100644
index 0000000..5a9e853
--- /dev/null
+++ b/src/starboard/common/thread_collision_warner.cc
@@ -0,0 +1,63 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "starboard/common/thread_collision_warner.h"
+
+#include "starboard/atomic.h"
+#include "starboard/log.h"
+#include "starboard/thread.h"
+#include "starboard/types.h"
+
+namespace starboard {
+
+void DCheckAsserter::warn() {
+  SB_NOTREACHED() << "Thread Collision";
+}
+
+static SbAtomic32 CurrentThread() {
+  const SbThreadId current_thread_id = SbThreadGetId();
+  // We need to get the thread id into an atomic data type. This might be a
+  // truncating conversion, but any loss-of-information just increases the
+  // chance of a false negative, not a false positive.
+  const SbAtomic32 atomic_thread_id =
+      static_cast<SbAtomic32>(current_thread_id);
+  return atomic_thread_id;
+}
+
+void ThreadCollisionWarner::EnterSelf() {
+  // If the active thread is 0 then I'll write the current thread ID
+  // if two or more threads arrive here only one will succeed to
+  // write on valid_thread_id_ the current thread ID.
+  SbAtomic32 current_thread_id = CurrentThread();
+
+  int previous_value =
+      SbAtomicNoBarrier_CompareAndSwap(&valid_thread_id_, 0, current_thread_id);
+  if (previous_value != 0 && previous_value != current_thread_id) {
+    // gotcha! a thread is trying to use the same class and that is
+    // not current thread.
+    asserter_->warn();
+  }
+
+  SbAtomicNoBarrier_Increment(&counter_, 1);
+}
+
+void ThreadCollisionWarner::Enter() {
+  SbAtomic32 current_thread_id = CurrentThread();
+
+  if (SbAtomicNoBarrier_CompareAndSwap(&valid_thread_id_, 0,
+                                       current_thread_id) != 0) {
+    // gotcha! another thread is trying to use the same class.
+    asserter_->warn();
+  }
+
+  SbAtomicNoBarrier_Increment(&counter_, 1);
+}
+
+void ThreadCollisionWarner::Leave() {
+  if (SbAtomicBarrier_Increment(&counter_, -1) == 0) {
+    SbAtomicNoBarrier_Store(&valid_thread_id_, 0);
+  }
+}
+
+}  // namespace starboard
diff --git a/src/starboard/common/thread_collision_warner.h b/src/starboard/common/thread_collision_warner.h
new file mode 100644
index 0000000..4aefb21
--- /dev/null
+++ b/src/starboard/common/thread_collision_warner.h
@@ -0,0 +1,220 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef STARBOARD_COMMON_THREAD_COLLISION_WARNER_H_
+#define STARBOARD_COMMON_THREAD_COLLISION_WARNER_H_
+
+#include "starboard/atomic.h"
+
+// A helper class alongside macros to be used to verify assumptions about thread
+// safety of a class.
+//
+// Example: Queue implementation non thread-safe but still usable if clients
+//          are synchronized somehow.
+//
+//          In this case the macro DFAKE_SCOPED_LOCK has to be
+//          used, it checks that if a thread is inside the push/pop then
+//          noone else is still inside the pop/push
+//
+// class NonThreadSafeQueue {
+//  public:
+//   ...
+//   void push(int) { DFAKE_SCOPED_LOCK(push_pop_); ... }
+//   int pop() { DFAKE_SCOPED_LOCK(push_pop_); ... }
+//   ...
+//  private:
+//   DFAKE_MUTEX(push_pop_);
+// };
+//
+//
+// Example: Queue implementation non thread-safe but still usable if clients
+//          are synchronized somehow, it calls a method to "protect" from
+//          a "protected" method
+//
+//          In this case the macro DFAKE_SCOPED_RECURSIVE_LOCK
+//          has to be used, it checks that if a thread is inside the push/pop
+//          then noone else is still inside the pop/push
+//
+// class NonThreadSafeQueue {
+//  public:
+//   void push(int) {
+//     DFAKE_SCOPED_LOCK(push_pop_);
+//     ...
+//   }
+//   int pop() {
+//     DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
+//     bar();
+//     ...
+//   }
+//   void bar() { DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_); ... }
+//   ...
+//  private:
+//   DFAKE_MUTEX(push_pop_);
+// };
+//
+//
+// Example: Queue implementation not usable even if clients are synchronized,
+//          so only one thread in the class life cycle can use the two members
+//          push/pop.
+//
+//          In this case the macro DFAKE_SCOPED_LOCK_THREAD_LOCKED pins the
+//          specified
+//          critical section the first time a thread enters push or pop, from
+//          that time on only that thread is allowed to execute push or pop.
+//
+// class NonThreadSafeQueue {
+//  public:
+//   ...
+//   void push(int) { DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_); ... }
+//   int pop() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_); ... }
+//   ...
+//  private:
+//   DFAKE_MUTEX(push_pop_);
+// };
+//
+//
+// Example: Class that has to be contructed/destroyed on same thread, it has
+//          a "shareable" method (with external synchronization) and a not
+//          shareable method (even with external synchronization).
+//
+//          In this case 3 Critical sections have to be defined
+//
+// class ExoticClass {
+//  public:
+//   ExoticClass() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(ctor_dtor_); ... }
+//   ~ExoticClass() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(ctor_dtor_); ... }
+//
+//   void Shareable() { DFAKE_SCOPED_LOCK(shareable_section_); ... }
+//   void NotShareable() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(ctor_dtor_); ... }
+//   ...
+//  private:
+//   DFAKE_MUTEX(ctor_dtor_);
+//   DFAKE_MUTEX(shareable_section_);
+// };
+
+#if !defined(NDEBUG)
+
+// Defines a class member that acts like a mutex. It is used only as a
+// verification tool.
+#define DFAKE_MUTEX(obj) mutable starboard::ThreadCollisionWarner obj
+// Asserts the call is never called simultaneously in two threads. Used at
+// member function scope.
+#define DFAKE_SCOPED_LOCK(obj) \
+  starboard::ThreadCollisionWarner::ScopedCheck s_check_##obj(&obj)
+// Asserts the call is never called simultaneously in two threads. Used at
+// member function scope. Same as DFAKE_SCOPED_LOCK but allows recursive locks.
+#define DFAKE_SCOPED_RECURSIVE_LOCK(obj) \
+  starboard::ThreadCollisionWarner::ScopedRecursiveCheck sr_check_##obj(&obj)
+// Asserts the code is always executed in the same thread.
+#define DFAKE_SCOPED_LOCK_THREAD_LOCKED(obj) \
+  starboard::ThreadCollisionWarner::Check check_##obj(&obj)
+
+#else
+
+#define DFAKE_MUTEX(obj) typedef void InternalFakeMutexType##obj
+#define DFAKE_SCOPED_LOCK(obj) ((void)0)
+#define DFAKE_SCOPED_RECURSIVE_LOCK(obj) ((void)0)
+#define DFAKE_SCOPED_LOCK_THREAD_LOCKED(obj) ((void)0)
+
+#endif
+
+namespace starboard {
+
+// The class ThreadCollisionWarner uses an Asserter to notify the collision
+// AsserterBase is the interfaces and DCheckAsserter is the default asserter
+// used. During the unit tests is used another class that doesn't "DCHECK"
+// in case of collision (check thread_collision_warner_unittests.cc)
+struct AsserterBase {
+  virtual ~AsserterBase() {}
+  virtual void warn() = 0;
+};
+
+struct DCheckAsserter : public AsserterBase {
+  virtual ~DCheckAsserter() {}
+  virtual void warn();
+};
+
+class ThreadCollisionWarner {
+ public:
+  // The parameter asserter is there only for test purpose
+  ThreadCollisionWarner(AsserterBase* asserter = new DCheckAsserter())
+      : valid_thread_id_(0), counter_(0), asserter_(asserter) {}
+
+  ~ThreadCollisionWarner() { delete asserter_; }
+
+  // This class is meant to be used through the macro
+  // DFAKE_SCOPED_LOCK_THREAD_LOCKED
+  // it doesn't leave the critical section, as opposed to ScopedCheck,
+  // because the critical section being pinned is allowed to be used only
+  // from one thread
+  class Check {
+   public:
+    explicit Check(ThreadCollisionWarner* warner) : warner_(warner) {
+      warner_->EnterSelf();
+    }
+
+    ~Check() {}
+
+   private:
+    ThreadCollisionWarner* warner_;
+  };
+
+  // This class is meant to be used through the macro
+  // DFAKE_SCOPED_LOCK
+  class ScopedCheck {
+   public:
+    explicit ScopedCheck(ThreadCollisionWarner* warner) : warner_(warner) {
+      warner_->Enter();
+    }
+
+    ~ScopedCheck() { warner_->Leave(); }
+
+   private:
+    ThreadCollisionWarner* warner_;
+  };
+
+  // This class is meant to be used through the macro
+  // DFAKE_SCOPED_RECURSIVE_LOCK
+  class ScopedRecursiveCheck {
+   public:
+    explicit ScopedRecursiveCheck(ThreadCollisionWarner* warner)
+        : warner_(warner) {
+      warner_->EnterSelf();
+    }
+
+    ~ScopedRecursiveCheck() { warner_->Leave(); }
+
+   private:
+    ThreadCollisionWarner* warner_;
+  };
+
+ private:
+  // This method stores the current thread identifier and does a DCHECK
+  // if a another thread has already done it, it is safe if same thread
+  // calls this multiple time (recursion allowed).
+  void EnterSelf();
+
+  // Same as EnterSelf but recursion is not allowed.
+  void Enter();
+
+  // Removes the thread_id stored in order to allow other threads to
+  // call EnterSelf or Enter.
+  void Leave();
+
+  // This stores the thread id that is inside the critical section, if the
+  // value is 0 then no thread is inside.
+  volatile SbAtomic32 valid_thread_id_;
+
+  // Counter to trace how many time a critical section was "pinned"
+  // (when allowed) in order to unpin it when counter_ reaches 0.
+  volatile SbAtomic32 counter_;
+
+  // Here only for class unit tests purpose, during the test I need to not
+  // DCHECK but notify the collision with something else.
+  AsserterBase* asserter_;
+};
+
+}  // namespace starboard
+
+#endif  // STARBOARD_COMMON_THREAD_COLLISION_WARNER_H_
diff --git a/src/starboard/condition_variable.h b/src/starboard/condition_variable.h
index 463f523..673b7d9 100644
--- a/src/starboard/condition_variable.h
+++ b/src/starboard/condition_variable.h
@@ -12,7 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Condition variables.
+// Module Overview: Starboard Condition Variable module
+//
+// Defines an interface for condition variables.
 
 #ifndef STARBOARD_CONDITION_VARIABLE_H_
 #define STARBOARD_CONDITION_VARIABLE_H_
@@ -51,18 +53,22 @@
 }
 
 // Creates a new condition variable to work with |opt_mutex|, which may be null,
-// placing the newly created condition variable in |out_condition|. Returns
-// whether the condition variable could be created.
+// placing the newly created condition variable in |out_condition|.
+//
+// The return value indicates whether the condition variable could be created.
+//
 // TODO: It looks like WTF does not have the mutex available when creating
 // the condition variable, and pthreads doesn't appear to require the mutex on
 // condvar creation, so we should just remove the parameter.
 SB_EXPORT bool SbConditionVariableCreate(SbConditionVariable* out_condition,
                                          SbMutex* opt_mutex);
 
-// Destroys a condition variable, returning whether the destruction was
-// successful. The condition variable specified by |condition| is
-// invalidated. Behavior is undefined if other threads are currently waiting
-// on this condition variable.
+// Destroys the specified SbConditionVariable. The return value indicates
+// whether the destruction was successful. The behavior is undefined if other
+// threads are currently waiting on this condition variable.
+//
+// |condition|: The SbConditionVariable to be destroyed. This invalidates the
+// condition variable.
 SB_EXPORT bool SbConditionVariableDestroy(SbConditionVariable* condition);
 
 // Waits for |condition|, releasing the held lock |mutex|, blocking
@@ -72,19 +78,30 @@
 SbConditionVariableWait(SbConditionVariable* condition, SbMutex* mutex);
 
 // Waits for |condition|, releasing the held lock |mutex|, blocking up to
-// |timeout_duration|, and returning the acquisition result. If
-// |timeout_duration| is less than or equal to zero, it will return as quickly
-// as possible with a kSbConditionVariableTimedOut result. Behavior is undefined
-// if |mutex| is not held.
+// |timeout_duration|, and returning the acquisition result. Behavior is
+// undefined if |mutex| is not held.
+//
+// |timeout_duration|: The maximum amount of time that function should wait
+// for |condition|. If the |timeout_duration| value is less than or equal to
+// zero, the function returns as quickly as possible with a
+// kSbConditionVariableTimedOut result.
 SB_EXPORT SbConditionVariableResult
 SbConditionVariableWaitTimed(SbConditionVariable* condition,
                              SbMutex* mutex,
                              SbTime timeout_duration);
 
-// Broadcasts to all current waiters of |condition| to stop waiting.
+// Broadcasts to all current waiters of |condition| to stop waiting. This
+// function wakes all of the threads waiting on |condition| while
+// SbConditionVariableSignal wakes a single thread.
+//
+// |condition|: The condition that should no longer be waited for.
 SB_EXPORT bool SbConditionVariableBroadcast(SbConditionVariable* condition);
 
-// Signals the next waiter of |condition| to stop waiting.
+// Signals the next waiter of |condition| to stop waiting. This function wakes
+// a single thread waiting on |condition| while SbConditionVariableBroadcast
+// wakes all threads waiting on it.
+//
+// |condition|: The condition that the waiter should stop waiting for.
 SB_EXPORT bool SbConditionVariableSignal(SbConditionVariable* condition);
 
 #ifdef __cplusplus
diff --git a/src/starboard/configuration.h b/src/starboard/configuration.h
index 444cc9f..838b5e8 100644
--- a/src/starboard/configuration.h
+++ b/src/starboard/configuration.h
@@ -12,13 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// A description of the current platform in lurid detail such that common code
-// never needs to actually know what the current operating system and
-// architecture are. It is both very pragmatic and canonical in that if any
-// application code finds itself needing to make a platform decision, it should
-// always define a Starboard Configuration feature instead. This implies the
-// continued existence of very narrowly-defined configuration features, but it
-// retains porting control in Starboard.
+// Module Overview: Starboard Configuration module
+//
+// Provides a description of the current platform in lurid detail so that
+// common code never needs to actually know what the current operating system
+// and architecture are.
+//
+// It is both very pragmatic and canonical in that if any application code
+// finds itself needing to make a platform decision, it should always define
+// a Starboard Configuration feature instead. This implies the continued
+// existence of very narrowly-defined configuration features, but it retains
+// porting control in Starboard.
 
 #ifndef STARBOARD_CONFIGURATION_H_
 #define STARBOARD_CONFIGURATION_H_
@@ -365,6 +369,10 @@
 #error "Your platform must define SB_HAS_MICROPHONE in API versions 2 or later."
 #endif
 
+#if SB_VERSION(3) && !defined(SB_HAS_TIME_THREAD_NOW)
+#error "Your platform must define SB_HAS_TIME_THREAD_NOW in API 3 or later."
+#endif
+
 #if SB_HAS(PLAYER)
 #if !SB_IS(PLAYER_COMPOSITED) && !SB_IS(PLAYER_PUNCHED_OUT) && \
     !SB_IS(PLAYER_PRODUCING_TEXTURE)
diff --git a/src/starboard/creator/ci20directfb/starboard_platform.gyp b/src/starboard/creator/ci20directfb/starboard_platform.gyp
index b695c91..284be6b 100644
--- a/src/starboard/creator/ci20directfb/starboard_platform.gyp
+++ b/src/starboard/creator/ci20directfb/starboard_platform.gyp
@@ -209,6 +209,7 @@
         '<(DEPTH)/starboard/shared/posix/system_get_number_of_processors.cc',
         '<(DEPTH)/starboard/shared/posix/thread_sleep.cc',
         '<(DEPTH)/starboard/shared/posix/time_get_monotonic_now.cc',
+        '<(DEPTH)/starboard/shared/posix/time_get_monotonic_thread_now.cc',
         '<(DEPTH)/starboard/shared/posix/time_get_now.cc',
         '<(DEPTH)/starboard/shared/posix/time_zone_get_current.cc',
         '<(DEPTH)/starboard/shared/posix/time_zone_get_dst_name.cc',
diff --git a/src/starboard/creator/ci20directfb/system_get_property.cc b/src/starboard/creator/ci20directfb/system_get_property.cc
index db0f0e0..51ca55f 100644
--- a/src/starboard/creator/ci20directfb/system_get_property.cc
+++ b/src/starboard/creator/ci20directfb/system_get_property.cc
@@ -47,6 +47,7 @@
     case kSbSystemPropertyModelName:
     case kSbSystemPropertyModelYear:
     case kSbSystemPropertyNetworkOperatorName:
+    case kSbSystemPropertySpeechApiKey:
       return false;
 
     case kSbSystemPropertyFriendlyName:
diff --git a/src/starboard/creator/ci20x11/starboard_platform.gyp b/src/starboard/creator/ci20x11/starboard_platform.gyp
index bab02c6..34be5d0 100644
--- a/src/starboard/creator/ci20x11/starboard_platform.gyp
+++ b/src/starboard/creator/ci20x11/starboard_platform.gyp
@@ -173,6 +173,7 @@
         '<(DEPTH)/starboard/shared/posix/system_get_number_of_processors.cc',
         '<(DEPTH)/starboard/shared/posix/thread_sleep.cc',
         '<(DEPTH)/starboard/shared/posix/time_get_monotonic_now.cc',
+        '<(DEPTH)/starboard/shared/posix/time_get_monotonic_thread_now.cc',
         '<(DEPTH)/starboard/shared/posix/time_get_now.cc',
         '<(DEPTH)/starboard/shared/posix/time_zone_get_current.cc',
         '<(DEPTH)/starboard/shared/posix/time_zone_get_dst_name.cc',
diff --git a/src/starboard/creator/ci20x11/system_get_property.cc b/src/starboard/creator/ci20x11/system_get_property.cc
index 8a7a795..9d71165 100644
--- a/src/starboard/creator/ci20x11/system_get_property.cc
+++ b/src/starboard/creator/ci20x11/system_get_property.cc
@@ -47,6 +47,7 @@
     case kSbSystemPropertyModelName:
     case kSbSystemPropertyModelYear:
     case kSbSystemPropertyNetworkOperatorName:
+    case kSbSystemPropertySpeechApiKey:
       return false;
 
     case kSbSystemPropertyFriendlyName:
diff --git a/src/starboard/creator/shared/configuration_public.h b/src/starboard/creator/shared/configuration_public.h
index 8898d5b..bcf356a 100644
--- a/src/starboard/creator/shared/configuration_public.h
+++ b/src/starboard/creator/shared/configuration_public.h
@@ -88,7 +88,7 @@
 #define SB_HAS_CROSS_CORE_SCHEDULER 1
 
 // The API version implemented by this platform.
-#define SB_API_VERSION 1
+#define SB_API_VERSION 2
 
 // --- System Header Configuration -------------------------------------------
 
@@ -119,6 +119,12 @@
 // Whether the current platform provides the standard header float.h.
 #define SB_HAS_FLOAT_H 1
 
+// Whether the current platform has microphone supported.
+#define SB_HAS_MICROPHONE 0
+
+// Whether the current platform has speech synthesis.
+#define SB_HAS_SPEECH_SYNTHESIS 0
+
 // Type detection for wchar_t.
 #if defined(__WCHAR_MAX__) && \
     (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff)
@@ -439,6 +445,12 @@
 // The maximum number of users that can be signed in at the same time.
 #define SB_USER_MAX_SIGNED_IN 1
 
+// --- Timing API ------------------------------------------------------------
+
+// Whether this platform has an API to retrieve how long the current thread
+// has spent in the executing state.
+#define SB_HAS_TIME_THREAD_NOW 1
+
 // --- Platform Specific Audits ----------------------------------------------
 
 #if !defined(__GNUC__)
diff --git a/src/starboard/decode_target.h b/src/starboard/decode_target.h
index 6ea6951..557c511 100644
--- a/src/starboard/decode_target.h
+++ b/src/starboard/decode_target.h
@@ -49,7 +49,8 @@
 // Let's say there's an image decoder for .foo files:
 //
 //     bool SbImageDecodeFooSupportsFormat(SbDecodeTargetFormat format);
-//     bool SbImageDecodeFoo(void *data, int data_size, SbDecodeTarget target);
+//     SbDecodeTarget SbImageDecodeFoo(void* data, int data_size,
+//                                     SbDecodeTargetFormat format);
 //
 // First, the client should enumerate which SbDecodeTargetFormats are supported
 // by that decoder.
@@ -68,25 +69,13 @@
 //       }
 //     }
 //
-// Now that the client has a format, it can create a decode target that it will
-// use to decode the .foo file into. Let's assume format is
-// kSbDecodeTargetFormat1PlaneRGBA, and that we are on an EGL/GLES2 platform.
+// Now that the client has a format, it can create a decode target that it
+// will use to decode the .foo file into. Let's assume format is
+// kSbDecodeTargetFormat1PlaneRGBA, that we are on an EGL/GLES2 platform.
 // Also, we won't do any error checking, to keep things even simpler.
 //
-//     // Allocate a sized texture of the right format.
-//     GLuint texture_handle;
-//     glGenTextures(1, &texture_handle);
-//     glBindTexture(GL_TEXTURE_2D, texture_handle);
-//     glTexImage2D(GL_TEXTURE_2D, 0 /*level*/, GL_RGBA, width, height,
-//                  0 /*border*/, GL_RGBA8, GL_UNSIGNED_BYTE, NULL /*data*/);
-//     glBindTexture(GL_TEXTURE_2D, 0);
-//
-//     // Create an SbDecodeTarget wrapping the new texture handle.
-//     SbDecodeTarget target =
-//         SbDecodeTargetCreate(display, context, format, &texture_handle);
-//
-//     // Now pass the SbDecodeTarget into the decoder.
-//     SbImageDecodeFoo(encoded_foo_data, encoded_foo_data_size, target);
+//     SbDecodeTarget target = SbImageDecodeFoo(encoded_foo_data,
+//                                              encoded_foo_data_size, format);
 //
 //     // If the decode works, you can get the texture out and render it.
 //     GLuint texture =
@@ -100,14 +89,14 @@
 #include "starboard/export.h"
 #include "starboard/types.h"
 
-#if SB_VERSION(3) && SB_HAS(GRAPHICS)
+#if SB_VERSION(3)
 
 #if SB_HAS(BLITTER)
 #include "starboard/blitter.h"
-#else
+#elif SB_HAS(GLES2)  // SB_HAS(BLITTER)
 #include <EGL/egl.h>
-#include <GL/gl.h>
-#endif
+#include <GLES2/gl2.h>
+#endif  // SB_HAS(BLITTER)
 
 #ifdef __cplusplus
 extern "C" {
@@ -189,6 +178,9 @@
 
   // The function to release an acquired SbDecodeTarget back to the provider.
   SbDecodeTargetReleaseFunction release;
+
+  // |context| will be passed into every call to |acquire| and |release|.
+  void* context;
 } SbDecodeTargetProvider;
 
 // --- Constants -------------------------------------------------------------
@@ -203,6 +195,12 @@
   return handle != kSbDecodeTargetInvalid;
 }
 
+// Returns whether a given format is valid.
+static SB_C_INLINE bool SbDecodeTargetIsFormatValid(
+    SbDecodeTargetFormat format) {
+  return format != kSbDecodeTargetFormatInvalid;
+}
+
 #if SB_HAS(BLITTER)
 // Creates a new SbBlitter-compatible SbDecodeTarget from one or more |planes|
 // created from |display|.
@@ -218,7 +216,7 @@
 // Gets the surface that represents the given plane.
 SB_EXPORT SbBlitterSurface SbDecodeTargetGetPlane(SbDecodeTarget decode_target,
                                                   SbDecodeTargetPlane plane);
-#else   // SB_HAS(BLITTER)
+#elif SB_HAS(GLES2)  // SB_HAS(BLITTER)
 // Creates a new EGL/GLES2-compatible SbDecodeTarget from one or more |planes|
 // owned by |context|, created from |display|. Must be called from a thread
 // where |context| is current.
@@ -239,48 +237,71 @@
 // Gets the texture that represents the given plane.
 SB_EXPORT GLuint SbDecodeTargetGetPlane(SbDecodeTarget decode_target,
                                         SbDecodeTargetPlane plane);
+
+#else  // SB_HAS(BLITTER)
+
+// Stub function for when graphics aren't enabled.  Always creates
+// kSbDecodeTargetInvalid.
+static SB_C_INLINE SbDecodeTarget
+SbDecodeTargetCreate(SbDecodeTargetFormat format) {
+  SB_UNREFERENCED_PARAMETER(format);
+  return kSbDecodeTargetInvalid;
+}
+
+// Stub function for when graphics aren't enabled.  There is no concept of a
+// plane, and |NULL| is always returned.
+static SB_C_INLINE void* SbDecodeTargetGetPlane(SbDecodeTarget decode_target,
+                                                SbDecodeTargetPlane plane) {
+  SB_UNREFERENCED_PARAMETER(decode_target);
+  SB_UNREFERENCED_PARAMETER(plane);
+  return NULL;
+}
+
 #endif  // SB_HAS(BLITTER)
 
-// Destroys the given SbDecodeTarget and all associated surfaces.
+// Destroys the given SbDecodeTarget. Note that calling this function does NOT
+// destroy the associated surfaces with it, in order to accommodate the case
+// in which it is desirable for the lifetime of the surface to outlive the
+// SbDecodeTarget that contains it. If the surfaces should be destroyed along
+// with the SbDecodeTarget, then they should be extracted with
+// |SbDecodeTargetGetPlane| and destroyed manually by the client.
 SB_EXPORT void SbDecodeTargetDestroy(SbDecodeTarget decode_target);
 
 // Gets the format that |decode_target| was created with.
 SB_EXPORT SbDecodeTargetFormat
 SbDecodeTargetGetFormat(SbDecodeTarget decode_target);
 
-// Registers |provider| as the SbDecodeTargetProvider with the given |context|,
-// displacing any previous registered provider. The provider is expected to be
-// kept alive by the caller until unregistered, so this function is NOT passing
-// ownership in any way. |context| will be passed into every call to
-// SbDecodeTargetProvider::acquire or SbDecodeTargetProvider::release. May be
-// called from any thread.
-SB_EXPORT bool SbDecodeTargetRegisterProvider(SbDecodeTargetProvider* provider,
-                                              void* context);
+// Gets whether |decode_target| is opaque or not.  The underlying source of
+// this value is expected to be properly maintained by the Starboard
+// implementation.  So, for example, if an opaque only image type were decoded
+// into an SbDecodeTarget, then the implementation would configure things in
+// such a way that this function would return true.  By opaque, it is meant
+// that all alpha values are guaranteed to be 255, if |decode_target| is of a
+// format that has alpha values.  If |decode_target| is of a format that does
+// not have alpha values, then this function should return |true|.
+SB_EXPORT bool SbDecodeTargetIsOpaque(SbDecodeTarget decode_target);
 
-// Unregisters |provider| as the SbDecodeTargetProvider, with |context|, if it
-// is the current registered provider-context. This is checked by comparing the
-// pointer values of both |provider| and |context| to the currently registered
-// provider. May be called from any thread.
-SB_EXPORT void SbDecodeTargetUnregisterProvider(
-    SbDecodeTargetProvider* provider,
-    void* context);
-
-// Acquires a decode target from the registered SbDecodeTargetProvider,
-// returning NULL if none is registered. May be called from any thread.
-SB_EXPORT SbDecodeTarget
-SbDecodeTargetAcquireFromProvider(SbDecodeTargetFormat format,
+// Inline convenience function to acquire an SbDecodeTarget of type |format|,
+// |width|, and |height| from |provider|.
+static SB_C_INLINE SbDecodeTarget
+SbDecodeTargetAcquireFromProvider(SbDecodeTargetProvider* provider,
+                                  SbDecodeTargetFormat format,
                                   int width,
-                                  int height);
+                                  int height) {
+  return provider->acquire(provider->context, format, width, height);
+}
 
-// Releases |decode_target| back to the registered SbDecodeTargetProvider. If no
-// provider is registered, just calls SbDecodeTargetDestroy on |decode_target|.
-// May be called from any thread.
-SB_EXPORT void SbDecodeTargetReleaseToProvider(SbDecodeTarget decode_target);
+// Inline convenience function to release |decode_target| back to |provider|.
+static SB_C_INLINE void SbDecodeTargetReleaseToProvider(
+    SbDecodeTargetProvider* provider,
+    SbDecodeTarget decode_target) {
+  provider->release(provider->context, decode_target);
+}
 
 #ifdef __cplusplus
 }  // extern "C"
 #endif
 
-#endif  // SB_VERSION(3) && SB_HAS(GRAPHICS)
+#endif  // SB_VERSION(3)
 
 #endif  // STARBOARD_DECODE_TARGET_H_
diff --git a/src/starboard/directory.h b/src/starboard/directory.h
index 728b875..0147306 100644
--- a/src/starboard/directory.h
+++ b/src/starboard/directory.h
@@ -12,7 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Directory listing API.
+// Module Overview: Starboard Directory module
+//
+// Provides directory listing functions.
 
 #ifndef STARBOARD_DIRECTORY_H_
 #define STARBOARD_DIRECTORY_H_
@@ -46,26 +48,43 @@
   return directory != kSbDirectoryInvalid;
 }
 
-// Opens the given existing directory for listing. Will return
-// kSbDirectoryInvalidHandle if not successful. If |out_error| is provided by
-// the caller, it will be set to the appropriate SbFileError code on failure.
+// Opens the given existing directory for listing. This function returns
+// kSbDirectoryInvalidHandle if it is not successful.
+//
+// If |out_error| is provided by the caller, it will be set to the appropriate
+// SbFileError code on failure.
+//
+// |out_error|: An output parameter that, in case of an error, is set to the
+// reason that the directory could not be opened.
 SB_EXPORT SbDirectory SbDirectoryOpen(const char* path, SbFileError* out_error);
 
-// Closes an open directory stream handle. Returns whether the close was
-// successful.
+// Closes an open directory stream handle. The return value indicates whether
+// the directory was closed successfully.
+//
+// |directory|: The directory stream handle to close.
 SB_EXPORT bool SbDirectoryClose(SbDirectory directory);
 
-// Populates |out_entry| with the next entry in that directory stream, and moves
-// the stream forward by one entry. Returns |true| if there was a next
-// directory, and |false| at the end of the directory stream.
+// Populates |out_entry| with the next entry in the specified directory stream,
+// and moves the stream forward by one entry.
+//
+// This function returns |true| if there was a next directory, and |false|
+// at the end of the directory stream.
+//
+// |directory|: The directory stream from which to retrieve the next directory.
+// |out_entry|: The variable to be populated with the next directory entry.
 SB_EXPORT bool SbDirectoryGetNext(SbDirectory directory,
                                   SbDirectoryEntry* out_entry);
 
-// Returns whether SbDirectoryOpen is allowed for the given |path|.
+// Indicates whether SbDirectoryOpen is allowed for the given |path|.
+//
+// |path|: The path to be checked.
 SB_EXPORT bool SbDirectoryCanOpen(const char* path);
 
 // Creates the directory |path|, assuming the parent directory already exists.
-// Returns whether the directory now exists (even if it existed before).
+// This function returns |true| if the directory now exists (even if it existed
+// before) and returns |false| if the directory does not exist.
+//
+// |path|: The path to be created.
 SB_EXPORT bool SbDirectoryCreate(const char* path);
 
 #ifdef __cplusplus
diff --git a/src/starboard/double.h b/src/starboard/double.h
index bde6acc..8a28bbc 100644
--- a/src/starboard/double.h
+++ b/src/starboard/double.h
@@ -12,7 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Double-precision floating point helper functions.
+// Module Overview: Starboard Double module
+//
+// Provides double-precision floating point helper functions.
 
 #ifndef STARBOARD_DOUBLE_H_
 #define STARBOARD_DOUBLE_H_
@@ -25,21 +27,32 @@
 #endif
 
 // Floors double-precision floating-point number |d| to the nearest integer.
+//
+// |d|: The number to be floored.
 SB_EXPORT double SbDoubleFloor(const double d);
 
 // Returns the absolute value of the given double-precision floating-point
-// number |d|, preserving NaN and Infinity.
+// number |d|, preserving |NaN| and infinity.
+//
+// |d|: The number to be adjusted.
 SB_EXPORT double SbDoubleAbsolute(const double d);
 
 // Returns |base| taken to the power of |exponent|.
+//
+// |base|: The number to be adjusted.
+// |exponent|: The power to which the |base| number should be raised.
 SB_EXPORT double SbDoubleExponent(const double base, const double exponent);
 
 // Determines whether double-precision floating-point number |d| represents a
-// fininte number.
+// finite number.
+//
+// |d|: The number to be evaluated.
 SB_EXPORT bool SbDoubleIsFinite(const double d);
 
-// Determines whether double-precision floating-point number |d| represents "Not
-// a Number."
+// Determines whether double-precision floating-point number |d| represents
+// "Not a Number."
+//
+// |d|: The number to be evaluated.
 SB_EXPORT bool SbDoubleIsNan(const double d);
 
 #ifdef __cplusplus
diff --git a/src/starboard/event.h b/src/starboard/event.h
index cec1884..44cdd79 100644
--- a/src/starboard/event.h
+++ b/src/starboard/event.h
@@ -12,7 +12,47 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// The event system that wraps the Starboard main loop and entry point.
+// Module Overview: Starboard Event module
+//
+// Defines the event system that wraps the Starboard main loop and entry point.
+//
+// ## The Starboard Application life cycle
+//
+// |          *
+// |          |                      _________________________
+// |        Start                   |                         |
+// |          |                     |                       Resume
+// |          V                     V                         |
+// |     [ STARTED ] --Pause--> [ PAUSED ] --Suspend--> [ SUSPENDED ]
+// |          ^                     |                         |
+// |          |                  Unpause                     Stop
+// |          |_____________________|                         |
+// |                                                          V
+// |                                                     [ STOPPED ]
+//
+// The first event that a Starboard application receives is Start
+// (kSbEventTypeStart). This puts the application in the |STARTED| state.
+// The application is in the foreground and can expect to do all of the normal
+// things it might want to do. Once in the |STARTED| state, it may receive a
+// |Pause| event, putting the application into the |PAUSED| state.
+//
+// In the |PAUSED| state, the application is still visible, but has lost
+// focus, or it is partially obscured by a modal dialog, or it is on its way
+// to being shut down. The application should pause activity in this state.
+// In this state, it can receive |Unpause| to be brought back to the foreground
+// state (|STARTED|), or |Suspend| to be pushed further in the background
+// to the |SUSPENDED| state.
+//
+// In the |SUSPENDED| state, the application is generally not visible. It
+// should immediately release all graphics and video resources, and shut down
+// all background activity (timers, rendering, etc). Additionally, the
+// application should flush storage to ensure that if the application is
+// killed, the storage will be up-to-date. The application may be killed at
+// this point, but will ideally receive a |Stop| event for a more graceful
+// shutdown.
+//
+// Note that the application is always expected to transition through |PAUSED|
+// to |SUSPENDED| before receiving |Stop| or being killed.
 
 #ifndef STARBOARD_EVENT_H_
 #define STARBOARD_EVENT_H_
@@ -26,43 +66,6 @@
 extern "C" {
 #endif
 
-// The Starboard Application life cycle
-// ------------------------------------
-//
-//           *
-//           |                      _________________________
-//         Start                   |                         |
-//           |                     |                       Resume
-//           V                     V                         |
-//      [ STARTED ] --Pause--> [ PAUSED ] --Suspend--> [ SUSPENDED ]
-//           ^                     |                         |
-//           |                  Unpause                     Stop
-//           |_____________________|                         |
-//                                                           V
-//                                                      [ STOPPED ]
-//
-// The first event that a Starboard application will receive is Start
-// (kSbEventTypeStart). This puts the application in the STARTED state; it is in
-// the foreground and can expect to do all the normal things it might want to
-// do. Once in the STARTED state, it may receive a Pause event, putting the
-// application into the PAUSED state.
-//
-// In the PAUSED state, the application is still visible, but has lost focus, or
-// it is partially obscured by a modal dialog, or it is on its way to being shut
-// down. The application should pause activity in this state. In this state, it
-// can receive Unpause to be brought back to the foreground state, STARTED, or
-// Suspend to be pushed further in the background to the SUSPENDED state.
-//
-// In the SUSPENDED state, the application is generally not visible. It should
-// immediately release all graphics and video resources, and shut down all
-// background activity (timers, rendering, etc). Additionally, the application
-// should flush storage to ensure that if the application is killed, the storage
-// will be up-to-date. The application may be killed at this point, but will
-// ideally receive a Stop event for a more graceful shutdown.
-//
-// Note that the application is always expected to transition through PAUSED to
-// SUSPENDED before receiving Stop or being killed.
-
 // An enumeration of all possible event types dispatched directly by the
 // system. Each event is accompanied by a void* data argument, and each event
 // must define the type of the value pointed to by that data argument, if any.
@@ -185,31 +188,36 @@
   return handle != kSbEventIdInvalid;
 }
 
-// Declaration of the entry point that Starboard applications MUST implement.
-// Any memory pointed at by |event| or the |data| field inside |event| is owned
-// by the system, and will be reclaimed after this function returns, so the
-// implementation must copy this data to extend its life.  This should also be
-// assumed of all fields within the data object, unless otherwise explicitly
-// specified. This function will only be called from the main Starboard thread.
-// There is no specification about what other work might happen on this thread,
-// so the application should generally do as little work as possible on this
-// thread, and just dispatch it over to another thread.
+// The entry point that Starboard applications MUST implement. Any memory
+// pointed at by |event| or the |data| field inside |event| is owned by the
+// system, and that memory is reclaimed after this function returns, so the
+// implementation must copy this data to extend its life. This behavior should
+// also be assumed of all fields within the |data| object, unless otherwise
+// explicitly specified.
+//
+// This function is only called from the main Starboard thread. There is no
+// specification about what other work might happen on this thread, so the
+// application should generally do as little work as possible on this thread,
+// and just dispatch it over to another thread.
 SB_IMPORT void SbEventHandle(const SbEvent* event);
 
-// Schedules an event |callback| into the main Starboard event loop, with
-// accompanying |context|. This function may be called from any thread, but
-// |callback| will always be called from the main Starboard thread, queued with
-// other pending events. |callback| will not be called any earlier than |delay|
-// microseconds from the time SbEventInject is called. Set |delay| to 0 to call
-// the event as soon as possible.
+// Schedules an event |callback| into the main Starboard event loop.
+// This function may be called from any thread, but |callback| is always
+// called from the main Starboard thread, queued with other pending events.
+//
+// |callback|: The callback function to be called.
+// |context|: The context that is passed to the |callback| function.
+// |delay|: The minimum number of microseconds to wait before calling the
+// |callback| function. Set |delay| to |0| to call the callback as soon as
+// possible.
 SB_EXPORT SbEventId SbEventSchedule(SbEventCallback callback,
                                     void* context,
                                     SbTime delay);
 
-// Cancels the injected |event_id|. Does nothing if the event already fired. Can
-// be safely called from any thread, but there is no guarantee that the event
-// will not run anyway unless it is called from the main Starboard event loop
-// thread.
+// Cancels the specified |event_id|. Note that this function is a no-op
+// if the event already fired. This function can be safely called from any
+// thread, but the only way to guarantee that the event does not run anyway
+// is to call it from the main Starboard event loop thread.
 SB_EXPORT void SbEventCancel(SbEventId event_id);
 
 #ifdef __cplusplus
diff --git a/src/starboard/export.h b/src/starboard/export.h
index af2303f..b19c1c7 100644
--- a/src/starboard/export.h
+++ b/src/starboard/export.h
@@ -12,7 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Macros to properly export or import symbols from shared libraries.
+// Module Overview: Starboard Export module
+//
+// Provides macros for properly exporting or importing symbols from shared
+// libraries.
 
 #ifndef STARBOARD_EXPORT_H_
 #define STARBOARD_EXPORT_H_
diff --git a/src/starboard/file.h b/src/starboard/file.h
index 3f15daf..0e92907 100644
--- a/src/starboard/file.h
+++ b/src/starboard/file.h
@@ -12,7 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// File system Input/Output
+// Module Overview: Starboard File module
+//
+// Defines file system input/output functions.
 
 #ifndef STARBOARD_FILE_H_
 #define STARBOARD_FILE_H_
@@ -32,17 +34,33 @@
 // A handle to an open file.
 typedef SbFilePrivate* SbFile;
 
-// kSbFile(Open|Create)(Only|Always|Truncated) are mutually exclusive. You
-// should specify exactly one of the five (possibly combining with other flags)
-// when opening or creating a file.
+// Flags that define how a file is used in the application. These flags should
+// be or'd together when passed to SbFileOpen to open or create a file.
+//
+// The following five flags are mutually exclusive. You must specify exactly one
+// of them:
+// - |kSbFileOpenAlways|
+// - |kSbFileOpenOnly|
+// - |kSbFileOpenTruncated|
+// - |kSbFileCreateAlways|
+// - |kSbFileCreateOnly|
+//
+// In addition, one or more of the following flags must be specified:
+// - |kSbFileRead|
+// - |kSbFileWrite|
+//
+// The |kSbFileAsync| flag is optional.
 typedef enum SbFileFlags {
   kSbFileOpenOnly = 1 << 0,       // Opens a file, only if it exists.
   kSbFileCreateOnly = 1 << 1,     // Creates a new file, only if it
                                   //   does not already exist.
-  kSbFileOpenAlways = 1 << 2,     // May create a new file.
-  kSbFileCreateAlways = 1 << 3,   // May overwrite an old file.
-  kSbFileOpenTruncated = 1 << 4,  // Opens a file and truncates it
-                                  //   to zero, only if it exists.
+  kSbFileOpenAlways = 1 << 2,     // Opens an existing file at the specified
+                                  // path or creates a new file at that path.
+  kSbFileCreateAlways = 1 << 3,   // Creates a new file at the specified path
+                                  // or overwrites an existing file at that
+                                  // path.
+  kSbFileOpenTruncated = 1 << 4,  // Opens a file and truncates it to zero,
+                                  // only if it exists.
   kSbFileRead = 1 << 5,
   kSbFileWrite = 1 << 6,
   kSbFileAsync = 1 << 7,  // May allow asynchronous I/O on some
@@ -112,81 +130,140 @@
 }
 
 // Opens the file at |path|, which must be absolute, creating it if specified by
-// |flags|. |out_created|, if provided, will be set to true if a new file was
-// created (or an old one truncated to zero length to simulate a new file, which
-// can happen with kSbFileCreateAlways), and false otherwise.  |out_error| can
-// be NULL. If creation failed, it will return kSbFileInvalid. The read/write
-// position is at the beginning of the file.
+// |flags|. The read/write position is at the beginning of the file.
 //
-// It only guarantees the correct behavior when |path| points to a file. If
-// |path| points to directory, the behavior is undefined.
+// Note that this function only guarantees the correct behavior when |path|
+// points to a file. The behavior is undefined if |path| points to a directory.
+//
+// |path|: The absolute path of the file to be opened.
+// |flags|: |SbFileFlags| that determine how the file is used in the
+//   application. Among other things, |flags| can indicate whether the
+//   application should create |path| if |path| does not already exist.
+// |out_created|: Starboard sets this value to |true| if a new file is created
+//   or if an old file is truncated to zero length to simulate a new file,
+//   which can happen if the |kSbFileCreateAlways| flag is set. Otherwise,
+//   Starboard sets this value to |false|.
+// |out_error|: If |path| cannot be created, this is set to |kSbFileInvalid|.
+//   Otherwise, it is |NULL|.
 SB_EXPORT SbFile SbFileOpen(const char* path,
                             int flags,
                             bool* out_created,
                             SbFileError* out_error);
 
-// Closes |file|. Returns whether the close was successful.
+// Closes |file|. The return value indicates whether the file was closed
+// successfully.
+//
+// |file|: The absolute path of the file to be closed.
 SB_EXPORT bool SbFileClose(SbFile file);
 
-// Changes current read/write position in |file| to |offset| relative to the
-// origin defined by |whence|. Returns the resultant current read/write position
-// in the file (relative to the start) or -1 in case of error. May not support
+// Changes the current read/write position in |file|. The return value
+// identifies the resultant current read/write position in the file (relative
+// to the start) or |-1| in case of an error. This function might not support
 // seeking past the end of the file on some platforms.
+//
+// |file|: The SbFile in which the read/write position will be changed.
+// |whence|: The starting read/write position. The position is modified relative
+//   to this value.
+// |offset|: The amount that the read/write position is changed, relative to
+//   |whence|.
 SB_EXPORT int64_t SbFileSeek(SbFile file, SbFileWhence whence, int64_t offset);
 
 // Reads |size| bytes (or until EOF is reached) from |file| into |data|,
-// starting at the file's current position. Returns the number of bytes read, or
-// -1 on error. Note that this function does NOT make a best effort to read all
-// data on all platforms, it just reads however many bytes are quickly
-// available. Can be run in a loop to make it a best-effort read.
+// starting at the file's current position.
+//
+// The return value specifies the number of bytes read or |-1| if there was
+// an error. Note that this function does NOT make a best effort to read all
+// data on all platforms; rather, it just reads however many bytes are quickly
+// available. However, this function can be run in a loop to make it a
+// best-effort read.
+//
+// |file|: The SbFile from which to read data.
+// |data|: The variable to which data is read.
+// |size|: The amount of data (in bytes) to read.
 SB_EXPORT int SbFileRead(SbFile file, char* data, int size);
 
 // Writes the given buffer into |file| at the file's current position,
-// overwritting any data that was previously there. Returns the number of bytes
-// written, or -1 on error. Note that this function does NOT make a best effort
-// to write all data, it writes however many bytes can be written quickly. It
-// should be run in a loop to ensure all data is written.
+// overwriting any data that was previously there.
+//
+// The return value identifies the number of bytes written, or |-1| on error.
+// Note that this function does NOT make a best effort to write all data;
+// rather, it writes however many bytes can be written quickly. Generally, this
+// means that it writes however many bytes as possible without blocking on IO.
+// Run this function in a loop to ensure that all data is written.
+//
+// |file|: The SbFile to which data will be written.
+// |data|: The data to be written.
+// |size|: The amount of data (in bytes) to write.
 SB_EXPORT int SbFileWrite(SbFile file, const char* data, int size);
 
-// Truncates the given |file| to the given |length|. If length is greater than
-// the current size of the file, the file is extended with zeros. Negative
-// |length| will do nothing and return false.
+// Truncates the given |file| to the given |length|. The return value indicates
+// whether the file was truncated successfully.
+//
+// |file|: The file to be truncated.
+// |length|: The expected length of the file after it is truncated. If |length|
+//   is greater than the current size of the file, then the file is extended
+//   with zeros. If |length| is negative, then the function is a no-op and
+//   returns |false|.
 SB_EXPORT bool SbFileTruncate(SbFile file, int64_t length);
 
-// Flushes the write buffer to |file|. Data written via SbFileWrite isn't
-// necessarily comitted right away until the file is flushed or closed.
+// Flushes the write buffer to |file|. Data written via SbFileWrite is not
+// necessarily committed until the SbFile is flushed or closed.
+//
+// |file|: The SbFile to which the write buffer is flushed.
 SB_EXPORT bool SbFileFlush(SbFile file);
 
-// Places some information about |file|, an open SbFile, in |out_info|. Returns
-// |true| if successful. If unsuccessful, |out_info| is untouched.
+// Retrieves information about |file|. The return value indicates whether the
+// file information was retrieved successfully.
+//
+// |file|: The SbFile for which information is retrieved.
+// |out_info|: The variable into which the retrieved data is placed. This
+//   variable is not touched if the operation is not successful.
 SB_EXPORT bool SbFileGetInfo(SbFile file, SbFileInfo* out_info);
 
-// Places information about the file or directory at |path|, which must be
-// absolute, into |out_info|. Returns |true| if successful. If unsuccessful,
-// |out_info| is untouched.
+// Retrieves information about the file at |path|. The return value indicates
+// whether the file information was retrieved successfully.
+//
+// |file|: The absolute path of the file for which information is retrieved.
+// |out_info|: The variable into which the retrieved data is placed. This
+//   variable is not touched if the operation is not successful.
 SB_EXPORT bool SbFileGetPathInfo(const char* path, SbFileInfo* out_info);
 
-// Deletes the regular file, symlink, or empty directory at |path|, which must
-// be absolute. Used mainly to clean up after unit tests. May fail on some
-// platforms if the file in question is being held open.
+// Deletes the regular file, symlink, or empty directory at |path|. This
+// function is used primarily to clean up after unit tests. On some platforms,
+// this function fails if the file in question is being held open.
+//
+// |path|: The absolute path fo the file, symlink, or directory to be deleted.
 SB_EXPORT bool SbFileDelete(const char* path);
 
-// Returns whether a file or directory exists at |path|, which must be absolute.
+// Indicates whether a file or directory exists at |path|.
+//
+// |path|: The absolute path of the file or directory being checked.
 SB_EXPORT bool SbFileExists(const char* path);
 
-// Returns whether SbFileOpen() with the given |flags| is allowed for |path|,
-// which must be absolute.
+// Indicates whether SbFileOpen() with the given |flags| is allowed for |path|.
+//
+// |path|: The absolute path to be checked.
+// |flags|: The flags that are being evaluated for the given |path|.
 SB_EXPORT bool SbFileCanOpen(const char* path, int flags);
 
-// Converts an ISO fopen() mode string into flags that can be equivalently
+// Converts an ISO |fopen()| mode string into flags that can be equivalently
 // passed into SbFileOpen().
+//
+// |mode|: The mode string to be converted into flags.
 SB_EXPORT int SbFileModeStringToFlags(const char* mode);
 
-// Reads the given number of bytes (or until EOF is reached). Returns the number
-// of bytes read, or -1 on error. Note that this function makes a best effort to
-// read all data on all platforms, so it is not intended for stream oriented
-// files but instead for cases when the normal expectation is that actually
-// |size| bytes are read unless there is an error.
+// Reads |size| bytes (or until EOF is reached) from |file| into |data|,
+// starting from the beginning of the file.
+//
+// The return value specifies the number of bytes read or |-1| if there was
+// an error. Note that, unlike |SbFileRead|, this function does make a best
+// effort to read all data on all platforms. As such, it is not intended for
+// stream-oriented files but instead for cases when the normal expectation is
+// that |size| bytes can be read unless there is an error.
+//
+// |file|: The SbFile from which to read data.
+// |data|: The variable to which data is read.
+// |size|: The amount of data (in bytes) to read.
 static inline int SbFileReadAll(SbFile file, char* data, int size) {
   if (!SbFileIsValid(file) || size < 0) {
     return -1;
@@ -204,9 +281,15 @@
   return bytes_read ? bytes_read : rv;
 }
 
-// Writes the given buffer into the file, overwritting any data that was
-// previously there. Returns the number of bytes written, or -1 on error. Note
-// that this function makes a best effort to write all data on all platforms.
+// Writes the given buffer into |file|, starting at the beginning of the file,
+// and overwriting any data that was previously there. Unlike SbFileWrite, this
+// function does make a best effort to write all data on all platforms.
+//
+// The return value identifies the number of bytes written, or |-1| on error.
+//
+// |file|: The file to which data will be written.
+// |data|: The data to be written.
+// |size|: The amount of data (in bytes) to write.
 static inline int SbFileWriteAll(SbFile file, const char* data, int size) {
   if (!SbFileIsValid(file) || size < 0) {
     return -1;
@@ -287,7 +370,7 @@
 
   int64_t GetSize() const {
     SbFileInfo file_info;
-    static bool success = GetInfo(&file_info);
+    bool success = GetInfo(&file_info);
     return (success ? file_info.size : -1);
   }
 
diff --git a/src/starboard/image.h b/src/starboard/image.h
new file mode 100644
index 0000000..5ff6e3f
--- /dev/null
+++ b/src/starboard/image.h
@@ -0,0 +1,102 @@
+// 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.
+
+// Module Overview: Starboard Image Decoding Module
+//
+// API for hardware accelerated image decoding. This module allows for the
+// client to feed in raw, encoded data to be decoded directly into an
+// SbDecodeTarget.  It also provides an interface for the client to query what
+// combinations of encoded image formats and SbDecodeTargetFormats are
+// supported or not.
+//
+// All functions in this module are safe to call from any thread at any point
+// in time.
+//
+// #### SbImageIsDecodeSupported and SbImageDecode Example
+//
+// Let's assume that we're on a Blitter platform.
+//
+//     SbDecodeTargetProvider* provider = GetProviderFromSomewhere();
+//     void* data = GetCompressedJPEGFromSomewhere();
+//     int data_size = GetCompressedJPEGSizeFromSomewhere();
+//     const char* mime_type = "image/jpeg";
+//     SbDecodeTargetFormat format = kSbDecodeTargetFormat1PlaneRGBA;
+//
+//     if (!SbImageIsDecodeSupported(mime_type, format)) {
+//       return;
+//     }
+//
+//     SbDecodeTarget result_target = SbDecodeImage(provider, data, data_size,
+//                                                  mime_type, format);
+//     SbBlitterSurface surface =
+//         SbDecodeTargetGetPlane(target, kSbDecodeTargetPlaneRGBA);
+//     // Do stuff with surface...
+//
+
+#ifndef STARBOARD_IMAGE_H_
+#define STARBOARD_IMAGE_H_
+
+#include "starboard/configuration.h"
+#include "starboard/decode_target.h"
+#include "starboard/export.h"
+#include "starboard/types.h"
+
+#if SB_VERSION(3)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Whether the current platform supports hardware accelerated decoding an
+// image of mime type |mime_type| into SbDecodeTargetFormat |format|.  The
+// result of this function must not change over the course of the program,
+// which means that the results of this function may be cached indefinitely.
+SB_EXPORT bool SbImageIsDecodeSupported(const char* mime_type,
+                                        SbDecodeTargetFormat format);
+
+// Attempt to decode encoded |mime_type| image data |data| of size |data_size|
+// into an SbDecodeTarget of SbDecodeFormatType |format|, possibly using
+// SbDecodeTargetProvider |provider|, if it is non-null.  Thus, four following
+// scenarios regarding the provider may happen:
+//
+//   1. The provider is required by the |SbImageDecode| implementation and no
+//      provider is given.  The implementation should gracefully fail by
+//      immediately returning kSbDecodeTargetInvalid.
+//   2. The provider is required and is passed in.  The implementation will
+//      proceed forward, using the SbDecodeTarget from the provider.
+//   3. The provider is not required and is passed in.  The provider will NOT be
+//      called, and the implementation will proceed to decoding however it
+//      desires.
+//   4. The provider is not required and is not passed in.  The implementation
+//      will proceed forward.
+//
+// Thus, it is NOT safe for clients of this API to assume that the |provider|
+// it passes in will be called.  Finally, if the decode succeeds, a new
+// SbDecodeTarget will be allocated. If |mime_type| image decoding for the
+// requested format is not supported or the decode fails,
+// kSbDecodeTargetInvalid will be returned, with any intermediate allocations
+// being cleaned up in the implementation.
+SB_EXPORT SbDecodeTarget SbImageDecode(SbDecodeTargetProvider* provider,
+                                       void* data,
+                                       int data_size,
+                                       const char* mime_type,
+                                       SbDecodeTargetFormat format);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // SB_VERSION(3)
+
+#endif  // STARBOARD_IMAGE_H_
diff --git a/src/starboard/input.h b/src/starboard/input.h
index fbce0f2..e8f98b2 100644
--- a/src/starboard/input.h
+++ b/src/starboard/input.h
@@ -12,7 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Definition of input events and associated data types.
+// Module Overview: Starboard Input module
+//
+// Defines input events and associated data types.
 
 #ifndef STARBOARD_INPUT_H_
 #define STARBOARD_INPUT_H_
@@ -27,57 +29,58 @@
 extern "C" {
 #endif
 
-// All possible input subsystem types.
+// Identifies possible input subsystem types. The types of events that each
+// device type produces correspond to |SbInputEventType| values.
 typedef enum SbInputDeviceType {
-  // Input from some gesture-detection mechanism. Examples include Kinect,
+  // Input from a gesture-detection mechanism. Examples include Kinect,
   // Wiimotes, LG Magic Remotes, etc...
   //
-  // Produces Move, Grab, Ungrab, Press and Unpress events.
+  // Produces |Move|, |Grab|, |Ungrab|, |Press| and |Unpress| events.
   kSbInputDeviceTypeGesture,
 
   // Input from a gamepad, following the layout provided in the W3C Web Gamepad
-  // API.
+  // API. [https://www.w3.org/TR/gamepad/]
   //
-  // Produces Move, Press and Unpress events.
+  // Produces |Move|, |Press| and |Unpress| events.
   kSbInputDeviceTypeGamepad,
 
-  // Keyboard input from a traditional keyboard, or game controller chatpad.
+  // Keyboard input from a traditional keyboard or game controller chatpad.
   //
-  // Produces Press and Unpress events.
+  // Produces |Press| and |Unpress| events.
   kSbInputDeviceTypeKeyboard,
 
   // Input from a microphone that would provide audio data to the caller, who
   // may then find some way to detect speech or other sounds within it. It may
   // have processed or filtered the audio in some way before it arrives.
   //
-  // Produces Audio events.
+  // Produces |Audio| events.
   kSbInputDeviceTypeMicrophone,
 
   // Input from a traditional mouse.
   //
-  // Produces Move, Press, and Unpress events.
+  // Produces |Move|, |Press|, and |Unpress| events.
   kSbInputDeviceTypeMouse,
 
-  // Input from a TV remote control-style device.
+  // Input from a TV remote-control-style device.
   //
-  // Produces Press and Unpress events.
+  // Produces |Press| and |Unpress| events.
   kSbInputDeviceTypeRemote,
 
   // Input from a speech command analyzer, which is some hardware or software
   // that, given a set of known phrases, activates when one of the registered
   // phrases is heard.
   //
-  // Produces Command events.
+  // Produces |Command| events.
   kSbInputDeviceTypeSpeechCommand,
 
   // Input from a single- or multi-touchscreen.
   //
-  // Produces Move, Press, and Unpress events.
+  // Produces |Move|, |Press|, and |Unpress| events.
   kSbInputDeviceTypeTouchScreen,
 
-  // Input from a touchpad that isn't masquerading as a mouse.
+  // Input from a touchpad that is not masquerading as a mouse.
   //
-  // Produces Move, Press, and Unpress events.
+  // Produces |Move|, |Press|, and |Unpress| events.
   kSbInputDeviceTypeTouchPad,
 } SbInputDeviceType;
 
@@ -90,28 +93,26 @@
   // like a speech recognizer.
   kSbInputEventTypeCommand,
 
-  // Grab activation. In some gesture systems a grab gesture is dfferent from an
-  // activate gesture. An Ungrab event will follow when the grab gesture is
-  // terminated.
+  // Grab activation. This event type is deprecated.
   kSbInputEventTypeGrab,
 
-  // Device Movement. In the case of Mouse, and perhaps Gesture, the movement
-  // tracks an absolute cursor position. In the case of TouchPad, only relative
-  // movements are provided.
+  // Device Movement. In the case of |Mouse|, and perhaps |Gesture|, the
+  // movement tracks an absolute cursor position. In the case of |TouchPad|,
+  // only relative movements are provided.
   kSbInputEventTypeMove,
 
-  // Key or button press activation. This could be a key on a keyboard, a button
-  // on a mouse or game controller, or a push from a touch screen or gesture. An
-  // Unpress event will be delivered once the key/button/finger is
-  // raised. Injecting repeat presses is up to the client.
+  // Key or button press activation. This could be a key on a keyboard, a
+  // button on a mouse or game controller, a push from a touch screen, or
+  // a gesture. An |Unpress| event is subsequently delivered when the
+  // |Press| event terminates, such as when the key/button/finger is raised.
+  // Injecting repeat presses is up to the client.
   kSbInputEventTypePress,
 
-  // Grab deactivation. An Ungrab event will be sent when a grab gesture is
-  // terminated.
+  // Grab deactivation. This event type is deprecated.
   kSbInputEventTypeUngrab,
 
-  // Key or button deactivation. The counterpart to the Press event, this event
-  // is sent when the key or button being pressed is released.
+  // Key or button deactivation. The counterpart to the |Press| event, this
+  // event is sent when the key or button being pressed is released.
   kSbInputEventTypeUnpress,
 } SbInputEventType;
 
@@ -121,42 +122,44 @@
   int y;
 } SbInputVector;
 
-// Event data for kSbEventTypeInput events.
+// Event data for |kSbEventTypeInput| events.
 typedef struct SbInputData {
-  // The window that this input was generated at.
+  // The window in which the input was generated.
   SbWindow window;
 
-  // The type of input event this represents.
+  // The type of input event that this represents.
   SbInputEventType type;
 
   // The type of device that generated this input event.
   SbInputDeviceType device_type;
 
-  // An identifier unique amongst all connected devices.
+  // An identifier that is unique among all connected devices.
   int device_id;
 
   // An identifier that indicates which keyboard key or mouse button was
   // involved in this event, if any. All known keys for all devices are mapped
-  // to a single ID space, defined by the enum SbKey in key.h.
+  // to a single ID space, defined by the |SbKey| enum in |key.h|.
   SbKey key;
 
   // The character that corresponds to the key. For an external keyboard, this
-  // character also depends on the language of keyboard type. Will be 0 if there
+  // character also depends on the keyboard language. The value is |0| if there
   // is no corresponding character.
   wchar_t character;
 
   // The location of the specified key, in cases where there are multiple
-  // instances of the button on the keyboard. The "shift" key, for example.
+  // instances of the button on the keyboard. For example, some keyboards
+  // have more than one "shift" key.
   SbKeyLocation key_location;
 
-  // Key modifiers (e.g. Ctrl, Chift) held down during this input event.
+  // Key modifiers (e.g. |Ctrl|, |Shift|) held down during this input event.
   unsigned int key_modifiers;
 
   // The (x, y) coordinates of the persistent cursor controlled by this
-  // device. Will be 0 if not applicable.
+  // device. The value is |0| if this data is not applicable.
   SbInputVector position;
 
-  // The relative motion vector of this input. Will be 0 if not applicable.
+  // The relative motion vector of this input. The value is |0| if this data
+  // is not applicable.
   SbInputVector delta;
 } SbInputData;
 
diff --git a/src/starboard/key.h b/src/starboard/key.h
index 05f05d9..b50608f 100644
--- a/src/starboard/key.h
+++ b/src/starboard/key.h
@@ -12,7 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// The canonical set of Starboard key codes.
+// Module Overview: Starboard Key module
+//
+// Defines the canonical set of Starboard key codes.
 
 #ifndef STARBOARD_KEY_H_
 #define STARBOARD_KEY_H_
@@ -21,17 +23,16 @@
 extern "C" {
 #endif
 
-// A standard set of key codes representing each possible input key across all
-// kinds of devices, we use the semi-standard Windows virtual key codes.
-//
-// Windows virtual key codes doc:
+// A standard set of key codes, ordered by value, that represent each possible
+// input key across all kinds of devices. Starboard uses the semi-standard
+// Windows virtual key codes documented at:
 //   https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx
-//
-// The order here is by value.
 typedef enum SbKey {
   kSbKeyUnknown = 0,
   kSbKeyCancel = 0x03,
-  kSbKeyBack = 0x08,
+  kSbKeyBackspace = 0x08,
+  kSbKeyBack = kSbKeyBackspace,  // You probably want kSbKeyEscape for a
+                                 // semantic "back".
   kSbKeyTab = 0x09,
   kSbKeyBacktab = 0x0A,
   kSbKeyClear = 0x0C,
diff --git a/src/starboard/linux/shared/configuration_public.h b/src/starboard/linux/shared/configuration_public.h
index b374b00..afd4574 100644
--- a/src/starboard/linux/shared/configuration_public.h
+++ b/src/starboard/linux/shared/configuration_public.h
@@ -24,7 +24,7 @@
 #define STARBOARD_LINUX_SHARED_CONFIGURATION_PUBLIC_H_
 
 #ifndef SB_API_VERSION
-#define SB_API_VERSION 1
+#define SB_API_VERSION 2
 #endif
 
 // --- System Header Configuration -------------------------------------------
@@ -56,6 +56,12 @@
 // Whether the current platform provides the standard header float.h.
 #define SB_HAS_FLOAT_H 1
 
+// Whether the current platform has microphone supported.
+#define SB_HAS_MICROPHONE 0
+
+// Whether the current platform has speech synthesis.
+#define SB_HAS_SPEECH_SYNTHESIS 0
+
 // Type detection for wchar_t.
 #if defined(__WCHAR_MAX__) && \
     (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff)
@@ -375,6 +381,12 @@
 // The maximum number of users that can be signed in at the same time.
 #define SB_USER_MAX_SIGNED_IN 1
 
+// --- Timing API ------------------------------------------------------------
+
+// Whether this platform has an API to retrieve how long the current thread
+// has spent in the executing state.
+#define SB_HAS_TIME_THREAD_NOW 1
+
 // --- Platform Specific Audits ----------------------------------------------
 
 #if !defined(__GNUC__)
diff --git a/src/starboard/linux/shared/starboard_base_symbolize.gyp b/src/starboard/linux/shared/starboard_base_symbolize.gyp
new file mode 100644
index 0000000..5cd3440
--- /dev/null
+++ b/src/starboard/linux/shared/starboard_base_symbolize.gyp
@@ -0,0 +1,25 @@
+# Copyright 2016 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+{
+  'targets': [
+    {
+      'target_name': 'starboard_base_symbolize',
+      'type': 'static_library',
+      'sources': [
+        '<(DEPTH)/base/third_party/symbolize/demangle.cc',
+        '<(DEPTH)/base/third_party/symbolize/symbolize.cc',
+      ],
+    },
+  ],
+}
diff --git a/src/starboard/linux/shared/starboard_platform.gypi b/src/starboard/linux/shared/starboard_platform.gypi
new file mode 100644
index 0000000..1030459
--- /dev/null
+++ b/src/starboard/linux/shared/starboard_platform.gypi
@@ -0,0 +1,281 @@
+# Copyright 2016 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+{
+  'variables': {
+    'starboard_platform_sources': [
+      '<(DEPTH)/starboard/linux/shared/atomic_public.h',
+      '<(DEPTH)/starboard/linux/shared/configuration_public.h',
+      '<(DEPTH)/starboard/linux/shared/system_get_connection_type.cc',
+      '<(DEPTH)/starboard/linux/shared/system_get_device_type.cc',
+      '<(DEPTH)/starboard/linux/shared/system_get_path.cc',
+      '<(DEPTH)/starboard/linux/shared/system_has_capability.cc',
+      '<(DEPTH)/starboard/shared/alsa/alsa_audio_sink_type.cc',
+      '<(DEPTH)/starboard/shared/alsa/alsa_audio_sink_type.h',
+      '<(DEPTH)/starboard/shared/alsa/alsa_util.cc',
+      '<(DEPTH)/starboard/shared/alsa/alsa_util.h',
+      '<(DEPTH)/starboard/shared/alsa/audio_sink_get_max_channels.cc',
+      '<(DEPTH)/starboard/shared/alsa/audio_sink_get_nearest_supported_sample_frequency.cc',
+      '<(DEPTH)/starboard/shared/alsa/audio_sink_is_audio_frame_storage_type_supported.cc',
+      '<(DEPTH)/starboard/shared/alsa/audio_sink_is_audio_sample_type_supported.cc',
+      '<(DEPTH)/starboard/shared/dlmalloc/memory_allocate_aligned_unchecked.cc',
+      '<(DEPTH)/starboard/shared/dlmalloc/memory_allocate_unchecked.cc',
+      '<(DEPTH)/starboard/shared/dlmalloc/memory_free.cc',
+      '<(DEPTH)/starboard/shared/dlmalloc/memory_free_aligned.cc',
+      '<(DEPTH)/starboard/shared/dlmalloc/memory_map.cc',
+      '<(DEPTH)/starboard/shared/dlmalloc/memory_reallocate_unchecked.cc',
+      '<(DEPTH)/starboard/shared/dlmalloc/memory_unmap.cc',
+      '<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc',
+      '<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_audio_decoder.h',
+      '<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_common.cc',
+      '<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_common.h',
+      '<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc',
+      '<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_video_decoder.h',
+      '<(DEPTH)/starboard/shared/gcc/atomic_gcc_public.h',
+      '<(DEPTH)/starboard/shared/iso/character_is_alphanumeric.cc',
+      '<(DEPTH)/starboard/shared/iso/character_is_digit.cc',
+      '<(DEPTH)/starboard/shared/iso/character_is_hex_digit.cc',
+      '<(DEPTH)/starboard/shared/iso/character_is_space.cc',
+      '<(DEPTH)/starboard/shared/iso/character_is_upper.cc',
+      '<(DEPTH)/starboard/shared/iso/character_to_lower.cc',
+      '<(DEPTH)/starboard/shared/iso/character_to_upper.cc',
+      '<(DEPTH)/starboard/shared/iso/directory_close.cc',
+      '<(DEPTH)/starboard/shared/iso/directory_get_next.cc',
+      '<(DEPTH)/starboard/shared/iso/directory_open.cc',
+      '<(DEPTH)/starboard/shared/iso/double_absolute.cc',
+      '<(DEPTH)/starboard/shared/iso/double_exponent.cc',
+      '<(DEPTH)/starboard/shared/iso/double_floor.cc',
+      '<(DEPTH)/starboard/shared/iso/double_is_finite.cc',
+      '<(DEPTH)/starboard/shared/iso/double_is_nan.cc',
+      '<(DEPTH)/starboard/shared/iso/memory_compare.cc',
+      '<(DEPTH)/starboard/shared/iso/memory_copy.cc',
+      '<(DEPTH)/starboard/shared/iso/memory_find_byte.cc',
+      '<(DEPTH)/starboard/shared/iso/memory_move.cc',
+      '<(DEPTH)/starboard/shared/iso/memory_set.cc',
+      '<(DEPTH)/starboard/shared/iso/string_compare.cc',
+      '<(DEPTH)/starboard/shared/iso/string_compare_all.cc',
+      '<(DEPTH)/starboard/shared/iso/string_find_character.cc',
+      '<(DEPTH)/starboard/shared/iso/string_find_last_character.cc',
+      '<(DEPTH)/starboard/shared/iso/string_find_string.cc',
+      '<(DEPTH)/starboard/shared/iso/string_get_length.cc',
+      '<(DEPTH)/starboard/shared/iso/string_get_length_wide.cc',
+      '<(DEPTH)/starboard/shared/iso/string_parse_double.cc',
+      '<(DEPTH)/starboard/shared/iso/string_parse_signed_integer.cc',
+      '<(DEPTH)/starboard/shared/iso/string_parse_uint64.cc',
+      '<(DEPTH)/starboard/shared/iso/string_parse_unsigned_integer.cc',
+      '<(DEPTH)/starboard/shared/iso/string_scan.cc',
+      '<(DEPTH)/starboard/shared/iso/system_binary_search.cc',
+      '<(DEPTH)/starboard/shared/iso/system_sort.cc',
+      '<(DEPTH)/starboard/shared/libevent/socket_waiter_add.cc',
+      '<(DEPTH)/starboard/shared/libevent/socket_waiter_create.cc',
+      '<(DEPTH)/starboard/shared/libevent/socket_waiter_destroy.cc',
+      '<(DEPTH)/starboard/shared/libevent/socket_waiter_internal.cc',
+      '<(DEPTH)/starboard/shared/libevent/socket_waiter_remove.cc',
+      '<(DEPTH)/starboard/shared/libevent/socket_waiter_wait.cc',
+      '<(DEPTH)/starboard/shared/libevent/socket_waiter_wait_timed.cc',
+      '<(DEPTH)/starboard/shared/libevent/socket_waiter_wake_up.cc',
+      '<(DEPTH)/starboard/shared/linux/byte_swap.cc',
+      '<(DEPTH)/starboard/shared/linux/get_home_directory.cc',
+      '<(DEPTH)/starboard/shared/linux/memory_get_stack_bounds.cc',
+      '<(DEPTH)/starboard/shared/linux/page_internal.cc',
+      '<(DEPTH)/starboard/shared/linux/socket_get_local_interface_address.cc',
+      '<(DEPTH)/starboard/shared/linux/system_get_random_data.cc',
+      '<(DEPTH)/starboard/shared/linux/system_get_stack.cc',
+      '<(DEPTH)/starboard/shared/linux/system_get_total_cpu_memory.cc',
+      '<(DEPTH)/starboard/shared/linux/system_get_used_cpu_memory.cc',
+      '<(DEPTH)/starboard/shared/linux/system_is_debugger_attached.cc',
+      '<(DEPTH)/starboard/shared/linux/system_symbolize.cc',
+      '<(DEPTH)/starboard/shared/linux/thread_get_id.cc',
+      '<(DEPTH)/starboard/shared/linux/thread_get_name.cc',
+      '<(DEPTH)/starboard/shared/linux/thread_set_name.cc',
+      '<(DEPTH)/starboard/shared/nouser/user_get_current.cc',
+      '<(DEPTH)/starboard/shared/nouser/user_get_property.cc',
+      '<(DEPTH)/starboard/shared/nouser/user_get_signed_in.cc',
+      '<(DEPTH)/starboard/shared/nouser/user_internal.cc',
+      '<(DEPTH)/starboard/shared/posix/directory_create.cc',
+      '<(DEPTH)/starboard/shared/posix/file_can_open.cc',
+      '<(DEPTH)/starboard/shared/posix/file_close.cc',
+      '<(DEPTH)/starboard/shared/posix/file_delete.cc',
+      '<(DEPTH)/starboard/shared/posix/file_exists.cc',
+      '<(DEPTH)/starboard/shared/posix/file_flush.cc',
+      '<(DEPTH)/starboard/shared/posix/file_get_info.cc',
+      '<(DEPTH)/starboard/shared/posix/file_get_path_info.cc',
+      '<(DEPTH)/starboard/shared/posix/file_open.cc',
+      '<(DEPTH)/starboard/shared/posix/file_read.cc',
+      '<(DEPTH)/starboard/shared/posix/file_seek.cc',
+      '<(DEPTH)/starboard/shared/posix/file_truncate.cc',
+      '<(DEPTH)/starboard/shared/posix/file_write.cc',
+      '<(DEPTH)/starboard/shared/posix/log.cc',
+      '<(DEPTH)/starboard/shared/posix/log_flush.cc',
+      '<(DEPTH)/starboard/shared/posix/log_format.cc',
+      '<(DEPTH)/starboard/shared/posix/log_is_tty.cc',
+      '<(DEPTH)/starboard/shared/posix/log_raw.cc',
+      '<(DEPTH)/starboard/shared/posix/memory_flush.cc',
+      '<(DEPTH)/starboard/shared/posix/set_non_blocking_internal.cc',
+      '<(DEPTH)/starboard/shared/posix/socket_accept.cc',
+      '<(DEPTH)/starboard/shared/posix/socket_bind.cc',
+      '<(DEPTH)/starboard/shared/posix/socket_clear_last_error.cc',
+      '<(DEPTH)/starboard/shared/posix/socket_connect.cc',
+      '<(DEPTH)/starboard/shared/posix/socket_create.cc',
+      '<(DEPTH)/starboard/shared/posix/socket_destroy.cc',
+      '<(DEPTH)/starboard/shared/posix/socket_free_resolution.cc',
+      '<(DEPTH)/starboard/shared/posix/socket_get_last_error.cc',
+      '<(DEPTH)/starboard/shared/posix/socket_get_local_address.cc',
+      '<(DEPTH)/starboard/shared/posix/socket_internal.cc',
+      '<(DEPTH)/starboard/shared/posix/socket_is_connected.cc',
+      '<(DEPTH)/starboard/shared/posix/socket_is_connected_and_idle.cc',
+      '<(DEPTH)/starboard/shared/posix/socket_join_multicast_group.cc',
+      '<(DEPTH)/starboard/shared/posix/socket_listen.cc',
+      '<(DEPTH)/starboard/shared/posix/socket_receive_from.cc',
+      '<(DEPTH)/starboard/shared/posix/socket_resolve.cc',
+      '<(DEPTH)/starboard/shared/posix/socket_send_to.cc',
+      '<(DEPTH)/starboard/shared/posix/socket_set_broadcast.cc',
+      '<(DEPTH)/starboard/shared/posix/socket_set_receive_buffer_size.cc',
+      '<(DEPTH)/starboard/shared/posix/socket_set_reuse_address.cc',
+      '<(DEPTH)/starboard/shared/posix/socket_set_send_buffer_size.cc',
+      '<(DEPTH)/starboard/shared/posix/socket_set_tcp_keep_alive.cc',
+      '<(DEPTH)/starboard/shared/posix/socket_set_tcp_no_delay.cc',
+      '<(DEPTH)/starboard/shared/posix/socket_set_tcp_window_scaling.cc',
+      '<(DEPTH)/starboard/shared/posix/string_compare_no_case.cc',
+      '<(DEPTH)/starboard/shared/posix/string_compare_no_case_n.cc',
+      '<(DEPTH)/starboard/shared/posix/string_compare_wide.cc',
+      '<(DEPTH)/starboard/shared/posix/string_format.cc',
+      '<(DEPTH)/starboard/shared/posix/string_format_wide.cc',
+      '<(DEPTH)/starboard/shared/posix/system_break_into_debugger.cc',
+      '<(DEPTH)/starboard/shared/posix/system_clear_last_error.cc',
+      '<(DEPTH)/starboard/shared/posix/system_get_error_string.cc',
+      '<(DEPTH)/starboard/shared/posix/system_get_last_error.cc',
+      '<(DEPTH)/starboard/shared/posix/system_get_locale_id.cc',
+      '<(DEPTH)/starboard/shared/posix/system_get_number_of_processors.cc',
+      '<(DEPTH)/starboard/shared/posix/thread_sleep.cc',
+      '<(DEPTH)/starboard/shared/posix/time_get_monotonic_now.cc',
+      '<(DEPTH)/starboard/shared/posix/time_get_monotonic_thread_now.cc',
+      '<(DEPTH)/starboard/shared/posix/time_get_now.cc',
+      '<(DEPTH)/starboard/shared/posix/time_zone_get_current.cc',
+      '<(DEPTH)/starboard/shared/posix/time_zone_get_dst_name.cc',
+      '<(DEPTH)/starboard/shared/posix/time_zone_get_name.cc',
+      '<(DEPTH)/starboard/shared/pthread/condition_variable_broadcast.cc',
+      '<(DEPTH)/starboard/shared/pthread/condition_variable_create.cc',
+      '<(DEPTH)/starboard/shared/pthread/condition_variable_destroy.cc',
+      '<(DEPTH)/starboard/shared/pthread/condition_variable_signal.cc',
+      '<(DEPTH)/starboard/shared/pthread/condition_variable_wait.cc',
+      '<(DEPTH)/starboard/shared/pthread/condition_variable_wait_timed.cc',
+      '<(DEPTH)/starboard/shared/pthread/mutex_acquire.cc',
+      '<(DEPTH)/starboard/shared/pthread/mutex_acquire_try.cc',
+      '<(DEPTH)/starboard/shared/pthread/mutex_create.cc',
+      '<(DEPTH)/starboard/shared/pthread/mutex_destroy.cc',
+      '<(DEPTH)/starboard/shared/pthread/mutex_release.cc',
+      '<(DEPTH)/starboard/shared/pthread/once.cc',
+      '<(DEPTH)/starboard/shared/pthread/thread_create.cc',
+      '<(DEPTH)/starboard/shared/pthread/thread_create_local_key.cc',
+      '<(DEPTH)/starboard/shared/pthread/thread_destroy_local_key.cc',
+      '<(DEPTH)/starboard/shared/pthread/thread_detach.cc',
+      '<(DEPTH)/starboard/shared/pthread/thread_get_current.cc',
+      '<(DEPTH)/starboard/shared/pthread/thread_get_local_value.cc',
+      '<(DEPTH)/starboard/shared/pthread/thread_is_equal.cc',
+      '<(DEPTH)/starboard/shared/pthread/thread_join.cc',
+      '<(DEPTH)/starboard/shared/pthread/thread_set_local_value.cc',
+      '<(DEPTH)/starboard/shared/pthread/thread_yield.cc',
+      '<(DEPTH)/starboard/shared/signal/crash_signals.h',
+      '<(DEPTH)/starboard/shared/signal/crash_signals_sigaction.cc',
+      '<(DEPTH)/starboard/shared/signal/suspend_signals.cc',
+      '<(DEPTH)/starboard/shared/signal/suspend_signals.h',
+      '<(DEPTH)/starboard/shared/starboard/application.cc',
+      '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_create.cc',
+      '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_destroy.cc',
+      '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_internal.cc',
+      '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_internal.h',
+      '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_is_valid.cc',
+      '<(DEPTH)/starboard/shared/starboard/audio_sink/stub_audio_sink_type.cc',
+      '<(DEPTH)/starboard/shared/starboard/audio_sink/stub_audio_sink_type.h',
+      '<(DEPTH)/starboard/shared/starboard/directory_can_open.cc',
+      '<(DEPTH)/starboard/shared/starboard/event_cancel.cc',
+      '<(DEPTH)/starboard/shared/starboard/event_schedule.cc',
+      '<(DEPTH)/starboard/shared/starboard/file_mode_string_to_flags.cc',
+      '<(DEPTH)/starboard/shared/starboard/file_storage/storage_close_record.cc',
+      '<(DEPTH)/starboard/shared/starboard/file_storage/storage_delete_record.cc',
+      '<(DEPTH)/starboard/shared/starboard/file_storage/storage_get_record_size.cc',
+      '<(DEPTH)/starboard/shared/starboard/file_storage/storage_open_record.cc',
+      '<(DEPTH)/starboard/shared/starboard/file_storage/storage_read_record.cc',
+      '<(DEPTH)/starboard/shared/starboard/file_storage/storage_write_record.cc',
+      '<(DEPTH)/starboard/shared/starboard/log_message.cc',
+      '<(DEPTH)/starboard/shared/starboard/log_raw_dump_stack.cc',
+      '<(DEPTH)/starboard/shared/starboard/log_raw_format.cc',
+      '<(DEPTH)/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc',
+      '<(DEPTH)/starboard/shared/starboard/media/media_is_output_protected.cc',
+      '<(DEPTH)/starboard/shared/starboard/media/media_set_output_protection.cc',
+      '<(DEPTH)/starboard/shared/starboard/media/mime_type.cc',
+      '<(DEPTH)/starboard/shared/starboard/media/mime_type.h',
+      '<(DEPTH)/starboard/shared/starboard/new.cc',
+      '<(DEPTH)/starboard/shared/starboard/player/filter/audio_decoder_internal.h',
+      '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_internal.cc',
+      '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_internal.h',
+      '<(DEPTH)/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc',
+      '<(DEPTH)/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.h',
+      '<(DEPTH)/starboard/shared/starboard/player/filter/video_decoder_internal.h',
+      '<(DEPTH)/starboard/shared/starboard/player/filter/video_renderer_internal.cc',
+      '<(DEPTH)/starboard/shared/starboard/player/filter/video_renderer_internal.h',
+      '<(DEPTH)/starboard/shared/starboard/player/input_buffer_internal.cc',
+      '<(DEPTH)/starboard/shared/starboard/player/input_buffer_internal.h',
+      '<(DEPTH)/starboard/shared/starboard/player/player_create.cc',
+      '<(DEPTH)/starboard/shared/starboard/player/player_destroy.cc',
+      '<(DEPTH)/starboard/shared/starboard/player/player_get_info.cc',
+      '<(DEPTH)/starboard/shared/starboard/player/player_internal.cc',
+      '<(DEPTH)/starboard/shared/starboard/player/player_internal.h',
+      '<(DEPTH)/starboard/shared/starboard/player/player_seek.cc',
+      '<(DEPTH)/starboard/shared/starboard/player/player_set_bounds.cc',
+      '<(DEPTH)/starboard/shared/starboard/player/player_set_pause.cc',
+      '<(DEPTH)/starboard/shared/starboard/player/player_set_volume.cc',
+      '<(DEPTH)/starboard/shared/starboard/player/player_worker.cc',
+      '<(DEPTH)/starboard/shared/starboard/player/player_worker.h',
+      '<(DEPTH)/starboard/shared/starboard/player/player_write_end_of_stream.cc',
+      '<(DEPTH)/starboard/shared/starboard/player/player_write_sample.cc',
+      '<(DEPTH)/starboard/shared/starboard/player/video_frame_internal.cc',
+      '<(DEPTH)/starboard/shared/starboard/player/video_frame_internal.h',
+      '<(DEPTH)/starboard/shared/starboard/queue_application.cc',
+      '<(DEPTH)/starboard/shared/starboard/string_concat.cc',
+      '<(DEPTH)/starboard/shared/starboard/string_concat_wide.cc',
+      '<(DEPTH)/starboard/shared/starboard/string_copy.cc',
+      '<(DEPTH)/starboard/shared/starboard/string_copy_wide.cc',
+      '<(DEPTH)/starboard/shared/starboard/string_duplicate.cc',
+      '<(DEPTH)/starboard/shared/starboard/system_get_random_uint64.cc',
+      '<(DEPTH)/starboard/shared/starboard/system_request_stop.cc',
+      '<(DEPTH)/starboard/shared/starboard/window_set_default_options.cc',
+      '<(DEPTH)/starboard/shared/stub/drm_close_session.cc',
+      '<(DEPTH)/starboard/shared/stub/drm_create_system.cc',
+      '<(DEPTH)/starboard/shared/stub/drm_destroy_system.cc',
+      '<(DEPTH)/starboard/shared/stub/drm_generate_session_update_request.cc',
+      '<(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/microphone_close.cc',
+      '<(DEPTH)/starboard/shared/stub/microphone_create.cc',
+      '<(DEPTH)/starboard/shared/stub/microphone_destroy.cc',
+      '<(DEPTH)/starboard/shared/stub/microphone_get_available.cc',
+      '<(DEPTH)/starboard/shared/stub/microphone_is_sample_rate_supported.cc',
+      '<(DEPTH)/starboard/shared/stub/microphone_open.cc',
+      '<(DEPTH)/starboard/shared/stub/microphone_read.cc',
+      '<(DEPTH)/starboard/shared/stub/system_clear_platform_error.cc',
+      '<(DEPTH)/starboard/shared/stub/system_get_total_gpu_memory.cc',
+      '<(DEPTH)/starboard/shared/stub/system_get_used_gpu_memory.cc',
+      '<(DEPTH)/starboard/shared/stub/system_hide_splash_screen.cc',
+      '<(DEPTH)/starboard/shared/stub/system_raise_platform_error.cc',
+    ],
+    'starboard_platform_dependencies': [
+      '<(DEPTH)/starboard/common/common.gyp:common',
+      '<(DEPTH)/starboard/linux/shared/starboard_base_symbolize.gyp:starboard_base_symbolize',
+      '<(DEPTH)/third_party/dlmalloc/dlmalloc.gyp:dlmalloc',
+      '<(DEPTH)/third_party/libevent/libevent.gyp:libevent',
+    ],
+  },
+}
diff --git a/src/starboard/linux/x64directfb/configuration_public.h b/src/starboard/linux/x64directfb/configuration_public.h
index c891232..6f91914 100644
--- a/src/starboard/linux/x64directfb/configuration_public.h
+++ b/src/starboard/linux/x64directfb/configuration_public.h
@@ -52,4 +52,8 @@
 #define SB_PREFERRED_RGBA_BYTE_ORDER SB_PREFERRED_RGBA_BYTE_ORDER_BGRA
 #endif
 
+// The current platform has microphone supported.
+#undef SB_HAS_MICROPHONE
+#define SB_HAS_MICROPHONE 1
+
 #endif  // STARBOARD_LINUX_X64DIRECTFB_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64directfb/starboard_platform.gyp b/src/starboard/linux/x64directfb/starboard_platform.gyp
index 2419586..c45f24a 100644
--- a/src/starboard/linux/x64directfb/starboard_platform.gyp
+++ b/src/starboard/linux/x64directfb/starboard_platform.gyp
@@ -12,309 +12,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 {
+  'includes': [
+    'starboard_platform.gypi'
+  ],
   'targets': [
     {
-      'target_name': 'starboard_base_symbolize',
-      'type': 'static_library',
-      'sources': [
-        '<(DEPTH)/base/third_party/symbolize/demangle.cc',
-        '<(DEPTH)/base/third_party/symbolize/symbolize.cc',
-      ],
-    },
-    {
       'target_name': 'starboard_platform',
       'type': 'static_library',
-      'sources': [
-        '<(DEPTH)/starboard/linux/shared/atomic_public.h',
-        '<(DEPTH)/starboard/linux/shared/configuration_public.h',
-        '<(DEPTH)/starboard/linux/shared/system_get_connection_type.cc',
-        '<(DEPTH)/starboard/linux/shared/system_get_device_type.cc',
-        '<(DEPTH)/starboard/linux/shared/system_get_path.cc',
-        '<(DEPTH)/starboard/linux/shared/system_has_capability.cc',
-        '<(DEPTH)/starboard/linux/x64directfb/main.cc',
-        '<(DEPTH)/starboard/linux/x64directfb/system_get_property.cc',
-        '<(DEPTH)/starboard/shared/alsa/alsa_audio_sink_type.cc',
-        '<(DEPTH)/starboard/shared/alsa/alsa_audio_sink_type.h',
-        '<(DEPTH)/starboard/shared/alsa/alsa_util.cc',
-        '<(DEPTH)/starboard/shared/alsa/alsa_util.h',
-        '<(DEPTH)/starboard/shared/alsa/audio_sink_get_max_channels.cc',
-        '<(DEPTH)/starboard/shared/alsa/audio_sink_get_nearest_supported_sample_frequency.cc',
-        '<(DEPTH)/starboard/shared/alsa/audio_sink_is_audio_frame_storage_type_supported.cc',
-        '<(DEPTH)/starboard/shared/alsa/audio_sink_is_audio_sample_type_supported.cc',
-        '<(DEPTH)/starboard/shared/directfb/application_directfb.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_blit_rect_to_rect.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_create_context.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_create_default_device.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_create_pixel_data.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_create_render_target_surface.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_create_surface_from_pixel_data.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_create_swap_chain_from_window.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_destroy_context.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_destroy_device.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_destroy_pixel_data.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_destroy_surface.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_destroy_swap_chain.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_download_surface_pixels.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_fill_rect.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_flip_swap_chain.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_flush_context.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_get_max_contexts.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_get_pixel_data_pitch_in_bytes.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_get_pixel_data_pointer.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_get_render_target_from_surface.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_get_render_target_from_swap_chain.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_get_surface_info.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_internal.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_is_pixel_format_supported_by_download_surface_pixels.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_is_pixel_format_supported_by_pixel_data.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_is_surface_format_supported_by_render_target_surface.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_set_blending.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_set_color.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_set_modulate_blits_with_color.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_set_render_target.cc',
-        '<(DEPTH)/starboard/shared/directfb/blitter_set_scissor.cc',
-        '<(DEPTH)/starboard/shared/directfb/window_create.cc',
-        '<(DEPTH)/starboard/shared/directfb/window_destroy.cc',
-        '<(DEPTH)/starboard/shared/directfb/window_get_platform_handle.cc',
-        '<(DEPTH)/starboard/shared/directfb/window_get_size.cc',
-        '<(DEPTH)/starboard/shared/directfb/window_internal.cc',
-        '<(DEPTH)/starboard/shared/dlmalloc/memory_allocate_aligned_unchecked.cc',
-        '<(DEPTH)/starboard/shared/dlmalloc/memory_allocate_unchecked.cc',
-        '<(DEPTH)/starboard/shared/dlmalloc/memory_free.cc',
-        '<(DEPTH)/starboard/shared/dlmalloc/memory_free_aligned.cc',
-        '<(DEPTH)/starboard/shared/dlmalloc/memory_map.cc',
-        '<(DEPTH)/starboard/shared/dlmalloc/memory_reallocate_unchecked.cc',
-        '<(DEPTH)/starboard/shared/dlmalloc/memory_unmap.cc',
-        '<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc',
-        '<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_audio_decoder.h',
-        '<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_common.cc',
-        '<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_common.h',
-        '<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc',
-        '<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_video_decoder.h',
-        '<(DEPTH)/starboard/shared/gcc/atomic_gcc_public.h',
-        '<(DEPTH)/starboard/shared/iso/character_is_alphanumeric.cc',
-        '<(DEPTH)/starboard/shared/iso/character_is_digit.cc',
-        '<(DEPTH)/starboard/shared/iso/character_is_hex_digit.cc',
-        '<(DEPTH)/starboard/shared/iso/character_is_space.cc',
-        '<(DEPTH)/starboard/shared/iso/character_is_upper.cc',
-        '<(DEPTH)/starboard/shared/iso/character_to_lower.cc',
-        '<(DEPTH)/starboard/shared/iso/character_to_upper.cc',
-        '<(DEPTH)/starboard/shared/iso/directory_close.cc',
-        '<(DEPTH)/starboard/shared/iso/directory_get_next.cc',
-        '<(DEPTH)/starboard/shared/iso/directory_open.cc',
-        '<(DEPTH)/starboard/shared/iso/double_absolute.cc',
-        '<(DEPTH)/starboard/shared/iso/double_exponent.cc',
-        '<(DEPTH)/starboard/shared/iso/double_floor.cc',
-        '<(DEPTH)/starboard/shared/iso/double_is_finite.cc',
-        '<(DEPTH)/starboard/shared/iso/double_is_nan.cc',
-        '<(DEPTH)/starboard/shared/iso/memory_compare.cc',
-        '<(DEPTH)/starboard/shared/iso/memory_copy.cc',
-        '<(DEPTH)/starboard/shared/iso/memory_find_byte.cc',
-        '<(DEPTH)/starboard/shared/iso/memory_move.cc',
-        '<(DEPTH)/starboard/shared/iso/memory_set.cc',
-        '<(DEPTH)/starboard/shared/iso/string_compare.cc',
-        '<(DEPTH)/starboard/shared/iso/string_compare_all.cc',
-        '<(DEPTH)/starboard/shared/iso/string_find_character.cc',
-        '<(DEPTH)/starboard/shared/iso/string_find_last_character.cc',
-        '<(DEPTH)/starboard/shared/iso/string_find_string.cc',
-        '<(DEPTH)/starboard/shared/iso/string_get_length.cc',
-        '<(DEPTH)/starboard/shared/iso/string_get_length_wide.cc',
-        '<(DEPTH)/starboard/shared/iso/string_parse_double.cc',
-        '<(DEPTH)/starboard/shared/iso/string_parse_signed_integer.cc',
-        '<(DEPTH)/starboard/shared/iso/string_parse_uint64.cc',
-        '<(DEPTH)/starboard/shared/iso/string_parse_unsigned_integer.cc',
-        '<(DEPTH)/starboard/shared/iso/string_scan.cc',
-        '<(DEPTH)/starboard/shared/iso/system_binary_search.cc',
-        '<(DEPTH)/starboard/shared/iso/system_sort.cc',
-        '<(DEPTH)/starboard/shared/libevent/socket_waiter_add.cc',
-        '<(DEPTH)/starboard/shared/libevent/socket_waiter_create.cc',
-        '<(DEPTH)/starboard/shared/libevent/socket_waiter_destroy.cc',
-        '<(DEPTH)/starboard/shared/libevent/socket_waiter_internal.cc',
-        '<(DEPTH)/starboard/shared/libevent/socket_waiter_remove.cc',
-        '<(DEPTH)/starboard/shared/libevent/socket_waiter_wait.cc',
-        '<(DEPTH)/starboard/shared/libevent/socket_waiter_wait_timed.cc',
-        '<(DEPTH)/starboard/shared/libevent/socket_waiter_wake_up.cc',
-        '<(DEPTH)/starboard/shared/linux/byte_swap.cc',
-        '<(DEPTH)/starboard/shared/linux/get_home_directory.cc',
-        '<(DEPTH)/starboard/shared/linux/memory_get_stack_bounds.cc',
-        '<(DEPTH)/starboard/shared/linux/page_internal.cc',
-        '<(DEPTH)/starboard/shared/linux/socket_get_local_interface_address.cc',
-        '<(DEPTH)/starboard/shared/linux/system_get_random_data.cc',
-        '<(DEPTH)/starboard/shared/linux/system_get_stack.cc',
-        '<(DEPTH)/starboard/shared/linux/system_get_total_cpu_memory.cc',
-        '<(DEPTH)/starboard/shared/linux/system_get_used_cpu_memory.cc',
-        '<(DEPTH)/starboard/shared/linux/system_is_debugger_attached.cc',
-        '<(DEPTH)/starboard/shared/linux/system_symbolize.cc',
-        '<(DEPTH)/starboard/shared/linux/thread_get_id.cc',
-        '<(DEPTH)/starboard/shared/linux/thread_get_name.cc',
-        '<(DEPTH)/starboard/shared/linux/thread_set_name.cc',
-        '<(DEPTH)/starboard/shared/nouser/user_get_current.cc',
-        '<(DEPTH)/starboard/shared/nouser/user_get_property.cc',
-        '<(DEPTH)/starboard/shared/nouser/user_get_signed_in.cc',
-        '<(DEPTH)/starboard/shared/nouser/user_internal.cc',
-        '<(DEPTH)/starboard/shared/posix/directory_create.cc',
-        '<(DEPTH)/starboard/shared/posix/file_can_open.cc',
-        '<(DEPTH)/starboard/shared/posix/file_close.cc',
-        '<(DEPTH)/starboard/shared/posix/file_delete.cc',
-        '<(DEPTH)/starboard/shared/posix/file_exists.cc',
-        '<(DEPTH)/starboard/shared/posix/file_flush.cc',
-        '<(DEPTH)/starboard/shared/posix/file_get_info.cc',
-        '<(DEPTH)/starboard/shared/posix/file_get_path_info.cc',
-        '<(DEPTH)/starboard/shared/posix/file_open.cc',
-        '<(DEPTH)/starboard/shared/posix/file_read.cc',
-        '<(DEPTH)/starboard/shared/posix/file_seek.cc',
-        '<(DEPTH)/starboard/shared/posix/file_truncate.cc',
-        '<(DEPTH)/starboard/shared/posix/file_write.cc',
-        '<(DEPTH)/starboard/shared/posix/log.cc',
-        '<(DEPTH)/starboard/shared/posix/log_flush.cc',
-        '<(DEPTH)/starboard/shared/posix/log_format.cc',
-        '<(DEPTH)/starboard/shared/posix/log_is_tty.cc',
-        '<(DEPTH)/starboard/shared/posix/log_raw.cc',
-        '<(DEPTH)/starboard/shared/posix/memory_flush.cc',
-        '<(DEPTH)/starboard/shared/posix/set_non_blocking_internal.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_accept.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_bind.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_clear_last_error.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_connect.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_create.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_destroy.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_free_resolution.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_get_last_error.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_get_local_address.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_internal.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_is_connected.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_is_connected_and_idle.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_join_multicast_group.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_listen.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_receive_from.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_resolve.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_send_to.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_set_broadcast.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_set_receive_buffer_size.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_set_reuse_address.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_set_send_buffer_size.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_set_tcp_keep_alive.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_set_tcp_no_delay.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_set_tcp_window_scaling.cc',
-        '<(DEPTH)/starboard/shared/posix/string_compare_no_case.cc',
-        '<(DEPTH)/starboard/shared/posix/string_compare_no_case_n.cc',
-        '<(DEPTH)/starboard/shared/posix/string_compare_wide.cc',
-        '<(DEPTH)/starboard/shared/posix/string_format.cc',
-        '<(DEPTH)/starboard/shared/posix/string_format_wide.cc',
-        '<(DEPTH)/starboard/shared/posix/system_break_into_debugger.cc',
-        '<(DEPTH)/starboard/shared/posix/system_clear_last_error.cc',
-        '<(DEPTH)/starboard/shared/posix/system_get_error_string.cc',
-        '<(DEPTH)/starboard/shared/posix/system_get_last_error.cc',
-        '<(DEPTH)/starboard/shared/posix/system_get_locale_id.cc',
-        '<(DEPTH)/starboard/shared/posix/system_get_number_of_processors.cc',
-        '<(DEPTH)/starboard/shared/posix/thread_sleep.cc',
-        '<(DEPTH)/starboard/shared/posix/time_get_monotonic_now.cc',
-        '<(DEPTH)/starboard/shared/posix/time_get_now.cc',
-        '<(DEPTH)/starboard/shared/posix/time_zone_get_current.cc',
-        '<(DEPTH)/starboard/shared/posix/time_zone_get_dst_name.cc',
-        '<(DEPTH)/starboard/shared/posix/time_zone_get_name.cc',
-        '<(DEPTH)/starboard/shared/pthread/condition_variable_broadcast.cc',
-        '<(DEPTH)/starboard/shared/pthread/condition_variable_create.cc',
-        '<(DEPTH)/starboard/shared/pthread/condition_variable_destroy.cc',
-        '<(DEPTH)/starboard/shared/pthread/condition_variable_signal.cc',
-        '<(DEPTH)/starboard/shared/pthread/condition_variable_wait.cc',
-        '<(DEPTH)/starboard/shared/pthread/condition_variable_wait_timed.cc',
-        '<(DEPTH)/starboard/shared/pthread/mutex_acquire.cc',
-        '<(DEPTH)/starboard/shared/pthread/mutex_acquire_try.cc',
-        '<(DEPTH)/starboard/shared/pthread/mutex_create.cc',
-        '<(DEPTH)/starboard/shared/pthread/mutex_destroy.cc',
-        '<(DEPTH)/starboard/shared/pthread/mutex_release.cc',
-        '<(DEPTH)/starboard/shared/pthread/once.cc',
-        '<(DEPTH)/starboard/shared/pthread/thread_create.cc',
-        '<(DEPTH)/starboard/shared/pthread/thread_create_local_key.cc',
-        '<(DEPTH)/starboard/shared/pthread/thread_destroy_local_key.cc',
-        '<(DEPTH)/starboard/shared/pthread/thread_detach.cc',
-        '<(DEPTH)/starboard/shared/pthread/thread_get_current.cc',
-        '<(DEPTH)/starboard/shared/pthread/thread_get_local_value.cc',
-        '<(DEPTH)/starboard/shared/pthread/thread_is_equal.cc',
-        '<(DEPTH)/starboard/shared/pthread/thread_join.cc',
-        '<(DEPTH)/starboard/shared/pthread/thread_set_local_value.cc',
-        '<(DEPTH)/starboard/shared/pthread/thread_yield.cc',
-        '<(DEPTH)/starboard/shared/signal/crash_signals_sigaction.cc',
-        '<(DEPTH)/starboard/shared/signal/crash_signals.h',
-        '<(DEPTH)/starboard/shared/signal/suspend_signals.cc',
-        '<(DEPTH)/starboard/shared/signal/suspend_signals.h',
-        '<(DEPTH)/starboard/shared/starboard/application.cc',
-        '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_create.cc',
-        '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_destroy.cc',
-        '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_internal.cc',
-        '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_internal.h',
-        '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_is_valid.cc',
-        '<(DEPTH)/starboard/shared/starboard/audio_sink/stub_audio_sink_type.cc',
-        '<(DEPTH)/starboard/shared/starboard/audio_sink/stub_audio_sink_type.h',
-        '<(DEPTH)/starboard/shared/starboard/blitter_blit_rect_to_rect_tiled.cc',
-        '<(DEPTH)/starboard/shared/starboard/blitter_blit_rects_to_rects.cc',
-        '<(DEPTH)/starboard/shared/starboard/directory_can_open.cc',
-        '<(DEPTH)/starboard/shared/starboard/event_cancel.cc',
-        '<(DEPTH)/starboard/shared/starboard/event_schedule.cc',
-        '<(DEPTH)/starboard/shared/starboard/file_mode_string_to_flags.cc',
-        '<(DEPTH)/starboard/shared/starboard/file_storage/storage_close_record.cc',
-        '<(DEPTH)/starboard/shared/starboard/file_storage/storage_delete_record.cc',
-        '<(DEPTH)/starboard/shared/starboard/file_storage/storage_get_record_size.cc',
-        '<(DEPTH)/starboard/shared/starboard/file_storage/storage_open_record.cc',
-        '<(DEPTH)/starboard/shared/starboard/file_storage/storage_read_record.cc',
-        '<(DEPTH)/starboard/shared/starboard/file_storage/storage_write_record.cc',
-        '<(DEPTH)/starboard/shared/starboard/log_message.cc',
-        '<(DEPTH)/starboard/shared/starboard/log_raw_dump_stack.cc',
-        '<(DEPTH)/starboard/shared/starboard/log_raw_format.cc',
-        '<(DEPTH)/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc',
-        '<(DEPTH)/starboard/shared/starboard/media/media_is_output_protected.cc',
-        '<(DEPTH)/starboard/shared/starboard/media/media_set_output_protection.cc',
-        '<(DEPTH)/starboard/shared/starboard/media/mime_type.cc',
-        '<(DEPTH)/starboard/shared/starboard/media/mime_type.h',
-        '<(DEPTH)/starboard/shared/starboard/new.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/filter/audio_decoder_internal.h',
-        '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_internal.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_internal.h',
-        '<(DEPTH)/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.h',
-        '<(DEPTH)/starboard/shared/starboard/player/filter/video_decoder_internal.h',
-        '<(DEPTH)/starboard/shared/starboard/player/filter/video_renderer_internal.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/filter/video_renderer_internal.h',
-        '<(DEPTH)/starboard/shared/starboard/player/input_buffer_internal.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/input_buffer_internal.h',
-        '<(DEPTH)/starboard/shared/starboard/player/player_create.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/player_destroy.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/player_get_info.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/player_internal.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/player_internal.h',
-        '<(DEPTH)/starboard/shared/starboard/player/player_seek.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/player_set_bounds.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/player_set_pause.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/player_set_volume.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/player_worker.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/player_worker.h',
-        '<(DEPTH)/starboard/shared/starboard/player/player_write_end_of_stream.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/player_write_sample.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/video_frame_internal.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/video_frame_internal.h',
-        '<(DEPTH)/starboard/shared/starboard/queue_application.cc',
-        '<(DEPTH)/starboard/shared/starboard/string_concat.cc',
-        '<(DEPTH)/starboard/shared/starboard/string_concat_wide.cc',
-        '<(DEPTH)/starboard/shared/starboard/string_copy.cc',
-        '<(DEPTH)/starboard/shared/starboard/string_copy_wide.cc',
-        '<(DEPTH)/starboard/shared/starboard/string_duplicate.cc',
-        '<(DEPTH)/starboard/shared/starboard/system_get_random_uint64.cc',
-        '<(DEPTH)/starboard/shared/starboard/system_request_stop.cc',
-        '<(DEPTH)/starboard/shared/starboard/window_set_default_options.cc',
-        '<(DEPTH)/starboard/shared/stub/drm_close_session.cc',
-        '<(DEPTH)/starboard/shared/stub/drm_create_system.cc',
-        '<(DEPTH)/starboard/shared/stub/drm_destroy_system.cc',
-        '<(DEPTH)/starboard/shared/stub/drm_generate_session_update_request.cc',
-        '<(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_hide_splash_screen.cc',
-        '<(DEPTH)/starboard/shared/stub/system_raise_platform_error.cc',
-        '<(DEPTH)/starboard/shared/stub/system_get_total_gpu_memory.cc',
-        '<(DEPTH)/starboard/shared/stub/system_get_used_gpu_memory.cc',
-      ],
+      'sources': ['<@(starboard_platform_sources)'],
       'include_dirs': [
         '/usr/include/directfb',
       ],
@@ -324,10 +29,7 @@
         'STARBOARD_IMPLEMENTATION',
       ],
       'dependencies': [
-        '<(DEPTH)/starboard/common/common.gyp:common',
-        '<(DEPTH)/third_party/dlmalloc/dlmalloc.gyp:dlmalloc',
-        '<(DEPTH)/third_party/libevent/libevent.gyp:libevent',
-        'starboard_base_symbolize',
+        '<@(starboard_platform_dependencies)',
       ],
     },
   ],
diff --git a/src/starboard/linux/x64directfb/starboard_platform.gypi b/src/starboard/linux/x64directfb/starboard_platform.gypi
new file mode 100644
index 0000000..f5d40ad
--- /dev/null
+++ b/src/starboard/linux/x64directfb/starboard_platform.gypi
@@ -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.
+{
+  'includes': ['../shared/starboard_platform.gypi'],
+
+  'variables': {
+    'starboard_platform_sources': [
+        '<(DEPTH)/starboard/linux/x64directfb/main.cc',
+        '<(DEPTH)/starboard/linux/x64directfb/system_get_property.cc',
+        '<(DEPTH)/starboard/shared/directfb/application_directfb.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_blit_rect_to_rect.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_create_context.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_create_default_device.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_create_pixel_data.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_create_render_target_surface.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_create_surface_from_pixel_data.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_create_swap_chain_from_window.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_destroy_context.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_destroy_device.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_destroy_pixel_data.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_destroy_surface.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_destroy_swap_chain.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_download_surface_pixels.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_fill_rect.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_flip_swap_chain.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_flush_context.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_get_max_contexts.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_get_pixel_data_pitch_in_bytes.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_get_pixel_data_pointer.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_get_render_target_from_surface.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_get_render_target_from_swap_chain.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_get_surface_info.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_internal.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_is_pixel_format_supported_by_download_surface_pixels.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_is_pixel_format_supported_by_pixel_data.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_is_surface_format_supported_by_render_target_surface.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_set_blending.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_set_color.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_set_modulate_blits_with_color.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_set_render_target.cc',
+        '<(DEPTH)/starboard/shared/directfb/blitter_set_scissor.cc',
+        '<(DEPTH)/starboard/shared/directfb/window_create.cc',
+        '<(DEPTH)/starboard/shared/directfb/window_destroy.cc',
+        '<(DEPTH)/starboard/shared/directfb/window_get_platform_handle.cc',
+        '<(DEPTH)/starboard/shared/directfb/window_get_size.cc',
+        '<(DEPTH)/starboard/shared/directfb/window_internal.cc',
+        '<(DEPTH)/starboard/shared/starboard/blitter_blit_rect_to_rect_tiled.cc',
+        '<(DEPTH)/starboard/shared/starboard/blitter_blit_rects_to_rects.cc',
+    ],
+  },
+}
diff --git a/src/starboard/linux/x64directfb/system_get_property.cc b/src/starboard/linux/x64directfb/system_get_property.cc
index b1529fe..1d20f7f 100644
--- a/src/starboard/linux/x64directfb/system_get_property.cc
+++ b/src/starboard/linux/x64directfb/system_get_property.cc
@@ -47,6 +47,7 @@
     case kSbSystemPropertyModelName:
     case kSbSystemPropertyModelYear:
     case kSbSystemPropertyNetworkOperatorName:
+    case kSbSystemPropertySpeechApiKey:
       return false;
 
     case kSbSystemPropertyFriendlyName:
diff --git a/src/starboard/linux/x64x11/configuration_public.h b/src/starboard/linux/x64x11/configuration_public.h
index 4aec879..8022c88 100644
--- a/src/starboard/linux/x64x11/configuration_public.h
+++ b/src/starboard/linux/x64x11/configuration_public.h
@@ -109,9 +109,14 @@
 // textures. These textures typically originate from video decoders.
 #define SB_HAS_NV12_TEXTURE_SUPPORT 1
 
-#define SB_HAS_MICROPHONE 0
+// Whether the current platform has speech synthesis.
+#define SB_HAS_SPEECH_SYNTHESIS 0
 
 // Include the Linux configuration that's common between all Desktop Linuxes.
 #include "starboard/linux/shared/configuration_public.h"
 
+// The current platform has microphone supported.
+#undef SB_HAS_MICROPHONE
+#define SB_HAS_MICROPHONE 1
+
 #endif  // STARBOARD_LINUX_X64X11_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/future/gyp_configuration.gypi b/src/starboard/linux/x64x11/future/gyp_configuration.gypi
index 0cb12cf..0bd1f09 100644
--- a/src/starboard/linux/x64x11/future/gyp_configuration.gypi
+++ b/src/starboard/linux/x64x11/future/gyp_configuration.gypi
@@ -14,6 +14,13 @@
 
 {
   'target_defaults': {
+    # By default, <EGL/eglplatform.h> pulls in some X11 headers that have some
+    # nasty macros (|Status|, for example) that conflict with Chromium base.
+    # Since certain Cobalt headers now depend on EGL through SbDecodeTarget,
+    # we define this macro to configure EGL to not pull in these headers.
+    'defines': [
+      'MESA_EGL_NO_X11_HEADERS'
+    ],
     'default_configuration': 'linux-x64x11-future_debug',
     'configurations': {
       'linux-x64x11-future_debug': {
diff --git a/src/starboard/linux/x64x11/future/starboard_platform.gyp b/src/starboard/linux/x64x11/future/starboard_platform.gyp
index 9648c9d..31eaa25 100644
--- a/src/starboard/linux/x64x11/future/starboard_platform.gyp
+++ b/src/starboard/linux/x64x11/future/starboard_platform.gyp
@@ -12,16 +12,23 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 {
+  'includes': [
+    '../starboard_platform.gypi'
+  ],
   'targets': [
     {
       'target_name': 'starboard_platform',
       'product_name': 'starboard_platform_future',
       'type': 'static_library',
       'sources': [
+        '<@(starboard_platform_sources)',
         '<(DEPTH)/starboard/shared/stub/decode_target_create_egl.cc',
         '<(DEPTH)/starboard/shared/stub/decode_target_destroy.cc',
         '<(DEPTH)/starboard/shared/stub/decode_target_get_format.cc',
         '<(DEPTH)/starboard/shared/stub/decode_target_get_plane_egl.cc',
+        '<(DEPTH)/starboard/shared/stub/decode_target_is_opaque.cc',
+        '<(DEPTH)/starboard/shared/stub/image_decode.cc',
+        '<(DEPTH)/starboard/shared/stub/image_is_decode_supported.cc',
       ],
       'defines': [
         # This must be defined when building Starboard, and must not when
@@ -29,11 +36,7 @@
         'STARBOARD_IMPLEMENTATION',
       ],
       'dependencies': [
-        '<(DEPTH)/starboard/common/common.gyp:common',
-        '<(DEPTH)/starboard/linux/x64x11/starboard_platform.gyp:starboard_platform',
-        '<(DEPTH)/starboard/linux/x64x11/starboard_platform.gyp:starboard_base_symbolize',
-        '<(DEPTH)/third_party/dlmalloc/dlmalloc.gyp:dlmalloc',
-        '<(DEPTH)/third_party/libevent/libevent.gyp:libevent',
+        '<@(starboard_platform_dependencies)',
       ],
     },
   ],
diff --git a/src/starboard/linux/x64x11/starboard_platform.gyp b/src/starboard/linux/x64x11/starboard_platform.gyp
index 228ceb0..56e5781 100644
--- a/src/starboard/linux/x64x11/starboard_platform.gyp
+++ b/src/starboard/linux/x64x11/starboard_platform.gyp
@@ -12,287 +12,21 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 {
+  'includes': [
+    'starboard_platform.gypi'
+  ],
   'targets': [
     {
-      'target_name': 'starboard_base_symbolize',
-      'type': 'static_library',
-      'sources': [
-        '<(DEPTH)/base/third_party/symbolize/demangle.cc',
-        '<(DEPTH)/base/third_party/symbolize/symbolize.cc',
-      ],
-    },
-    {
       'target_name': 'starboard_platform',
       'type': 'static_library',
-      'sources': [
-        '<(DEPTH)/starboard/linux/shared/atomic_public.h',
-        '<(DEPTH)/starboard/linux/shared/configuration_public.h',
-        '<(DEPTH)/starboard/linux/shared/system_get_connection_type.cc',
-        '<(DEPTH)/starboard/linux/shared/system_get_device_type.cc',
-        '<(DEPTH)/starboard/linux/shared/system_get_path.cc',
-        '<(DEPTH)/starboard/linux/shared/system_has_capability.cc',
-        '<(DEPTH)/starboard/linux/x64x11/main.cc',
-        '<(DEPTH)/starboard/linux/x64x11/sanitizer_options.cc',
-        '<(DEPTH)/starboard/linux/x64x11/system_get_property.cc',
-        '<(DEPTH)/starboard/shared/alsa/alsa_audio_sink_type.cc',
-        '<(DEPTH)/starboard/shared/alsa/alsa_audio_sink_type.h',
-        '<(DEPTH)/starboard/shared/alsa/alsa_util.cc',
-        '<(DEPTH)/starboard/shared/alsa/alsa_util.h',
-        '<(DEPTH)/starboard/shared/alsa/audio_sink_get_max_channels.cc',
-        '<(DEPTH)/starboard/shared/alsa/audio_sink_get_nearest_supported_sample_frequency.cc',
-        '<(DEPTH)/starboard/shared/alsa/audio_sink_is_audio_frame_storage_type_supported.cc',
-        '<(DEPTH)/starboard/shared/alsa/audio_sink_is_audio_sample_type_supported.cc',
-        '<(DEPTH)/starboard/shared/dlmalloc/memory_allocate_aligned_unchecked.cc',
-        '<(DEPTH)/starboard/shared/dlmalloc/memory_allocate_unchecked.cc',
-        '<(DEPTH)/starboard/shared/dlmalloc/memory_free.cc',
-        '<(DEPTH)/starboard/shared/dlmalloc/memory_free_aligned.cc',
-        '<(DEPTH)/starboard/shared/dlmalloc/memory_map.cc',
-        '<(DEPTH)/starboard/shared/dlmalloc/memory_reallocate_unchecked.cc',
-        '<(DEPTH)/starboard/shared/dlmalloc/memory_unmap.cc',
-        '<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc',
-        '<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_audio_decoder.h',
-        '<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_common.cc',
-        '<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_common.h',
-        '<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc',
-        '<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_video_decoder.h',
-        '<(DEPTH)/starboard/shared/gcc/atomic_gcc_public.h',
-        '<(DEPTH)/starboard/shared/iso/character_is_alphanumeric.cc',
-        '<(DEPTH)/starboard/shared/iso/character_is_digit.cc',
-        '<(DEPTH)/starboard/shared/iso/character_is_hex_digit.cc',
-        '<(DEPTH)/starboard/shared/iso/character_is_space.cc',
-        '<(DEPTH)/starboard/shared/iso/character_is_upper.cc',
-        '<(DEPTH)/starboard/shared/iso/character_to_lower.cc',
-        '<(DEPTH)/starboard/shared/iso/character_to_upper.cc',
-        '<(DEPTH)/starboard/shared/iso/directory_close.cc',
-        '<(DEPTH)/starboard/shared/iso/directory_get_next.cc',
-        '<(DEPTH)/starboard/shared/iso/directory_open.cc',
-        '<(DEPTH)/starboard/shared/iso/double_absolute.cc',
-        '<(DEPTH)/starboard/shared/iso/double_exponent.cc',
-        '<(DEPTH)/starboard/shared/iso/double_floor.cc',
-        '<(DEPTH)/starboard/shared/iso/double_is_finite.cc',
-        '<(DEPTH)/starboard/shared/iso/double_is_nan.cc',
-        '<(DEPTH)/starboard/shared/iso/memory_compare.cc',
-        '<(DEPTH)/starboard/shared/iso/memory_copy.cc',
-        '<(DEPTH)/starboard/shared/iso/memory_find_byte.cc',
-        '<(DEPTH)/starboard/shared/iso/memory_move.cc',
-        '<(DEPTH)/starboard/shared/iso/memory_set.cc',
-        '<(DEPTH)/starboard/shared/iso/string_compare.cc',
-        '<(DEPTH)/starboard/shared/iso/string_compare_all.cc',
-        '<(DEPTH)/starboard/shared/iso/string_find_character.cc',
-        '<(DEPTH)/starboard/shared/iso/string_find_last_character.cc',
-        '<(DEPTH)/starboard/shared/iso/string_find_string.cc',
-        '<(DEPTH)/starboard/shared/iso/string_get_length.cc',
-        '<(DEPTH)/starboard/shared/iso/string_get_length_wide.cc',
-        '<(DEPTH)/starboard/shared/iso/string_parse_double.cc',
-        '<(DEPTH)/starboard/shared/iso/string_parse_signed_integer.cc',
-        '<(DEPTH)/starboard/shared/iso/string_parse_uint64.cc',
-        '<(DEPTH)/starboard/shared/iso/string_parse_unsigned_integer.cc',
-        '<(DEPTH)/starboard/shared/iso/string_scan.cc',
-        '<(DEPTH)/starboard/shared/iso/system_binary_search.cc',
-        '<(DEPTH)/starboard/shared/iso/system_sort.cc',
-        '<(DEPTH)/starboard/shared/libevent/socket_waiter_add.cc',
-        '<(DEPTH)/starboard/shared/libevent/socket_waiter_create.cc',
-        '<(DEPTH)/starboard/shared/libevent/socket_waiter_destroy.cc',
-        '<(DEPTH)/starboard/shared/libevent/socket_waiter_internal.cc',
-        '<(DEPTH)/starboard/shared/libevent/socket_waiter_remove.cc',
-        '<(DEPTH)/starboard/shared/libevent/socket_waiter_wait.cc',
-        '<(DEPTH)/starboard/shared/libevent/socket_waiter_wait_timed.cc',
-        '<(DEPTH)/starboard/shared/libevent/socket_waiter_wake_up.cc',
-        '<(DEPTH)/starboard/shared/linux/byte_swap.cc',
-        '<(DEPTH)/starboard/shared/linux/get_home_directory.cc',
-        '<(DEPTH)/starboard/shared/linux/memory_get_stack_bounds.cc',
-        '<(DEPTH)/starboard/shared/linux/page_internal.cc',
-        '<(DEPTH)/starboard/shared/linux/socket_get_local_interface_address.cc',
-        '<(DEPTH)/starboard/shared/linux/system_get_random_data.cc',
-        '<(DEPTH)/starboard/shared/linux/system_get_stack.cc',
-        '<(DEPTH)/starboard/shared/linux/system_get_total_cpu_memory.cc',
-        '<(DEPTH)/starboard/shared/linux/system_get_used_cpu_memory.cc',
-        '<(DEPTH)/starboard/shared/linux/system_is_debugger_attached.cc',
-        '<(DEPTH)/starboard/shared/linux/system_symbolize.cc',
-        '<(DEPTH)/starboard/shared/linux/thread_get_id.cc',
-        '<(DEPTH)/starboard/shared/linux/thread_get_name.cc',
-        '<(DEPTH)/starboard/shared/linux/thread_set_name.cc',
-        '<(DEPTH)/starboard/shared/nouser/user_get_current.cc',
-        '<(DEPTH)/starboard/shared/nouser/user_get_property.cc',
-        '<(DEPTH)/starboard/shared/nouser/user_get_signed_in.cc',
-        '<(DEPTH)/starboard/shared/nouser/user_internal.cc',
-        '<(DEPTH)/starboard/shared/posix/directory_create.cc',
-        '<(DEPTH)/starboard/shared/posix/file_can_open.cc',
-        '<(DEPTH)/starboard/shared/posix/file_close.cc',
-        '<(DEPTH)/starboard/shared/posix/file_delete.cc',
-        '<(DEPTH)/starboard/shared/posix/file_exists.cc',
-        '<(DEPTH)/starboard/shared/posix/file_flush.cc',
-        '<(DEPTH)/starboard/shared/posix/file_get_info.cc',
-        '<(DEPTH)/starboard/shared/posix/file_get_path_info.cc',
-        '<(DEPTH)/starboard/shared/posix/file_open.cc',
-        '<(DEPTH)/starboard/shared/posix/file_read.cc',
-        '<(DEPTH)/starboard/shared/posix/file_seek.cc',
-        '<(DEPTH)/starboard/shared/posix/file_truncate.cc',
-        '<(DEPTH)/starboard/shared/posix/file_write.cc',
-        '<(DEPTH)/starboard/shared/posix/log.cc',
-        '<(DEPTH)/starboard/shared/posix/log_flush.cc',
-        '<(DEPTH)/starboard/shared/posix/log_format.cc',
-        '<(DEPTH)/starboard/shared/posix/log_is_tty.cc',
-        '<(DEPTH)/starboard/shared/posix/log_raw.cc',
-        '<(DEPTH)/starboard/shared/posix/memory_flush.cc',
-        '<(DEPTH)/starboard/shared/posix/set_non_blocking_internal.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_accept.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_bind.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_clear_last_error.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_connect.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_create.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_destroy.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_free_resolution.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_get_last_error.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_get_local_address.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_internal.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_is_connected.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_is_connected_and_idle.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_join_multicast_group.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_listen.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_receive_from.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_resolve.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_send_to.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_set_broadcast.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_set_receive_buffer_size.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_set_reuse_address.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_set_send_buffer_size.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_set_tcp_keep_alive.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_set_tcp_no_delay.cc',
-        '<(DEPTH)/starboard/shared/posix/socket_set_tcp_window_scaling.cc',
-        '<(DEPTH)/starboard/shared/posix/string_compare_no_case.cc',
-        '<(DEPTH)/starboard/shared/posix/string_compare_no_case_n.cc',
-        '<(DEPTH)/starboard/shared/posix/string_compare_wide.cc',
-        '<(DEPTH)/starboard/shared/posix/string_format.cc',
-        '<(DEPTH)/starboard/shared/posix/string_format_wide.cc',
-        '<(DEPTH)/starboard/shared/posix/system_break_into_debugger.cc',
-        '<(DEPTH)/starboard/shared/posix/system_clear_last_error.cc',
-        '<(DEPTH)/starboard/shared/posix/system_get_error_string.cc',
-        '<(DEPTH)/starboard/shared/posix/system_get_last_error.cc',
-        '<(DEPTH)/starboard/shared/posix/system_get_locale_id.cc',
-        '<(DEPTH)/starboard/shared/posix/system_get_number_of_processors.cc',
-        '<(DEPTH)/starboard/shared/posix/thread_sleep.cc',
-        '<(DEPTH)/starboard/shared/posix/time_get_monotonic_now.cc',
-        '<(DEPTH)/starboard/shared/posix/time_get_now.cc',
-        '<(DEPTH)/starboard/shared/posix/time_zone_get_current.cc',
-        '<(DEPTH)/starboard/shared/posix/time_zone_get_dst_name.cc',
-        '<(DEPTH)/starboard/shared/posix/time_zone_get_name.cc',
-        '<(DEPTH)/starboard/shared/pthread/condition_variable_broadcast.cc',
-        '<(DEPTH)/starboard/shared/pthread/condition_variable_create.cc',
-        '<(DEPTH)/starboard/shared/pthread/condition_variable_destroy.cc',
-        '<(DEPTH)/starboard/shared/pthread/condition_variable_signal.cc',
-        '<(DEPTH)/starboard/shared/pthread/condition_variable_wait.cc',
-        '<(DEPTH)/starboard/shared/pthread/condition_variable_wait_timed.cc',
-        '<(DEPTH)/starboard/shared/pthread/mutex_acquire.cc',
-        '<(DEPTH)/starboard/shared/pthread/mutex_acquire_try.cc',
-        '<(DEPTH)/starboard/shared/pthread/mutex_create.cc',
-        '<(DEPTH)/starboard/shared/pthread/mutex_destroy.cc',
-        '<(DEPTH)/starboard/shared/pthread/mutex_release.cc',
-        '<(DEPTH)/starboard/shared/pthread/once.cc',
-        '<(DEPTH)/starboard/shared/pthread/thread_create.cc',
-        '<(DEPTH)/starboard/shared/pthread/thread_create_local_key.cc',
-        '<(DEPTH)/starboard/shared/pthread/thread_destroy_local_key.cc',
-        '<(DEPTH)/starboard/shared/pthread/thread_detach.cc',
-        '<(DEPTH)/starboard/shared/pthread/thread_get_current.cc',
-        '<(DEPTH)/starboard/shared/pthread/thread_get_local_value.cc',
-        '<(DEPTH)/starboard/shared/pthread/thread_is_equal.cc',
-        '<(DEPTH)/starboard/shared/pthread/thread_join.cc',
-        '<(DEPTH)/starboard/shared/pthread/thread_set_local_value.cc',
-        '<(DEPTH)/starboard/shared/pthread/thread_yield.cc',
-        '<(DEPTH)/starboard/shared/signal/crash_signals.h',
-        '<(DEPTH)/starboard/shared/signal/crash_signals_sigaction.cc',
-        '<(DEPTH)/starboard/shared/signal/suspend_signals.cc',
-        '<(DEPTH)/starboard/shared/signal/suspend_signals.h',
-        '<(DEPTH)/starboard/shared/starboard/application.cc',
-        '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_create.cc',
-        '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_destroy.cc',
-        '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_internal.cc',
-        '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_internal.h',
-        '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_is_valid.cc',
-        '<(DEPTH)/starboard/shared/starboard/audio_sink/stub_audio_sink_type.cc',
-        '<(DEPTH)/starboard/shared/starboard/audio_sink/stub_audio_sink_type.h',
-        '<(DEPTH)/starboard/shared/starboard/directory_can_open.cc',
-        '<(DEPTH)/starboard/shared/starboard/event_cancel.cc',
-        '<(DEPTH)/starboard/shared/starboard/event_schedule.cc',
-        '<(DEPTH)/starboard/shared/starboard/file_mode_string_to_flags.cc',
-        '<(DEPTH)/starboard/shared/starboard/file_storage/storage_close_record.cc',
-        '<(DEPTH)/starboard/shared/starboard/file_storage/storage_delete_record.cc',
-        '<(DEPTH)/starboard/shared/starboard/file_storage/storage_get_record_size.cc',
-        '<(DEPTH)/starboard/shared/starboard/file_storage/storage_open_record.cc',
-        '<(DEPTH)/starboard/shared/starboard/file_storage/storage_read_record.cc',
-        '<(DEPTH)/starboard/shared/starboard/file_storage/storage_write_record.cc',
-        '<(DEPTH)/starboard/shared/starboard/log_message.cc',
-        '<(DEPTH)/starboard/shared/starboard/log_raw_dump_stack.cc',
-        '<(DEPTH)/starboard/shared/starboard/log_raw_format.cc',
-        '<(DEPTH)/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc',
-        '<(DEPTH)/starboard/shared/starboard/media/media_is_output_protected.cc',
-        '<(DEPTH)/starboard/shared/starboard/media/media_set_output_protection.cc',
-        '<(DEPTH)/starboard/shared/starboard/media/mime_type.cc',
-        '<(DEPTH)/starboard/shared/starboard/media/mime_type.h',
-        '<(DEPTH)/starboard/shared/starboard/new.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/filter/audio_decoder_internal.h',
-        '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_internal.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_internal.h',
-        '<(DEPTH)/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.h',
-        '<(DEPTH)/starboard/shared/starboard/player/filter/video_decoder_internal.h',
-        '<(DEPTH)/starboard/shared/starboard/player/filter/video_renderer_internal.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/filter/video_renderer_internal.h',
-        '<(DEPTH)/starboard/shared/starboard/player/input_buffer_internal.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/input_buffer_internal.h',
-        '<(DEPTH)/starboard/shared/starboard/player/player_create.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/player_destroy.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/player_get_info.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/player_internal.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/player_internal.h',
-        '<(DEPTH)/starboard/shared/starboard/player/player_seek.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/player_set_bounds.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/player_set_pause.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/player_set_volume.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/player_worker.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/player_worker.h',
-        '<(DEPTH)/starboard/shared/starboard/player/player_write_end_of_stream.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/player_write_sample.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/video_frame_internal.cc',
-        '<(DEPTH)/starboard/shared/starboard/player/video_frame_internal.h',
-        '<(DEPTH)/starboard/shared/starboard/queue_application.cc',
-        '<(DEPTH)/starboard/shared/starboard/string_concat.cc',
-        '<(DEPTH)/starboard/shared/starboard/string_concat_wide.cc',
-        '<(DEPTH)/starboard/shared/starboard/string_copy.cc',
-        '<(DEPTH)/starboard/shared/starboard/string_copy_wide.cc',
-        '<(DEPTH)/starboard/shared/starboard/string_duplicate.cc',
-        '<(DEPTH)/starboard/shared/starboard/system_get_random_uint64.cc',
-        '<(DEPTH)/starboard/shared/starboard/system_request_stop.cc',
-        '<(DEPTH)/starboard/shared/starboard/window_set_default_options.cc',
-        '<(DEPTH)/starboard/shared/stub/drm_close_session.cc',
-        '<(DEPTH)/starboard/shared/stub/drm_create_system.cc',
-        '<(DEPTH)/starboard/shared/stub/drm_destroy_system.cc',
-        '<(DEPTH)/starboard/shared/stub/drm_generate_session_update_request.cc',
-        '<(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_get_total_gpu_memory.cc',
-        '<(DEPTH)/starboard/shared/stub/system_get_used_gpu_memory.cc',
-        '<(DEPTH)/starboard/shared/stub/system_hide_splash_screen.cc',
-        '<(DEPTH)/starboard/shared/stub/system_raise_platform_error.cc',
-        '<(DEPTH)/starboard/shared/x11/application_x11.cc',
-        '<(DEPTH)/starboard/shared/x11/window_create.cc',
-        '<(DEPTH)/starboard/shared/x11/window_destroy.cc',
-        '<(DEPTH)/starboard/shared/x11/window_get_platform_handle.cc',
-        '<(DEPTH)/starboard/shared/x11/window_get_size.cc',
-        '<(DEPTH)/starboard/shared/x11/window_internal.cc',
-      ],
+      'sources': ['<@(starboard_platform_sources)'],
       'defines': [
         # This must be defined when building Starboard, and must not when
         # building Starboard client code.
         'STARBOARD_IMPLEMENTATION',
       ],
       'dependencies': [
-        '<(DEPTH)/starboard/common/common.gyp:common',
-        '<(DEPTH)/third_party/dlmalloc/dlmalloc.gyp:dlmalloc',
-        '<(DEPTH)/third_party/libevent/libevent.gyp:libevent',
-        'starboard_base_symbolize',
+        '<@(starboard_platform_dependencies)',
       ],
     },
   ],
diff --git a/src/starboard/linux/x64x11/starboard_platform.gypi b/src/starboard/linux/x64x11/starboard_platform.gypi
new file mode 100644
index 0000000..05f1e12
--- /dev/null
+++ b/src/starboard/linux/x64x11/starboard_platform.gypi
@@ -0,0 +1,30 @@
+# 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.
+{
+  'includes': ['../shared/starboard_platform.gypi'],
+
+  'variables': {
+    'starboard_platform_sources': [
+      '<(DEPTH)/starboard/linux/x64x11/main.cc',
+      '<(DEPTH)/starboard/linux/x64x11/sanitizer_options.cc',
+      '<(DEPTH)/starboard/linux/x64x11/system_get_property.cc',
+      '<(DEPTH)/starboard/shared/x11/application_x11.cc',
+      '<(DEPTH)/starboard/shared/x11/window_create.cc',
+      '<(DEPTH)/starboard/shared/x11/window_destroy.cc',
+      '<(DEPTH)/starboard/shared/x11/window_get_platform_handle.cc',
+      '<(DEPTH)/starboard/shared/x11/window_get_size.cc',
+      '<(DEPTH)/starboard/shared/x11/window_internal.cc',
+    ],
+  },
+}
diff --git a/src/starboard/linux/x64x11/system_get_property.cc b/src/starboard/linux/x64x11/system_get_property.cc
index cffaa35..b72747d 100644
--- a/src/starboard/linux/x64x11/system_get_property.cc
+++ b/src/starboard/linux/x64x11/system_get_property.cc
@@ -47,6 +47,7 @@
     case kSbSystemPropertyModelName:
     case kSbSystemPropertyModelYear:
     case kSbSystemPropertyNetworkOperatorName:
+    case kSbSystemPropertySpeechApiKey:
       return false;
 
     case kSbSystemPropertyFriendlyName:
diff --git a/src/starboard/log.h b/src/starboard/log.h
index 3693925..8e86cd8 100644
--- a/src/starboard/log.h
+++ b/src/starboard/log.h
@@ -12,7 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Debug logging.
+// Module Overview: Starboard Logging module
+//
+// Defines debug logging functions.
 
 #ifndef STARBOARD_LOG_H_
 #define STARBOARD_LOG_H_
@@ -41,28 +43,38 @@
   kSbLogPriorityFatal,
 } SbLogPriority;
 
-// Writes |message| at |priority| to the debug output log for this platform.
-// Passing kSbLogPriorityFatal will not terminate the program, such policy must
-// be enforced at the application level. |priority| may, in fact, be completely
-// ignored on many platforms. No formatting is required to be done on the
-// message, not even newline termination. That said, platforms may wish to
-// adjust the message to be more suitable for their output method. This could be
-// wrapping the text, or stripping unprintable characters.
+// Writes |message| to the platform's debug output log.
+//
+// |priority|: The SbLogPriority at which the message should be logged. Note
+//   that passing |kSbLogPriorityFatal| does not terminate the program. Such a
+//   policy must be enforced at the application level. In fact, |priority| may
+//   be completely ignored on many platforms.
+// |message|: The message to be logged. No formatting is required to be done
+//   on the value, including newline termination. That said, platforms can
+//   adjust the message to be more suitable for their output method by
+//   wrapping the text, stripping unprintable characters, etc.
 SB_EXPORT void SbLog(SbLogPriority priority, const char* message);
 
 // A bare-bones log output method that is async-signal-safe, i.e. safe to call
-// from an asynchronous signal handler (e.g. a SIGSEGV handler). It should do no
-// additional formatting.
+// from an asynchronous signal handler (e.g. a |SIGSEGV| handler). It should not
+// do any additional formatting.
+//
+// |message|: The message to be logged.
 SB_EXPORT void SbLogRaw(const char* message);
 
 // Dumps the stack of the current thread to the log in an async-signal-safe
-// manner, i.e. safe to call from an asynchronous signal handler (e.g. a SIGSEGV
-// handler). Does not include SbLogRawDumpStack itself, and will additionally
-// skip |frames_to_skip| frames from the top of the stack.
+// manner, i.e. safe to call from an asynchronous signal handler (e.g. a
+// |SIGSEGV| handler). Does not include SbLogRawDumpStack itself.
+//
+// |frames_to_skip|: The number of frames to skip from the top of the stack
+//   when dumping the current thread to the log. This parameter lets you remove
+//   noise from helper functions that might end up on top of every stack dump
+//   so that the stack dump is just the relevant function stack where the
+//   problem occurred.
 SB_EXPORT void SbLogRawDumpStack(int frames_to_skip);
 
 // A formatted log output method that is async-signal-safe, i.e. safe to call
-// from an asynchronous signal handler (e.g. a SIGSEGV handler).
+// from an asynchronous signal handler (e.g. a |SIGSEGV| handler).
 SB_EXPORT void SbLogRawFormat(const char* format, va_list args)
     SB_PRINTF_FORMAT(1, 0);
 
@@ -76,12 +88,12 @@
   va_end(args);
 }
 
-// A log output method, that additionally performs a string format on the way
-// out.
+// A log output method that additionally performs a string format on the
+// data being logged.
 SB_EXPORT void SbLogFormat(const char* format, va_list args)
     SB_PRINTF_FORMAT(1, 0);
 
-// Inline wrapper of SbLogFormat to convert from ellipsis to va_args.
+// Inline wrapper of SbLogFormat that converts from ellipsis to va_args.
 static SB_C_INLINE void SbLogFormatF(const char* format, ...)
     SB_PRINTF_FORMAT(1, 2);
 void SbLogFormatF(const char* format, ...) {
@@ -91,10 +103,10 @@
   va_end(args);
 }
 
-// Flushes the log buffer, on some platforms.
+// Flushes the log buffer on some platforms.
 SB_EXPORT void SbLogFlush();
 
-// Returns whether the log output goes to a TTY or is being redirected.
+// Indicates whether the log output goes to a TTY or is being redirected.
 SB_EXPORT bool SbLogIsTty();
 
 #ifdef __cplusplus
diff --git a/src/starboard/media.h b/src/starboard/media.h
index 89f2608..2c800ba 100644
--- a/src/starboard/media.h
+++ b/src/starboard/media.h
@@ -12,7 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Media definitions that are common between the Decoder and Player interfaces.
+// Module Overview: Starboard Media module
+//
+// Provides media definitions that are common between the Decoder and Player
+// interfaces.
 
 #ifndef STARBOARD_MEDIA_H_
 #define STARBOARD_MEDIA_H_
@@ -40,7 +43,7 @@
   kSbMediaTypeVideo,
 } SbMediaType;
 
-// Possibly supported types of video elementary streams.
+// Types of video elementary streams that could be supported.
 typedef enum SbMediaVideoCodec {
   kSbMediaVideoCodecNone,
 
@@ -54,7 +57,7 @@
   kSbMediaVideoCodecVp9,
 } SbMediaVideoCodec;
 
-// Possibly supported types of audio elementary streams.
+// Types of audio elementary streams that can be supported.
 typedef enum SbMediaAudioCodec {
   kSbMediaAudioCodecNone,
 
@@ -63,8 +66,9 @@
   kSbMediaAudioCodecVorbis,
 } SbMediaAudioCodec;
 
-// Types of media support which is a direct map as the result of canPlayType()
-// specified in the following link:
+// Indicates how confident the device is that it can play media resources
+// of the given type. The values are a direct map of the canPlayType() method
+// specified at the following link:
 // https://www.w3.org/TR/2011/WD-html5-20110113/video.html#dom-navigator-canplaytype
 typedef enum SbMediaSupportType {
   // The media type cannot be played.
@@ -111,24 +115,27 @@
   kSbMediaAudioSampleTypeFloat32,
 } SbMediaAudioSampleType;
 
-// Possible audio frame storage types.  Interleaved means the samples of a
-// multi-channel audio stream are stored in one continuous buffer, samples at
-// the same timestamp are stored one after another.  Planar means the samples
-// of each channel are stored in their own continuous buffer. For example, for
-// stereo stream with channels L and R that contains samples with timestamp
-// 0, 1, ..., interleaved means the samples are stored in one buffer as
-// "L0 R0 L1 R1 L2 R2 ...".  Planar means the samples are stored in two buffers
-// "L0 L1 L2 ..." and "R0 R1 R2 ...".
+// Possible audio frame storage types.
 typedef enum SbMediaAudioFrameStorageType {
+  // The samples of a multi-channel audio stream are stored in one continuous
+  // buffer. Samples at the same timestamp are stored one after another. For
+  // example, for a stereo stream with channels L and R that contains samples
+  // with timestamps 0, 1, 2, etc., the samples are stored in one buffer as
+  // "L0 R0 L1 R1 L2 R2 ...".
   kSbMediaAudioFrameStorageTypeInterleaved,
+
+  // The samples of each channel are stored in their own continuous buffer.
+  // For example, for a stereo stream with channels L and R that contains
+  // samples with timestamps 0, 1, 2, etc., the samples are stored in two
+  // buffers "L0 L1 L2 ..." and "R0 R1 R2 ...".
   kSbMediaAudioFrameStorageTypePlanar,
 } SbMediaAudioFrameStorageType;
 
 // The set of information required by the decoder or player for each video
 // sample.
 typedef struct SbMediaVideoSampleInfo {
-  // Whether the associated sample is a key frame (I-frame). Video key frames
-  // must always start with SPS and PPS NAL units.
+  // Indicates whether the associated sample is a key frame (I-frame).
+  // Video key frames must always start with SPS and PPS NAL units.
   bool is_key_frame;
 
   // The frame width of this sample, in pixels. Also could be parsed from the
@@ -148,11 +155,11 @@
   // The platform-defined index of the associated audio output.
   int index;
 
-  // The type of audio connector. Will be the empty kSbMediaAudioConnectorNone
+  // The type of audio connector. Will be the empty |kSbMediaAudioConnectorNone|
   // if this device cannot provide this information.
   SbMediaAudioConnector connector;
 
-  // The expected latency of audio over this output, in microseconds, or 0 if
+  // The expected latency of audio over this output, in microseconds, or |0| if
   // this device cannot provide this information.
   SbTime latency;
 
@@ -160,8 +167,8 @@
   SbMediaAudioCodingType coding_type;
 
   // The number of audio channels currently supported by this device output, or
-  // 0 if this device cannot provide this information, in which case the caller
-  // can probably assume stereo output.
+  // |0| if this device cannot provide this information, in which case the
+  // caller can probably assume stereo output.
   int number_of_channels;
 } SbMediaAudioConfiguration;
 
@@ -170,18 +177,14 @@
 // decoder.
 //
 // The Sequence Header consists of a little-endian hexadecimal encoded
-// WAVEFORMATEX structure followed by an Audio-specific configuration field.
-//
-// Specification of WAVEFORMATEX structure:
+// |WAVEFORMATEX| structure followed by an Audio-specific configuration field.
+// The |WAVEFORMATEX| structure is specified at:
 // http://msdn.microsoft.com/en-us/library/dd390970(v=vs.85).aspx
-//
-// AudioSpecificConfig defined here in section 1.6.2.1:
-// http://read.pudn.com/downloads98/doc/comm/401153/14496/ISO_IEC_14496-3%20Part%203%20Audio/C036083E_SUB1.PDF
 typedef struct SbMediaAudioHeader {
   // The waveform-audio format type code.
   uint16_t format_tag;
 
-  // The number of audio channels in this format. 1 for mono, 2 for stereo.
+  // The number of audio channels in this format. |1| for mono, |2| for stereo.
   uint16_t number_of_channels;
 
   // The sampling rate.
@@ -193,13 +196,14 @@
   // Byte block alignment, e.g, 4.
   uint16_t block_alignment;
 
-  // The bit depth for the stream this represents, e.g. 8 or 16.
+  // The bit depth for the stream this represents, e.g. |8| or |16|.
   uint16_t bits_per_sample;
 
   // The size, in bytes, of the audio_specific_config.
   uint16_t audio_specific_config_size;
 
-  // The AudioSpecificConfig, as specified in ISO/IEC-14496-3.
+  // The AudioSpecificConfig, as specified in ISO/IEC-14496-3, section 1.6.2.1:
+  // http://read.pudn.com/downloads98/doc/comm/401153/14496/ISO_IEC_14496-3%20Part%203%20Audio/C036083E_SUB1.PDF
   int8_t audio_specific_config[8];
 } SbMediaAudioHeader;
 
@@ -209,73 +213,99 @@
 
 // --- Functions -------------------------------------------------------------
 
-// Returns whether decoding |video_codec|, |audio_codec|, and decrypting using
-// |key_system| is supported together by this platform.  If |video_codec| is
-// kSbMediaVideoCodecNone or |audio_codec| is kSbMediaAudioCodecNone, this
-// function should return true if |key_system| is supported on the platform to
-// decode any supported input formats.
+// Indicates whether this platform supports decoding |video_codec| and
+// |audio_codec| along with decrypting using |key_system|. If |video_codec| is
+// |kSbMediaVideoCodecNone| or if |audio_codec| is |kSbMediaAudioCodecNone|,
+// this function should return |true| as long as |key_system| is supported on
+// the platform to decode any supported input formats.
+//
+// |video_codec|: The |SbMediaVideoCodec| being checked for platform
+//   compatibility.
+// |audio_codec|: The |SbMediaAudioCodec| being checked for platform
+//   compatibility.
+// |key_system|: The key system being checked for platform compatibility.
 SB_EXPORT bool SbMediaIsSupported(SbMediaVideoCodec video_codec,
                                   SbMediaAudioCodec audio_codec,
                                   const char* key_system);
 
-// Returns whether a given combination of |frame_width| x |frame_height| frames
-// at |bitrate| and |fps| is supported on this platform with |video_codec|. If
-// |video_codec| is not supported under any condition, this function will always
-// return false.
+// Indicates whether a given combination of
+// (|frame_width| x |frame_height|) frames at |bitrate| and |fps| is supported
+// on this platform with |video_codec|. If |video_codec| is not supported under
+// any condition, this function returns |false|.
 //
-// Any of the parameters may be set to 0 to mean that they shouldn't be
+// Setting any of the parameters to |0| indicates that they shouldn't be
 // considered.
+//
+// |video_codec|: The video codec used in the media content.
+// |frame_width|: The frame width of the media content.
+// |frame_height|: The frame height of the media content.
+// |bitrate|: The bitrate of the media content.
+// |fps|: The number of frames per second in the media content.
 SB_EXPORT bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec,
                                        int frame_width,
                                        int frame_height,
                                        int64_t bitrate,
                                        int fps);
 
-// Returns whether |audio_codec| is supported on this platform at |bitrate|. If
-// |audio_codec| is not supported under any condition, this function will always
-// return false.
+// Indicates whether this platform supports |audio_codec| at |bitrate|.
+// If |audio_codec| is not supported under any condition, this function
+// returns |false|.
+//
+// |audio_codec|: The media's audio codec (|SbMediaAudioCodec|).
+// |bitrate|: The media's bitrate.
 SB_EXPORT bool SbMediaIsAudioSupported(SbMediaVideoCodec audio_codec,
                                        int64_t bitrate);
 
-// Returns information on whether the playback of the specific media described
-// by |mime| and encrypted using |key_system| can be played.
-// |mime| contains the mime information of the media in the form of 'video/webm'
-// or 'video/mp4; codecs="avc1.42001E"'.  It may include arbitrary parameters
-// like "codecs", "channels", etc..
-// |key_system| should be a lower case in fhe form of
-// "com.example.somesystem" as suggested by
-// https://w3c.github.io/encrypted-media/#key-system
+// Returns information about whether the playback of the specific media
+// described by |mime| and encrypted using |key_system| can be played.
+//
+// Note that neither |mime| nor |key_system| can be NULL. This function returns
+// |kSbMediaSupportNotSupported| if either is NULL.
+//
+// |mime|: The mime information of the media in the form of |video/webm|
+//   or |video/mp4; codecs="avc1.42001E"|. It may include arbitrary parameters
+//   like "codecs", "channels", etc.
+// |key_system|: A lowercase value in fhe form of "com.example.somesystem"
+// as suggested by https://w3c.github.io/encrypted-media/#key-system
 // that can be matched exactly with known DRM key systems of the platform.
 // When |key_system| is an empty string, the return value is an indication for
 // non-encrypted media.
-// Note that both |mime| and |key_system| cannot be NULL.  This function returns
-// kSbMediaSupportNotSupported if any of them is NULL.
 SB_EXPORT SbMediaSupportType
 SbMediaCanPlayMimeAndKeySystem(const char* mime, const char* key_system);
 
-// Returns the number of audio outputs currently available on this device.  It
-// is expected that, even if the number of outputs or their audio configurations
-// can't be determined, the platform will at least return a single output that
-// supports at least stereo.
+// Returns the number of audio outputs currently available on this device.
+// Even if the number of outputs or their audio configurations can't be
+// determined, it is expected that the platform will at least return a single
+// output that supports at least stereo.
 SB_EXPORT int SbMediaGetAudioOutputCount();
 
-// Places the current physical audio configuration of audio output
-// |output_index| on this device into |out_configuration|, which must not be
-// NULL, or returns false if nothing could be determined on this platform, or if
-// |output_index| doesn't exist on this device.
+// Retrieves the current physical audio configuration of audio output
+// |output_index| on this device and places it in |out_configuration|,
+// which must not be NULL.
+//
+// This function returns |false| if nothing could be determined on this
+// platform or if |output_index| does not exist on this device.
+//
+// |out_configuration|: The variable that holds the audio configuration
+//   information.
 SB_EXPORT bool SbMediaGetAudioConfiguration(
     int output_index,
     SbMediaAudioConfiguration* out_configuration);
 
-// Returns whether output copy protection is currently enabled on all capable
-// outputs. If true, then non-protection-capable outputs are expected to be
+// Indicates whether output copy protection is currently enabled on all capable
+// outputs. If |true|, then non-protection-capable outputs are expected to be
 // blanked.
 SB_EXPORT bool SbMediaIsOutputProtected();
 
 // Enables or disables output copy protection on all capable outputs. If
 // enabled, then non-protection-capable outputs are expected to be blanked.
-// Returns whether the operation was successful. Returns a success even if the
-// call was redundant.
+//
+// The return value indicates whether the operation was successful, and the
+// function returns a success even if the call is redundant in that it doesn't
+// change the current value.
+//
+// |enabled|: Indicates whether output protection is enabled (|true|) or
+//   disabled.
 SB_EXPORT bool SbMediaSetOutputProtection(bool enabled);
 
 #ifdef __cplusplus
diff --git a/src/starboard/memory.h b/src/starboard/memory.h
index f48b44e..51102d6 100644
--- a/src/starboard/memory.h
+++ b/src/starboard/memory.h
@@ -11,13 +11,29 @@
 // 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.
+
+// Module Overview: Starboard Memory module
 //
-// Memory allocation, alignment, copying, and comparing.
+// Defines functions for memory allocation, alignment, copying, and comparing.
 //
-// DO NOT CALL SbMemoryAllocateUnchecked(), SbMemoryAllocateChecked()
-// SbMemoryReallocateUnchecked(), SbMemoryReallocateChecked(),
-// SbMemoryAllocateAlignedUnchecked(), SbMemoryAllocateAlignedChecked(),
-// SbMemoryFree(), SbMemoryFreeAligned(). They are internal.
+// #### Porters
+//
+// All of the "Unchecked" and "Free" functions must be implemented, but they
+// should not be called directly. The Starboard platform wraps them with extra
+// accounting under certain circumstances.
+//
+// #### Porters and Cobalt developers
+//
+// Nobody should call the "Checked", "Unchecked" or "Free" functions directly
+// because that evades Starboard's memory tracking. In both port implementations
+// and Cobalt code, you should always call SbMemoryAllocate and
+// SbMemoryDeallocate rather than SbMemoryAllocateUnchecked and SbMemoryFree.
+//
+// - The "checked" functions are SbMemoryAllocateChecked(),
+//   SbMemoryReallocateChecked(), and SbMemoryAllocateAlignedChecked().
+// - The "unchecked" functions are SbMemoryAllocateUnchecked(),
+//   SbMemoryReallocateUnchecked(), and SbMemoryAllocateAlignedUnchecked().
+// - The "free" functions are SbMemoryFree() and SbMemoryFreeAligned().
 
 #ifndef STARBOARD_MEMORY_H_
 #define STARBOARD_MEMORY_H_
@@ -64,46 +80,63 @@
   }
 }
 
-// Allocates a chunk of memory of at least |size| bytes, returning it. If unable
-// to allocate the memory, it returns NULL. If |size| is 0, it may return NULL
-// or it may return a unique pointer value that can be passed to
-// SbMemoryDeallocate. Meant to be a drop-in replacement for malloc.
+// Allocates and returns a chunk of memory of at least |size| bytes. This
+// function should be called from the Cobalt codebase. It is intended to
+// be a drop-in replacement for |malloc|.
 //
-// This memory function should be called from the Cobalt codebase.
+// Note that this function returns |NULL| if it is unable to allocate the
+// memory.
+//
+// |size|: The amount of memory to be allocated. If |size| is 0, the function
+//   may return |NULL| or it may return a unique pointer value that can be
+//   passed to SbMemoryDeallocate.
 SB_EXPORT void* SbMemoryAllocate(size_t size);
 
-// Attempts to resize |memory| to be at least |size| bytes, without touching the
-// contents. If it cannot perform the fast resize, it will allocate a new chunk
-// of memory, copy the contents over, and free the previous chunk, returning a
-// pointer to the new chunk. If it cannot perform the slow resize, it will
-// return NULL, leaving the given memory chunk unchanged. |memory| may be NULL,
-// in which case it behaves exactly like SbMemoryAllocateUnchecked.  If |size|
-// is 0, it may return NULL or it may return a unique pointer value that can be
-// passed to SbMemoryDeallocate. Meant to be a drop-in replacement for realloc.
+// Attempts to resize |memory| to be at least |size| bytes, without touching
+// the contents of memory.
+// - If the function cannot perform the fast resize, it allocates a new chunk
+//   of memory, copies the contents over, and frees the previous chunk,
+//   returning a pointer to the new chunk.
+// - If the function cannot perform the slow resize, it returns |NULL|,
+//   leaving the given memory chunk unchanged.
 //
-// This memory function should be called from the Cobalt codebase.
+// This function should be called from the Cobalt codebase. It is meant
+// to be a drop-in replacement for |realloc|.
+//
+// |memory|: The chunk of memory to be resized. |memory| may be NULL, in which
+//   case it behaves exactly like SbMemoryAllocateUnchecked.
+// |size|: The size to which |memory| will be resized. If |size| is |0|,
+//   the function may return |NULL| or it may return a unique pointer value
+//   that can be passed to SbMemoryDeallocate.
 SB_EXPORT void* SbMemoryReallocate(void* memory, size_t size);
 
-// Allocates a chunk of memory of at least |size| bytes, aligned to
-// |alignment|, returning it. |alignment| must be a power of two, otherwise
-// behavior is undefined. If unable to allocate the memory, it returns NULL.
-// If |size| is 0, it may return NULL or it may return a unique aligned pointer
-// value that can be passed to SbMemoryDeallocateAligned. Meant to be a drop-in
-// replacement for memalign.
+// Allocates and returns a chunk of memory of at least |size| bytes, aligned
+// to |alignment|. This function should be called from the Cobalt codebase.
+// It is meant to be a drop-in replacement for |memalign|.
 //
-// This memory function should be called from the Cobalt codebase.
+// The function returns |NULL| if it cannot allocate the memory. In addition,
+// the function's behavior is undefined if |alignment| is not a power of two.
+//
+// |alignment|: The way that data is arranged and accessed in memory. The value
+//   must be a power of two.
+// |size|: The size of the memory to be allocated. If |size| is |0|, the
+//   function may return |NULL| or it may return a unique aligned pointer value
+//   that can be passed to SbMemoryDeallocateAligned.
 SB_EXPORT void* SbMemoryAllocateAligned(size_t alignment, size_t size);
 
-// Frees a previously allocated chunk of memory. If |memory| is NULL, then it
-// does nothing.  Meant to be a drop-in replacement for free.
+// Frees a previously allocated chunk of memory. If |memory| is NULL, then the
+// operation is a no-op. This function should be called from the Cobalt
+// codebase. It is meant to be a drop-in replacement for |free|.
 //
-// This memory function should be called from the Cobalt codebase.
+// |memory|: The chunk of memory to be freed.
 SB_EXPORT void SbMemoryDeallocate(void* memory);
 
-// Frees a previously allocated chunk of aligned memory. If |memory| is NULL,
-// then it does nothing.  Meant to be a drop-in replacement for _aligned_free.
-//
-// This memory function should be called from the Cobalt codebase.
+// Frees a previously allocated chunk of aligned memory. This function should
+// be called from the Cobalt codebase. It is meant to be a drop-in replacement
+// for |_aligned_free|.
+
+// |memory|: The chunk of memory to be freed. If |memory| is NULL, then the
+//   function is a no-op.
 SB_EXPORT void SbMemoryDeallocateAligned(void* memory);
 
 /////////////////////////////////////////////////////////////////
@@ -148,19 +181,24 @@
 
 #if SB_HAS(MMAP)
 // Allocates |size_bytes| worth of physical memory pages and maps them into an
-// available virtual region. |flags| is the bitwise or of the protection flags
-// for the mapped memory as specified in SbMemoryMapFlags. On some platforms,
-// |name| appears in the debugger and can be up to 32 bytes. Returns
-// SB_MEMORY_MAP_FAILED on failure, as NULL is a valid return value.
+// available virtual region. This function returns |SB_MEMORY_MAP_FAILED| on
+// failure. |NULL| is a valid return value.
+//
+// |size_bytes|: The amount of physical memory pages to be allocated.
+// |flags|: The bitwise OR of the protection flags for the mapped memory
+//   as specified in |SbMemoryMapFlags|.
+// |name|: A value that appears in the debugger on some platforms. The value
+//   can be up to 32 bytes.
 SB_EXPORT void* SbMemoryMap(int64_t size_bytes, int flags, const char* name);
 
 // Unmap |size_bytes| of physical pages starting from |virtual_address|,
-// returning true on success. After this, [virtual_address, virtual_address +
-// size_bytes) will not be read/writable. SbMemoryUnmap() can unmap multiple
-// contiguous regions that were mapped with separate calls to
-// SbMemoryMap(). E.g. if one call to SbMemoryMap(0x1000) returns (void*)0xA000
-// and another call to SbMemoryMap(0x1000) returns (void*)0xB000,
-// SbMemoryUnmap(0xA000, 0x2000) should free both.
+// returning |true| on success. After this function completes,
+// [virtual_address, virtual_address + size_bytes) will not be read/writable.
+// This function can unmap multiple contiguous regions that were mapped with
+// separate calls to SbMemoryMap(). For example, if one call to
+// |SbMemoryMap(0x1000)| returns |(void*)0xA000|, and another call to
+// |SbMemoryMap(0x1000)| returns |(void*)0xB000|,
+// |SbMemoryUnmap(0xA000, 0x2000)| should free both regions.
 SB_EXPORT bool SbMemoryUnmap(void* virtual_address, int64_t size_bytes);
 
 #if SB_CAN(MAP_EXECUTABLE_MEMORY)
@@ -172,51 +210,78 @@
 #endif
 #endif  // SB_HAS(MMAP)
 
-// Gets the stack bounds for the current thread, placing the highest addressable
-// byte + 1 in |out_high|, and the lowest addressable byte in |out_low|.
+// Gets the stack bounds for the current thread.
+//
+// |out_high|: The highest addressable byte + 1 for the current thread.
+// |out_low|: The lowest addressable byte for the current thread.
 SB_EXPORT void SbMemoryGetStackBounds(void** out_high, void** out_low);
 
 // Copies |count| sequential bytes from |source| to |destination|, without
-// support for the |source| and |destination| regions overlapping.  Behavior is
-// undefined if |destination| or |source| are NULL. Does nothing if |count| is
-// 0. Returns |destination|, for some reason. Meant to be a drop-in replacement
-// for memcpy.
+// support for the |source| and |destination| regions overlapping. This
+// function is meant to be a drop-in replacement for |memcpy|.
+//
+// The function's behavior is undefined if |destination| or |source| are NULL,
+// and the function is a no-op if |count| is 0. The return value is
+// |destination|.
+//
+// |destination|: The destination of the copied memory.
+// |source|: The source of the copied memory.
+// |count|: The number of sequential bytes to be copied.
 SB_EXPORT void* SbMemoryCopy(void* destination,
                              const void* source,
                              size_t count);
 
 // Copies |count| sequential bytes from |source| to |destination|, with support
-// for the |source| and |destination| regions overlapping.  Behavior is
-// undefined if |destination| or |source| are NULL. Does nothing if |count| is
-// 0. Returns |destination|, for some reason. Meant to be a drop-in replacement
-// for memmove.
+// for the |source| and |destination| regions overlapping. This function is
+// meant to be a drop-in replacement for |memmove|.
+//
+// The function's behavior is undefined if |destination| or |source| are NULL,
+// and the function is a no-op if |count| is 0. The return value is
+// |destination|.
+//
+// |destination|: The destination of the copied memory.
+// |source|: The source of the copied memory.
+// |count|: The number of sequential bytes to be copied.
 SB_EXPORT void* SbMemoryMove(void* destination,
                              const void* source,
                              size_t count);
 
 // Fills |count| sequential bytes starting at |destination|, with the unsigned
-// char coercion of |byte_value|. Behavior is undefined if |destination| is
-// NULL. Returns |destination|, for some reason. Does nothing if |count| is 0.
-// Meant to be a drop-in replacement for memset.
+// char coercion of |byte_value|. This function is meant to be a drop-in
+// replacement for |memset|.
+//
+// The function's behavior is undefined if |destination| is NULL, and the
+// function is a no-op if |count| is 0. The return value is |destination|.
+//
+// |destination|: The destination of the copied memory.
+// |count|: The number of sequential bytes to be set.
 SB_EXPORT void* SbMemorySet(void* destination, int byte_value, size_t count);
 
 // Compares the contents of the first |count| bytes of |buffer1| and |buffer2|.
-// returns -1 if |buffer1| is "less-than" |buffer2|, 0 if they are equal, or 1
-// if |buffer1| is "greater-than" |buffer2|.  Meant to be a drop-in replacement
-// for memcmp.
+// This function returns:
+// - |-1| if |buffer1| is "less-than" |buffer2|
+// - |0| if |buffer1| and |buffer2| are equal
+// - |1| if |buffer1| is "greater-than" |buffer2|.
+//
+// This function is meant to be a drop-in replacement for |memcmp|.
+//
+// |buffer1|: The first buffer to be compared.
+// |buffer2|: The second buffer to be compared.
+// |count|: The number of bytes to be compared.
 SB_EXPORT int SbMemoryCompare(const void* buffer1,
                               const void* buffer2,
                               size_t count);
 
-// Finds the lower 8-bits of |value| in the first |count| bytes of |buffer|,
-// returning a pointer to the first found occurrence, or NULL if not
-// found. Meant to be a drop-in replacement for memchr.
+// Finds the lower 8-bits of |value| in the first |count| bytes of |buffer|
+// and returns either a pointer to the first found occurrence or |NULL| if
+// the value is not found. This function is meant to be a drop-in replacement
+// for |memchr|.
 SB_EXPORT const void* SbMemoryFindByte(const void* buffer,
                                        int value,
                                        size_t count);
 
-// A wrapper that implements a drop-in replacement for calloc, since some
-// packages actually seem to use it.
+// A wrapper that implements a drop-in replacement for |calloc|, which is used
+// in some packages.
 static SB_C_INLINE void* SbMemoryCalloc(size_t count, size_t size) {
   size_t total = count * size;
   void* result = SbMemoryAllocate(total);
diff --git a/src/starboard/memory_reporter.h b/src/starboard/memory_reporter.h
new file mode 100644
index 0000000..1a17c38
--- /dev/null
+++ b/src/starboard/memory_reporter.h
@@ -0,0 +1,105 @@
+// 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.
+
+// Module Overview: Memory Reporting API.
+//
+// Provides an interface for memory reporting.
+
+#ifndef STARBOARD_MEMORY_REPORTER_H_
+#define STARBOARD_MEMORY_REPORTER_H_
+
+#include "starboard/configuration.h"
+#include "starboard/export.h"
+#include "starboard/types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// These are callbacks used by SbMemoryReporter to report memory
+// allocation and deallocation.
+///////////////////////////////////////////////////////////////////////////////
+
+// A function to report a memory allocation from SbMemoryAllocate(). Note that
+// operator new calls SbMemoryAllocate which will delegate to this callback.
+typedef void (*SbMemoryReporterOnAlloc)(void* context, const void* memory,
+                                        size_t size);
+
+// A function to report a memory deallocation from SbMemoryDeallcoate(). Note
+// that operator delete calls SbMemoryDeallocate which will delegate to this
+// callback.
+typedef void (*SbMemoryReporterOnDealloc)(void* context, const void* memory);
+
+// A function to report a memory mapping from SbMemoryMap().
+typedef void (*SbMemoryReporterOnMapMemory)(void* context, const void* memory,
+                                            size_t size);
+
+// A function to report a memory unmapping from SbMemoryUnmap().
+typedef void (*SbMemoryReporterOnUnMapMemory)(void* context,
+                                              const void* memory,
+                                              size_t size);
+
+// SbMemoryReporter allows memory reporting via user-supplied functions.
+// The void* context is passed to every call back.
+// It's strongly recommended that C-Style struct initialization is used
+// so that the arguments can be typed check by the compiler.
+// For example,
+//  SbMemoryReporter mem_reporter = { MallocCallback, .... context };
+struct SbMemoryReporter {
+  // Callback to report allocations.
+  SbMemoryReporterOnAlloc on_alloc_cb;
+
+  // Callback to report deallocations.
+  SbMemoryReporterOnDealloc on_dealloc_cb;
+
+  // Callback to report memory map.
+  SbMemoryReporterOnMapMemory on_mapmem_cb;
+
+  // Callback to report memory unmap.
+  SbMemoryReporterOnUnMapMemory on_unmapmem_cb;
+
+  // Optional, is passed to callbacks as first argument.
+  void* context;
+};
+
+// Sets the MemoryReporter. Any previous memory reporter is unset. No lifetime
+// management is done internally on input pointer.
+//
+// Returns true if the memory reporter was set with no errors. If an error
+// was reported then check the log for why it failed.
+//
+// Note that other than a thread-barrier-write of the input pointer, there is
+// no thread safety guarantees with this function due to performance
+// considerations. It's recommended that this be called once during the
+// lifetime of the program, or not at all. Do not delete the supplied pointer,
+// ever.
+// Example (Good):
+//    SbMemoryReporter* mem_reporter = new ...;
+//    SbMemorySetReporter(&mem_reporter);
+//    ...
+//    SbMemorySetReporter(NULL);  // allow value to leak.
+// Example (Bad):
+//    SbMemoryReporter* mem_reporter = new ...;
+//    SbMemorySetReporter(&mem_reporter);
+//    ...
+//    SbMemorySetReporter(NULL);
+//    delete mem_reporter;        // May crash.
+SB_EXPORT bool SbMemorySetReporter(struct SbMemoryReporter* tracker);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // STARBOARD_MEMORY_REPORTER_H_
diff --git a/src/starboard/microphone.h b/src/starboard/microphone.h
index b742f71..52464c3 100644
--- a/src/starboard/microphone.h
+++ b/src/starboard/microphone.h
@@ -12,24 +12,29 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Microphone creation, control, audio data fetching and destruction.
-// Multiple calls to |SbMicrophoneOpen| and |SbMicrophoneClose| are allowed, and
-// the implementation also should take care of same calls of open and close in a
-// row on a microphone.
-// This API is not threadsafe and must be called from a single thread.
+// Module Overview: Starboard Microphone module
+//
+// Defines functions for microphone creation, control, audio data fetching,
+// and destruction. This module supports multiple calls to |SbMicrophoneOpen|
+// and |SbMicrophoneClose|, and the implementation should handle multiple calls
+// to one of those functions on the same microphone. For example, your
+// implementation should handle cases where |SbMicrophoneOpen| is called twice
+// on the same microphone without a call to |SbMicrophoneClose| in between.
+//
+// This API is not thread-safe and must be called from a single thread.
 //
 // How to use this API:
-// 1) |SbMicrophoneGetAvailableInfos| to get a list of available microphone
+// 1. Call |SbMicrophoneGetAvailableInfos| to get a list of available microphone
 //    information.
-// 2) Choose one to create microphone |SbMicrophoneCreate| with enough buffer
-//    size and sample rate. The sample rate can be verified by
-//    |SbMicrophoneIsSampleRateSupported|.
-// 3) Open the microphone port and start recording audio data by
-//    |SbMicrophoneOpen|.
-// 4) Periodically read out the data from microphone by |SbMicrophoneRead|.
-// 5) Close the microphone port and stop recording audio data by
-//    |SbMicrophoneClose|.
-// 6) Destroy the microphone |SbMicrophoneDestroy|.
+// 2. Create a supported microphone, using |SbMicrophoneCreate|, with enough
+//    buffer size and sample rate. Use |SbMicrophoneIsSampleRateSupported| to
+//    verify the sample rate.
+// 3. Use |SbMicrophoneOpen| to open the microphone port and start recording
+//    audio data.
+// 4. Periodically read out the data from microphone with |SbMicrophoneRead|.
+// 5. Call |SbMicrophoneClose| to close the microphone port and stop recording
+//    audio data.
+// 6. Destroy the microphone with |SbMicrophoneDestroy|.
 
 #ifndef STARBOARD_MICROPHONE_H_
 #define STARBOARD_MICROPHONE_H_
@@ -46,10 +51,10 @@
 
 // All possible microphone types.
 typedef enum SbMicrophoneType {
-  // Build-in microphone in camera.
+  // Built-in microphone in camera.
   kSbMicrophoneCamera,
 
-  // Microphone in the headset which can be wire or wireless USB headset.
+  // Microphone in the headset that can be a wired or wireless USB headset.
   kSbMicrophoneUSBHeadset,
 
   // Microphone in the VR headset.
@@ -58,19 +63,19 @@
   // Microphone in the analog headset.
   kSBMicrophoneAnalogHeadset,
 
-  // Unknown microphone type. Microphone other than those listed or could be
-  // either of those listed.
+  // Unknown microphone type. The microphone could be different than the other
+  // enum descriptions or could fall under one of those descriptions.
   kSbMicrophoneUnknown,
 } SbMicrophoneType;
 
-// An opaque handle to an implementation-private structure representing a
-// microphone id.
+// An opaque handle to an implementation-private structure that represents a
+// microphone ID.
 typedef struct SbMicrophoneIdPrivate* SbMicrophoneId;
 
-// Well-defined value for an invalid microphone id handle.
+// Well-defined value for an invalid microphone ID handle.
 #define kSbMicrophoneIdInvalid ((SbMicrophoneId)NULL)
 
-// Returns whether the given microphone id is valid.
+// Indicates whether the given microphone ID is valid.
 static SB_C_INLINE bool SbMicrophoneIdIsValid(SbMicrophoneId id) {
   return id != kSbMicrophoneIdInvalid;
 }
@@ -83,99 +88,108 @@
   // Microphone type.
   SbMicrophoneType type;
 
-  // Microphone max supported sampling rate.
+  // The microphone's maximum supported sampling rate.
   int max_sample_rate_hz;
 
   // The minimum read size required for each read from microphone.
   int min_read_size;
 } SbMicrophoneInfo;
 
-// An opaque handle to an implementation-private structure representing a
+// An opaque handle to an implementation-private structure that represents a
 // microphone.
 typedef struct SbMicrophonePrivate* SbMicrophone;
 
 // Well-defined value for an invalid microphone handle.
 #define kSbMicrophoneInvalid ((SbMicrophone)NULL)
 
-// Returns whether the given microphone is valid.
+// Indicates whether the given microphone is valid.
 static SB_C_INLINE bool SbMicrophoneIsValid(SbMicrophone microphone) {
   return microphone != kSbMicrophoneInvalid;
 }
 
-// Gets all currently-available microphone information and the results are
-// stored in |out_info_array|. |info_array_size| is the size of
-// |out_info_array|.
-// Returns the number of the available microphones. A negative return
-// value indicates that an internal error has occurred. If the number of
-// available microphones is larger than |info_array_size|, |out_info_array| will
-// be filled up with as many available microphones as possible and the actual
-// number of available microphones will be returned.
+// Retrieves all currently available microphone information and stores it in
+// |out_info_array|. The return value is the number of the available
+// microphones. If the number of available microphones is larger than
+// |info_array_size|, then |out_info_array| is filled up with as many available
+// microphones as possible and the actual number of available microphones is
+// returned. A negative return value indicates that an internal error occurred.
+//
+// |out_info_array|: All currently available information about the microphone
+//   is placed into this output parameter.
+// |info_array_size|: The size of |out_info_array|.
 SB_EXPORT int SbMicrophoneGetAvailable(SbMicrophoneInfo* out_info_array,
                                        int info_array_size);
 
-// Returns true if the sample rate is supported by the microphone.
+// Indicates whether the microphone supports the sample rate.
 SB_EXPORT bool SbMicrophoneIsSampleRateSupported(SbMicrophoneId id,
                                                  int sample_rate_in_hz);
 
-// Creates a microphone with |id|, audio sample rate in HZ, and the size of
-// the cached audio buffer.
+// Creates a microphone with the specified ID, audio sample rate, and cached
+// audio buffer size. Starboard only requires support for creating one
+// microphone at a time, and implementations may return an error if a second
+// microphone is created before the first is destroyed.
 //
-// If you try to create a microphone that has already been initialized or
-// the sample rate is unavailable or the buffer size is invalid, it should
-// return |kSbMicrophoneInvalid|. |buffer_size_bytes| is the size of the buffer
-// where signed 16-bit integer audio data is temporarily cached to during the
-// capturing. The audio data will be removed from the audio buffer if it has
-// been read. New audio data can be read from this buffer in smaller chunks than
-// this size. |buffer_size_bytes| must be set to a value greater than zero and
-// the ideal size is 2^n. We only require support for creating one microphone at
-// a time, and that implementations may return an error if a second microphone
-// is created before destroying the first.
+// The function returns the newly created SbMicrophone object. However, if you
+// try to create a microphone that has already been initialized, if the sample
+// rate is unavailable, or if the buffer size is invalid, the function should
+// return |kSbMicrophoneInvalid|.
+//
+// |id|: The ID that will be assigned to the newly created SbMicrophone.
+// |sample_rate_in_hz|: The new microphone's audio sample rate in Hz.
+// |buffer_size_bytes|: The size of the buffer where signed 16-bit integer
+//   audio data is temporarily cached to during the capturing. The audio data
+//   is removed from the audio buffer if it has been read, and new audio data
+//   can be read from this buffer in smaller chunks than this size. This
+//   parameter must be set to a value greater than zero and the ideal size is
+//   |2^n|.
 SB_EXPORT SbMicrophone SbMicrophoneCreate(SbMicrophoneId id,
                                           int sample_rate_in_hz,
                                           int buffer_size_bytes);
 
 // Opens the microphone port and starts recording audio on |microphone|.
 //
-// Once started, the client will have to periodically call |SbMicrophoneRead| to
+// Once started, the client needs to periodically call |SbMicrophoneRead| to
 // receive the audio data. If the microphone has already been started, this call
-// will clear the unread buffer. The return value indicates if the microphone is
-// open.
+// clears the unread buffer. The return value indicates whether the microphone
+// is open.
+// |microphone|: The microphone that will be opened and will start recording
+// audio.
 SB_EXPORT bool SbMicrophoneOpen(SbMicrophone microphone);
 
-// Closes the microphone port and stops recording audio on |microphone|.
-//
-// Clear the unread buffer if it is not empty. If the microphone has already
-// been stopped, this call would be ignored. The return value indicates if the
+// Closes the microphone port, stops recording audio on |microphone|, and
+// clears the unread buffer if it is not empty. If the microphone has already
+// been stopped, this call is ignored. The return value indicates whether the
 // microphone is closed.
+//
+// |microphone|: The microphone to close.
 SB_EXPORT bool SbMicrophoneClose(SbMicrophone microphone);
 
-// Gets the recorded audio data from the microphone.
+// Retrieves the recorded audio data from the microphone and writes that data
+// to |out_audio_data|.
 //
-// |out_audio_data| is where the recorded audio data is written to.
-// |audio_data_size| is the number of requested bytes. The return value is zero
-// or the positive number of bytes that were read. Neither the return value nor
-// |audio_data_size| exceeds the buffer size. Negative return value indicates
-// an error. This function should be called frequently, otherwise microphone
-// only buffers |buffer_size| bytes which is configured in |SbMicrophoneCreate|
-// and the new audio data will be thrown out. No audio data will be read from a
-// stopped microphone. If |audio_data_size| is smaller than |min_read_size| of
-// |SbMicrophoneInfo|, the extra audio data which is already read from device
-// will be discarded.
+// The return value is zero or the positive number of bytes that were read.
+// Neither the return value nor |audio_data_size| exceeds the buffer size.
+// A negative return value indicates that an error occurred.
+//
+// This function should be called frequently. Otherwise, the microphone only
+// buffers |buffer_size| bytes as configured in |SbMicrophoneCreate| and the
+// new audio data is thrown out. No audio data is read from a stopped
+// microphone.
+//
+// |microphone|: The microphone from which to retrieve recorded audio data.
+// |out_audio_data|: The buffer to which the retrieved data will be written.
+// |audio_data_size|: The number of requested bytes. If |audio_data_size| is
+//   smaller than |min_read_size| of |SbMicrophoneInfo|, the extra audio data
+//   that has already been read from the device is discarded.
 SB_EXPORT int SbMicrophoneRead(SbMicrophone microphone,
                                void* out_audio_data,
                                int audio_data_size);
 
-// Destroys a microphone. If the microphone is in started state, it will be
-// stopped first and then be destroyed. Any data that has been recorded and not
-// read will be thrown away.
+// Destroys a microphone. If the microphone is in started state, it is first
+// stopped and then destroyed. Any data that has been recorded and not read
+// is thrown away.
 SB_EXPORT void SbMicrophoneDestroy(SbMicrophone microphone);
 
-// Returns the Google Speech API key. The platform manufacturer is responsible
-// for registering a Google Speech API key for their products. In the API
-// Console (http://developers.google.com/console), you are able to enable the
-// Speech APIs and generate a Speech API key.
-SB_EXPORT const char* SbMicrophoneGetSpeechApiKey();
-
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/src/starboard/mutex.h b/src/starboard/mutex.h
index d06c752..953fa0d 100644
--- a/src/starboard/mutex.h
+++ b/src/starboard/mutex.h
@@ -12,7 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// A mutually exclusive lock that can be used to coordinate with other threads.
+// Module Overview: Starboard Mutex module
+//
+// Defines a mutually exclusive lock that can be used to coordinate with other
+// threads.
 
 #ifndef STARBOARD_MUTEX_H_
 #define STARBOARD_MUTEX_H_
@@ -37,31 +40,46 @@
   kSbMutexDestroyed,
 } SbMutexResult;
 
-// Returns whether the given result is a success.
+// Indicates whether the given result is a success. A value of |true| indicates
+// that the mutex was acquired.
+//
+// |result|: The result being checked.
 static SB_C_FORCE_INLINE bool SbMutexIsSuccess(SbMutexResult result) {
   return result == kSbMutexAcquired;
 }
 
-// Creates a new mutex, placing the handle to the newly created mutex in
-// |out_mutex|. Returns whether able to create a new mutex.
+// Creates a new mutex. The return value indicates whether the function
+// was able to create a new mutex.
+//
+// |out_mutex|: The handle to the newly created mutex.
 SB_EXPORT bool SbMutexCreate(SbMutex* out_mutex);
 
-// Destroys a mutex, returning whether the destruction was successful. The mutex
-// specified by |mutex| is invalidated.
+// Destroys a mutex. The return value indicates whether the destruction was
+// successful.
+//
+// |mutex|: The mutex to be invalidated.
 SB_EXPORT bool SbMutexDestroy(SbMutex* mutex);
 
-// Acquires |mutex|, blocking indefinitely, returning the acquisition result.
-// SbMutexes are not reentrant, so a recursive acquisition will block forever.
+// Acquires |mutex|, blocking indefinitely. The return value identifies
+// the acquisition result. SbMutexes are not reentrant, so a recursive
+// acquisition blocks forever.
+//
+// |mutex|: The mutex to be acquired.
 SB_EXPORT SbMutexResult SbMutexAcquire(SbMutex* mutex);
 
-// Acquires |mutex|, without blocking, returning the acquisition result.
-// SbMutexes are not reentrant, so a recursive acquisition will always fail.
+// Acquires |mutex|, without blocking. The return value identifies
+// the acquisition result. SbMutexes are not reentrant, so a recursive
+// acquisition always fails.
+//
+// |mutex|: The mutex to be acquired.
 SB_EXPORT SbMutexResult SbMutexAcquireTry(SbMutex* mutex);
 
-// Releases |mutex| held by the current thread, returning whether the release
-// was successful. Releases should always be successful if the mutex is held by
-// the current thread.
-SB_EXPORT bool SbMutexRelease(SbMutex* handle);
+// Releases |mutex| held by the current thread. The return value indicates
+// whether the release was successful. Releases should always be successful
+// if |mutex| is held by the current thread.
+//
+// |mutex|: The mutex to be released.
+SB_EXPORT bool SbMutexRelease(SbMutex* mutex);
 
 #ifdef __cplusplus
 }  // extern "C"
diff --git a/src/starboard/nplb/decode_target_create_test.cc b/src/starboard/nplb/decode_target_create_test.cc
index 9358c68..e8f3ea4 100644
--- a/src/starboard/nplb/decode_target_create_test.cc
+++ b/src/starboard/nplb/decode_target_create_test.cc
@@ -53,7 +53,7 @@
   SbDecodeTargetDestroy(target);
   EXPECT_TRUE(SbBlitterDestroySurface(surface));
 }
-#else  // SB_HAS(BLITTER)
+#elif SB_HAS(GLES2)  // SB_HAS(BLITTER)
 // clang-format off
 EGLint const kAttributeList[] = {
   EGL_RED_SIZE, 8,
@@ -66,7 +66,7 @@
   EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
   EGL_CONFORMANT, EGL_OPENGL_ES2_BIT,
   EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-  EGL_NONE
+  EGL_NONE,
 };
 // clang-format on
 
@@ -160,17 +160,31 @@
   glGenTextures(1, &texture_handle);
   glBindTexture(GL_TEXTURE_2D, texture_handle);
   glTexImage2D(GL_TEXTURE_2D, 0 /*level*/, GL_RGBA, 256, 256, 0 /*border*/,
-               GL_RGBA8, GL_UNSIGNED_BYTE, NULL /*data*/);
+               GL_RGBA, GL_UNSIGNED_BYTE, NULL /*data*/);
   glBindTexture(GL_TEXTURE_2D, 0);
 
   SbDecodeTarget target = SbDecodeTargetCreate(
       display_, context_, kSbDecodeTargetFormat1PlaneRGBA, &texture_handle);
-  GLuint plane = SbDecodeTargetGetPlane(target, kSbDecodeTargetPlaneRGBA);
-  EXPECT_EQ(texture_handle, plane);
-  SbDecodeTargetDestroy(target);
+  if (SbDecodeTargetIsValid(target)) {
+    GLuint plane = SbDecodeTargetGetPlane(target, kSbDecodeTargetPlaneRGBA);
+    EXPECT_EQ(texture_handle, plane);
+    SbDecodeTargetDestroy(target);
+  }
   glDeleteTextures(1, &texture_handle);
 }
 
+#else  // SB_HAS(BLITTER)
+
+TEST(SbDecodeTargetTest, SunnyDayCreate) {
+  // When graphics are not enabled, we expect to always create a
+  // kSbDecodeTargetInvalid, and get NULL back for planes.
+  EXPECT_EQ(SbDecodeTargetCreate(kSbDecodeTargetFormat1PlaneRGBA),
+            kSbDecodeTargetInvalid);
+  EXPECT_EQ(
+      SbDecodeTargetGetPlane(kSbDecodeTargetInvalid, kSbDecodeTargetPlaneRGBA),
+      NULL);
+}
+
 #endif  // SB_HAS(BLITTER)
 
 }  // namespace
diff --git a/src/starboard/nplb/decode_target_provider_test.cc b/src/starboard/nplb/decode_target_provider_test.cc
index a5fece5..cd53e40 100644
--- a/src/starboard/nplb/decode_target_provider_test.cc
+++ b/src/starboard/nplb/decode_target_provider_test.cc
@@ -43,130 +43,110 @@
   int called_release;
 };
 
-template <typename T>
-SbDecodeTargetProvider MakeProvider() {
-  return {&T::Acquire, &T::Release};
-}
-
-void AcquireFalse() {
-  SbDecodeTarget target = SbDecodeTargetAcquireFromProvider(
-      kSbDecodeTargetFormat1PlaneRGBA, 16, 16);
-  bool valid = SbDecodeTargetIsValid(target);
-  EXPECT_FALSE(valid);
-  if (valid) {
-    SbDecodeTargetDestroy(target);
+void AcquireFalse(SbDecodeTargetProvider* provider) {
+  if (provider) {
+    SbDecodeTarget target = SbDecodeTargetAcquireFromProvider(
+        provider, kSbDecodeTargetFormat1PlaneRGBA, 16, 16);
+    bool valid = SbDecodeTargetIsValid(target);
+    EXPECT_FALSE(valid);
+    if (valid) {
+      SbDecodeTargetDestroy(target);
+    }
   }
 }
 
-void ReleaseInvalid() {
-  SbDecodeTargetReleaseToProvider(kSbDecodeTargetInvalid);
-}
-
-TEST(SbDecodeTargetProviderTest, SunnyDayRegisterUnregister) {
-  ProviderContext context = {};
-  SbDecodeTargetProvider provider = MakeProvider<ProviderContext>();
-  ASSERT_TRUE(SbDecodeTargetRegisterProvider(&provider, &context));
-  SbDecodeTargetUnregisterProvider(&provider, &context);
+void ReleaseInvalid(SbDecodeTargetProvider* provider) {
+  if (provider) {
+    SbDecodeTargetReleaseToProvider(provider, kSbDecodeTargetInvalid);
+  }
 }
 
 TEST(SbDecodeTargetProviderTest, SunnyDayCallsThroughToProvider) {
   ProviderContext context = {};
-  SbDecodeTargetProvider provider = MakeProvider<ProviderContext>();
-  ASSERT_TRUE(SbDecodeTargetRegisterProvider(&provider, &context));
+  SbDecodeTargetProvider provider = {&ProviderContext::Acquire,
+                                     &ProviderContext::Release,
+                                     reinterpret_cast<void*>(&context)};
+
   EXPECT_EQ(0, context.called_acquire);
   EXPECT_EQ(0, context.called_release);
 
-  AcquireFalse();
+  AcquireFalse(&provider);
   EXPECT_EQ(1, context.called_acquire);
-  AcquireFalse();
+  AcquireFalse(&provider);
   EXPECT_EQ(2, context.called_acquire);
 
-  ReleaseInvalid();
+  ReleaseInvalid(&provider);
   EXPECT_EQ(1, context.called_release);
-  ReleaseInvalid();
+  ReleaseInvalid(&provider);
   EXPECT_EQ(2, context.called_release);
-
-  SbDecodeTargetUnregisterProvider(&provider, &context);
 }
 
-TEST(SbDecodeTargetProviderTest, SunnyDayRegisterOver) {
+TEST(SbDecodeTargetProviderTest, SunnyDayMultipleProviders) {
   ProviderContext context = {};
-  SbDecodeTargetProvider provider = MakeProvider<ProviderContext>();
-  ASSERT_TRUE(SbDecodeTargetRegisterProvider(&provider, &context));
+  SbDecodeTargetProvider provider = {&ProviderContext::Acquire,
+                                     &ProviderContext::Release,
+                                     reinterpret_cast<void*>(&context)};
 
   ProviderContext context2 = {};
-  SbDecodeTargetProvider provider2 = MakeProvider<ProviderContext>();
-  ASSERT_TRUE(SbDecodeTargetRegisterProvider(&provider2, &context2));
+  SbDecodeTargetProvider provider2 = {&ProviderContext::Acquire,
+                                      &ProviderContext::Release,
+                                      reinterpret_cast<void*>(&context2)};
 
-  AcquireFalse();
+  AcquireFalse(&provider2);
   EXPECT_EQ(1, context2.called_acquire);
   EXPECT_EQ(0, context.called_acquire);
-  AcquireFalse();
+  AcquireFalse(&provider2);
   EXPECT_EQ(2, context2.called_acquire);
   EXPECT_EQ(0, context.called_acquire);
 
-  ReleaseInvalid();
+  ReleaseInvalid(&provider2);
   EXPECT_EQ(1, context2.called_release);
   EXPECT_EQ(0, context.called_release);
-  ReleaseInvalid();
+  ReleaseInvalid(&provider2);
   EXPECT_EQ(2, context2.called_release);
   EXPECT_EQ(0, context.called_release);
-
-  SbDecodeTargetUnregisterProvider(&provider2, &context2);
 }
 
 TEST(SbDecodeTargetProviderTest, RainyDayAcquireNoProvider) {
-  AcquireFalse();
+  AcquireFalse(NULL);
 }
 
 TEST(SbDecodeTargetProviderTest, RainyDayReleaseNoProvider) {
-  ReleaseInvalid();
+  ReleaseInvalid(NULL);
 }
 
-TEST(SbDecodeTargetProviderTest, RainyDayUnregisterUnregistered) {
+TEST(SbDecodeTargetProviderTest, RainyDayMultipleProviders) {
   ProviderContext context = {};
-  SbDecodeTargetProvider provider = MakeProvider<ProviderContext>();
-  SbDecodeTargetUnregisterProvider(&provider, &context);
+  SbDecodeTargetProvider provider = {&ProviderContext::Acquire,
+                                     &ProviderContext::Release,
+                                     reinterpret_cast<void*>(&context)};
 
   ProviderContext context2 = {};
-  SbDecodeTargetProvider provider2 = MakeProvider<ProviderContext>();
-  ASSERT_TRUE(SbDecodeTargetRegisterProvider(&provider2, &context2));
-  SbDecodeTargetUnregisterProvider(&provider, &context);
-  SbDecodeTargetUnregisterProvider(&provider, &context2);
-  SbDecodeTargetUnregisterProvider(&provider2, &context);
+  SbDecodeTargetProvider provider2 = {&ProviderContext::Acquire,
+                                      &ProviderContext::Release,
+                                      reinterpret_cast<void*>(&context2)};
 
-  AcquireFalse();
+  AcquireFalse(&provider2);
   EXPECT_EQ(1, context2.called_acquire);
-  AcquireFalse();
+  AcquireFalse(&provider2);
   EXPECT_EQ(2, context2.called_acquire);
 
-  ReleaseInvalid();
+  ReleaseInvalid(&provider2);
   EXPECT_EQ(1, context2.called_release);
-  ReleaseInvalid();
+  ReleaseInvalid(&provider2);
   EXPECT_EQ(2, context2.called_release);
 
-  SbDecodeTargetUnregisterProvider(&provider2, &context2);
-
-  AcquireFalse();
+  AcquireFalse(&provider);
   EXPECT_EQ(2, context2.called_acquire);
-  AcquireFalse();
+  AcquireFalse(&provider);
   EXPECT_EQ(2, context2.called_acquire);
 
-  ReleaseInvalid();
+  ReleaseInvalid(&provider);
   EXPECT_EQ(2, context2.called_release);
-  ReleaseInvalid();
+  ReleaseInvalid(&provider);
   EXPECT_EQ(2, context2.called_release);
 }
 
-TEST(SbDecodeTargetProviderTest, RainyDayUnregisterNull) {
-  ProviderContext context = {};
-  SbDecodeTargetUnregisterProvider(NULL, &context);
-}
-
-TEST(SbDecodeTargetProviderTest, RainyDayUnregisterNullNull) {
-  SbDecodeTargetUnregisterProvider(NULL, NULL);
-}
-
 }  // namespace
 }  // namespace nplb
 }  // namespace starboard
diff --git a/src/starboard/nplb/include_all.c b/src/starboard/nplb/include_all.c
index 5ac5aa1..e55a271 100644
--- a/src/starboard/nplb/include_all.c
+++ b/src/starboard/nplb/include_all.c
@@ -39,6 +39,7 @@
 #include "starboard/player.h"
 #include "starboard/socket.h"
 #include "starboard/socket_waiter.h"
+#include "starboard/speech_synthesis.h"
 #include "starboard/storage.h"
 #include "starboard/string.h"
 #include "starboard/system.h"
diff --git a/src/starboard/nplb/memory_reporter_test.cc b/src/starboard/nplb/memory_reporter_test.cc
new file mode 100644
index 0000000..f49e339
--- /dev/null
+++ b/src/starboard/nplb/memory_reporter_test.cc
@@ -0,0 +1,496 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/configuration.h"
+#include "starboard/memory.h"
+#include "starboard/memory_reporter.h"
+#include "starboard/mutex.h"
+#include "starboard/thread.h"
+#include "starboard/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace starboard {
+namespace nplb {
+namespace {
+
+// This thread local boolean is used to filter allocations and
+// 1) Prevent allocations from other threads.
+// 2) Selectively disable allocations so that unintended allocs from
+//    gTest (ASSERT_XXX) don't cause the current test to fail.
+void InitMemoryTrackingState_ThreadLocal();
+bool GetMemoryTrackingEnabled_ThreadLocal();
+void SetMemoryTrackingEnabled_ThreadLocal(bool value);
+
+// Scoped object that temporary turns off MemoryTracking. This is needed
+// to avoid allocations from gTest being inserted into the memory tracker.
+struct NoMemTracking {
+  bool prev_val;
+  NoMemTracking() {
+    prev_val = GetMemoryTrackingEnabled_ThreadLocal();
+    SetMemoryTrackingEnabled_ThreadLocal(false);
+  }
+  ~NoMemTracking() {
+    SetMemoryTrackingEnabled_ThreadLocal(prev_val);
+  }
+};
+
+// EXPECT_XXX and ASSERT_XXX allocate memory, a big no-no when
+// for unit testing allocations. These overrides disable memory
+// tracking for the duration of the EXPECT and ASSERT operations.
+#define EXPECT_EQ_NO_TRACKING(A, B)                \
+{ NoMemTracking no_memory_tracking_in_this_scope;  \
+  EXPECT_EQ(A, B);                                 \
+}
+
+#define EXPECT_NE_NO_TRACKING(A, B)                \
+{ NoMemTracking no_memory_tracking_in_this_scope;  \
+  EXPECT_NE(A, B);                                 \
+}
+
+#define EXPECT_TRUE_NO_TRACKING(A)                 \
+{ NoMemTracking no_memory_tracking_in_this_scope;  \
+  EXPECT_TRUE(A);                                  \
+}
+
+#define EXPECT_FALSE_NO_TRACKING(A)                \
+{ NoMemTracking no_memory_tracking_in_this_scope;  \
+  EXPECT_FALSE(A);                                 \
+}
+
+#define ASSERT_EQ_NO_TRACKING(A, B)                \
+{ NoMemTracking no_memory_tracking_in_this_scope;  \
+  ASSERT_EQ(A, B);                                 \
+}
+
+#define ASSERT_NE_NO_TRACKING(A, B)                \
+{ NoMemTracking no_memory_tracking_in_this_scope;  \
+  ASSERT_NE(A, B);                                 \
+}
+
+#define ASSERT_TRUE_NO_TRACKING(A)                 \
+{ NoMemTracking no_memory_tracking_in_this_scope;  \
+  ASSERT_TRUE(A);                                  \
+}
+
+#define ASSERT_FALSE_NO_TRACKING(A)                \
+{ NoMemTracking no_memory_tracking_in_this_scope;  \
+  ASSERT_FALSE(A);                                 \
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// A memory reporter that is used to watch allocations from the system.
+class TestMemReporter {
+ public:
+  TestMemReporter() { Construct(); }
+
+  SbMemoryReporter* memory_reporter() {
+    return &memory_reporter_;
+  }
+
+  // Removes this object from listening to allocations.
+  void RemoveGlobalHooks() {
+    SbMemorySetReporter(NULL);
+    // Sleep to allow other threads time to pass through.
+    SbThreadSleep(250 * kSbTimeMillisecond);
+  }
+
+  // Total number allocations outstanding.
+  int number_allocs() const { return number_allocs_; }
+
+  void Clear() {
+    starboard::ScopedLock lock(mutex_);
+    number_allocs_ = 0;
+    last_allocation_ = NULL;
+    last_deallocation_ = NULL;
+    last_mem_map_ = NULL;
+    last_mem_unmap_ = NULL;
+  }
+
+  const void* last_allocation() const {
+    return last_allocation_;
+  }
+  const void* last_deallocation() const {
+    return last_deallocation_;
+  }
+  const void* last_mem_map() const {
+    return last_mem_map_;
+  }
+  const void* last_mem_unmap() const {
+    return last_mem_unmap_;
+  }
+
+ private:
+  // Boilerplate to delegate static function callbacks to the class instance.
+  static void OnMalloc(void* context, const void* memory, size_t size) {
+    TestMemReporter* t = static_cast<TestMemReporter*>(context);
+    t->ReportAlloc(memory, size);
+  }
+
+  static void OnMapMem(void* context, const void* memory, size_t size) {
+    TestMemReporter* t = static_cast<TestMemReporter*>(context);
+    t->ReportMapMem(memory, size);
+  }
+
+  static void OnDealloc(void* context, const void* memory) {
+    TestMemReporter* t = static_cast<TestMemReporter*>(context);
+    t->ReportDealloc(memory);
+  }
+
+  static void SbUnMapMem(void* context, const void* memory, size_t size) {
+    TestMemReporter* t = static_cast<TestMemReporter*>(context);
+    t->ReportUnMapMemory(memory, size);
+  }
+
+  static SbMemoryReporter CreateSbMemoryReporter(TestMemReporter* context) {
+    SbMemoryReporter cb = { OnMalloc, OnDealloc,
+                            OnMapMem, SbUnMapMem,
+                            context };
+    return cb;
+  }
+
+  void ReportAlloc(const void* memory, size_t /*size*/) {
+    if (!GetMemoryTrackingEnabled_ThreadLocal()) {
+      return;
+    }
+    starboard::ScopedLock lock(mutex_);
+    last_allocation_ = memory;
+    number_allocs_++;
+  }
+
+  void ReportMapMem(const void* memory, size_t size) {
+    if (!GetMemoryTrackingEnabled_ThreadLocal()) {
+      return;
+    }
+    starboard::ScopedLock lock(mutex_);
+    last_mem_map_ = memory;
+    number_allocs_++;
+  }
+
+  void ReportDealloc(const void* memory) {
+    if (!GetMemoryTrackingEnabled_ThreadLocal()) {
+      return;
+    }
+    starboard::ScopedLock lock(mutex_);
+    last_deallocation_ = memory;
+    number_allocs_--;
+  }
+
+  void ReportUnMapMemory(const void* memory, size_t size) {
+    if (!GetMemoryTrackingEnabled_ThreadLocal()) {
+      return;
+    }
+    starboard::ScopedLock lock(mutex_);
+    last_mem_unmap_ = memory;
+    number_allocs_--;
+  }
+
+  void Construct() {
+    Clear();
+    memory_reporter_ = CreateSbMemoryReporter(this);
+  }
+
+  SbMemoryReporter memory_reporter_;
+  starboard::Mutex mutex_;
+  const void* last_allocation_;
+  const void* last_deallocation_;
+  const void* last_mem_map_;
+  const void* last_mem_unmap_;
+  int number_allocs_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Needed by all tests that require a memory tracker to be installed. On the
+// first test the test memory tracker is installed and then after the last test
+// the memory tracker is removed.
+class MemoryReportingTest : public ::testing::Test {
+ public:
+  TestMemReporter* mem_reporter() { return s_test_alloc_tracker_; }
+  bool MemoryReportingEnabled() const {
+    return s_memory_reporter_error_enabled_;
+  }
+
+ protected:
+  // Global setup - runs before the first test in the series.
+  static void SetUpTestCase() {
+    InitMemoryTrackingState_ThreadLocal();
+    // global init test code should run here.
+    if (s_test_alloc_tracker_ == NULL) {
+      s_test_alloc_tracker_ = new TestMemReporter;
+    }
+    s_memory_reporter_error_enabled_ =
+        SbMemorySetReporter(s_test_alloc_tracker_->memory_reporter());
+  }
+
+  // Global Teardown after last test has run it's course.
+  static void TearDownTestCase() {
+    s_test_alloc_tracker_->RemoveGlobalHooks();
+  }
+
+  // Per test setup.
+  virtual void SetUp() {
+    mem_reporter()->Clear();
+    // Allows current thread to capture memory allocations. If this wasn't
+    // done then background threads spawned by a framework could notify this
+    // class about allocations and fail the test.
+    SetMemoryTrackingEnabled_ThreadLocal(true);
+  }
+
+  // Per test teardown.
+  virtual void TearDown() {
+    SetMemoryTrackingEnabled_ThreadLocal(false);
+    if (mem_reporter()->number_allocs() != 0) {
+      ADD_FAILURE_AT(__FILE__, __LINE__) << "Memory Leak detected.";
+    }
+    mem_reporter()->Clear();
+  }
+  static TestMemReporter* s_test_alloc_tracker_;
+  static bool s_memory_reporter_error_enabled_;
+};
+TestMemReporter* MemoryReportingTest::s_test_alloc_tracker_ = NULL;
+bool MemoryReportingTest::s_memory_reporter_error_enabled_ = false;
+
+///////////////////////////////////////////////////////////////////////////////
+// TESTS.
+// There are two sets of tests: POSITIVE and NEGATIVE.
+//  The positive tests are active when STARBOARD_ALLOWS_MEMORY_TRACKING is
+//  defined and test that memory tracking is enabled.
+//  NEGATIVE tests ensure that tracking is disabled when
+//  STARBOARD_ALLOWS_MEMORY_TRACKING is not defined.
+// When adding new tests:
+//  POSITIVE tests are named normally.
+//  NEGATIVE tets are named with "No" prefixed to the beginning.
+//  Example:
+//   TEST_F(MemoryReportingTest, CapturesAllocDealloc) <--- POSITIVE test.
+//   TEST_F(MemoryReportingTest, NoCapturesAllocDealloc) <- NEGATIVE test.
+//  All positive & negative tests are grouped together.
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef STARBOARD_ALLOWS_MEMORY_TRACKING
+// These are POSITIVE tests, which test the expectation that when the define
+// STARBOARD_ALLOWS_MEMORY_TRACKING is active that the memory tracker will
+// receive memory allocations notifications.
+//
+// Tests the assumption that the SbMemoryAllocate and SbMemoryDeallocate
+// will report memory allocations.
+TEST_F(MemoryReportingTest, CapturesAllocDealloc) {
+  if (!MemoryReportingEnabled()) {
+    GTEST_SUCCEED() << "Memory reporting is disabled.";
+    return;
+  }
+  EXPECT_EQ_NO_TRACKING(0, mem_reporter()->number_allocs());
+  void* memory = SbMemoryAllocate(4);
+  EXPECT_EQ_NO_TRACKING(1, mem_reporter()->number_allocs());
+
+  EXPECT_EQ_NO_TRACKING(memory, mem_reporter()->last_allocation());
+
+  SbMemoryDeallocate(memory);
+  EXPECT_EQ_NO_TRACKING(mem_reporter()->number_allocs(), 0);
+
+  // Should equal the last allocation.
+  EXPECT_EQ_NO_TRACKING(memory, mem_reporter()->last_deallocation());
+}
+
+// Tests the assumption that SbMemoryReallocate() will report a
+// deallocation and an allocation to the memory tracker.
+TEST_F(MemoryReportingTest, CapturesRealloc) {
+  if (!MemoryReportingEnabled()) {
+    GTEST_SUCCEED() << "Memory reporting is disabled.";
+    return;
+  }
+  void* prev_memory = SbMemoryAllocate(4);
+  void* new_memory = SbMemoryReallocate(prev_memory, 8);
+
+  EXPECT_EQ_NO_TRACKING(new_memory, mem_reporter()->last_allocation());
+  EXPECT_EQ_NO_TRACKING(prev_memory, mem_reporter()->last_deallocation());
+
+  EXPECT_EQ_NO_TRACKING(1, mem_reporter()->number_allocs());
+
+  SbMemoryDeallocate(new_memory);
+  EXPECT_EQ_NO_TRACKING(mem_reporter()->number_allocs(), 0);
+}
+
+// Tests the assumption that the SbMemoryMap and SbMemoryUnmap
+// will report memory allocations.
+TEST_F(MemoryReportingTest, CapturesMemMapUnmap) {
+  if (!MemoryReportingEnabled()) {
+    GTEST_SUCCEED() << "Memory reporting is disabled.";
+    return;
+  }
+  const int64_t kMemSize = 4096;
+  const int kFlags = 0;
+  EXPECT_EQ_NO_TRACKING(0, mem_reporter()->number_allocs());
+  void* mem_chunk = SbMemoryMap(kMemSize, kFlags, "TestMemMap");
+  EXPECT_EQ_NO_TRACKING(1, mem_reporter()->number_allocs());
+
+  // Now unmap the memory and confirm that this memory was reported as free.
+  EXPECT_EQ_NO_TRACKING(mem_chunk, mem_reporter()->last_mem_map());
+  SbMemoryUnmap(mem_chunk, kMemSize);
+  EXPECT_EQ_NO_TRACKING(mem_chunk, mem_reporter()->last_mem_unmap());
+  EXPECT_EQ_NO_TRACKING(0, mem_reporter()->number_allocs());
+}
+
+// Tests the assumption that the operator/delete will report
+// memory allocations.
+TEST_F(MemoryReportingTest, CapturesOperatorNewDelete) {
+  if (!MemoryReportingEnabled()) {
+    GTEST_SUCCEED() << "Memory reporting is disabled.";
+    return;
+  }
+  EXPECT_TRUE_NO_TRACKING(mem_reporter()->number_allocs() == 0);
+  int* my_int = new int();
+  EXPECT_TRUE_NO_TRACKING(mem_reporter()->number_allocs() == 1);
+
+  bool is_last_allocation =
+      my_int == mem_reporter()->last_allocation();
+
+  EXPECT_TRUE_NO_TRACKING(is_last_allocation);
+
+  delete my_int;
+  EXPECT_TRUE_NO_TRACKING(mem_reporter()->number_allocs() == 0);
+
+  // Expect last deallocation to be the expected pointer.
+  EXPECT_EQ_NO_TRACKING(my_int, mem_reporter()->last_deallocation());
+}
+
+#else  // !defined(STARBOARD_ALLOWS_MEMORY_TRACKING)
+// These are NEGATIVE tests, which test the expectation that when the
+// STARBOARD_ALLOWS_MEMORY_TRACKING is undefined that the memory tracker does
+// not receive memory allocations notifications.
+
+TEST_F(MemoryReportingTest, NoCapturesAllocDealloc) {
+  EXPECT_FALSE_NO_TRACKING(MemoryReportingEnabled());
+
+  EXPECT_EQ_NO_TRACKING(0, mem_reporter()->number_allocs());
+  void* memory = SbMemoryAllocate(4);
+  EXPECT_EQ_NO_TRACKING(0, mem_reporter()->number_allocs());
+  EXPECT_EQ_NO_TRACKING(NULL, mem_reporter()->last_allocation());
+
+  SbMemoryDeallocate(memory);
+  EXPECT_EQ_NO_TRACKING(mem_reporter()->number_allocs(), 0);
+  EXPECT_EQ_NO_TRACKING(NULL, mem_reporter()->last_deallocation());
+}
+
+TEST_F(MemoryReportingTest, NoCapturesRealloc) {
+  EXPECT_FALSE_NO_TRACKING(MemoryReportingEnabled());
+  void* prev_memory = SbMemoryAllocate(4);
+  void* new_memory = SbMemoryReallocate(prev_memory, 8);
+
+  EXPECT_EQ_NO_TRACKING(NULL, mem_reporter()->last_allocation());
+  EXPECT_EQ_NO_TRACKING(NULL, mem_reporter()->last_deallocation());
+  EXPECT_EQ_NO_TRACKING(0, mem_reporter()->number_allocs());
+
+  SbMemoryDeallocate(new_memory);
+  EXPECT_EQ_NO_TRACKING(mem_reporter()->number_allocs(), 0);
+}
+
+TEST_F(MemoryReportingTest, NoCapturesMemMapUnmap) {
+  EXPECT_FALSE_NO_TRACKING(MemoryReportingEnabled());
+  const int64_t kMemSize = 4096;
+  const int kFlags = 0;
+  EXPECT_EQ_NO_TRACKING(0, mem_reporter()->number_allocs());
+  void* mem_chunk = SbMemoryMap(kMemSize, kFlags, "TestMemMap");
+  EXPECT_EQ_NO_TRACKING(0, mem_reporter()->number_allocs());
+
+  // Now unmap the memory and confirm that this memory was reported as free.
+  EXPECT_EQ_NO_TRACKING(NULL, mem_reporter()->last_mem_map());
+  SbMemoryUnmap(mem_chunk, kMemSize);
+  EXPECT_EQ_NO_TRACKING(NULL, mem_reporter()->last_mem_unmap());
+  EXPECT_EQ_NO_TRACKING(0, mem_reporter()->number_allocs());
+}
+
+TEST_F(MemoryReportingTest, NoCapturesOperatorNewDelete) {
+  EXPECT_FALSE_NO_TRACKING(MemoryReportingEnabled());
+  EXPECT_EQ_NO_TRACKING(0, mem_reporter()->number_allocs());
+  int* my_int = new int();
+  EXPECT_EQ_NO_TRACKING(0, mem_reporter()->number_allocs());
+  EXPECT_EQ_NO_TRACKING(NULL, mem_reporter()->last_allocation());
+
+  delete my_int;
+  EXPECT_EQ_NO_TRACKING(0, mem_reporter()->number_allocs());
+  EXPECT_EQ_NO_TRACKING(NULL, mem_reporter()->last_deallocation());
+}
+
+#endif  // !defined(STARBOARD_ALLOWS_MEMORY_TRACKING)
+
+/////////////////////////////// Implementation ////////////////////////////////
+
+// Simple ThreadLocalBool class which allows a default value to be
+// true or false.
+class ThreadLocalBool {
+ public:
+  ThreadLocalBool() {
+    // NULL is the destructor.
+    slot_ = SbThreadCreateLocalKey(NULL);
+  }
+
+  ~ThreadLocalBool() {
+    SbThreadDestroyLocalKey(slot_);
+  }
+
+  void SetEnabled(bool value) {
+    SetEnabledThreadLocal(value);
+  }
+
+  bool Enabled() const {
+    return GetEnabledThreadLocal();
+  }
+
+ private:
+  void SetEnabledThreadLocal(bool value) {
+    void* bool_as_pointer;
+    if (value) {
+      bool_as_pointer = reinterpret_cast<void*>(0x1);
+    } else {
+      bool_as_pointer = NULL;
+    }
+    SbThreadSetLocalValue(slot_, bool_as_pointer);
+  }
+
+  bool GetEnabledThreadLocal() const {
+    void* ptr = SbThreadGetLocalValue(slot_);
+    return ptr != NULL;
+  }
+
+  mutable SbThreadLocalKey slot_;
+  bool default_value_;
+};
+
+void InitMemoryTrackingState_ThreadLocal() {
+  GetMemoryTrackingEnabled_ThreadLocal();
+}
+
+static ThreadLocalBool* GetMemoryTrackingState() {
+  static ThreadLocalBool* thread_local_bool = new ThreadLocalBool();
+  return thread_local_bool;
+}
+
+bool GetMemoryTrackingEnabled_ThreadLocal() {
+  return GetMemoryTrackingState()->Enabled();
+}
+
+void SetMemoryTrackingEnabled_ThreadLocal(bool value) {
+  GetMemoryTrackingState()->SetEnabled(value);
+}
+
+// No use for these macros anymore.
+#undef EXPECT_EQ_NO_TRACKING
+#undef EXPECT_TRUE_NO_TRACKING
+#undef EXPECT_FALSE_NO_TRACKING
+#undef ASSERT_EQ_NO_TRACKING
+#undef ASSERT_TRUE_NO_TRACKING
+#undef ASSERT_FALSE_NO_TRACKING
+
+}  // namespace
+}  // namespace nplb
+}  // namespace starboard
diff --git a/src/starboard/nplb/nplb.gyp b/src/starboard/nplb/nplb.gyp
index cf31d23..dc39b90 100644
--- a/src/starboard/nplb/nplb.gyp
+++ b/src/starboard/nplb/nplb.gyp
@@ -122,12 +122,12 @@
         'memory_map_test.cc',
         'memory_move_test.cc',
         'memory_reallocate_test.cc',
+        'memory_reporter_test.cc',
         'memory_set_test.cc',
         'microphone_close_test.cc',
         'microphone_create_test.cc',
         'microphone_destroy_test.cc',
         'microphone_get_available_test.cc',
-        'microphone_get_speech_api_key_test.cc',
         'microphone_is_sample_rate_supported_test.cc',
         'microphone_open_test.cc',
         'microphone_read_test.cc',
@@ -163,6 +163,7 @@
         'socket_waiter_wait_test.cc',
         'socket_waiter_wait_timed_test.cc',
         'socket_waiter_wake_up_test.cc',
+        'speech_synthesis_basic_test.cc',
         'storage_close_record_test.cc',
         'storage_delete_record_test.cc',
         'storage_get_record_size_test.cc',
diff --git a/src/starboard/nplb/once_test.cc b/src/starboard/nplb/once_test.cc
index b40817a..a504fc2 100644
--- a/src/starboard/nplb/once_test.cc
+++ b/src/starboard/nplb/once_test.cc
@@ -22,6 +22,7 @@
 

 namespace starboard {

 namespace nplb {

+namespace {

 

 int s_global_value;

 

@@ -149,5 +150,14 @@
   EXPECT_EQ(0, s_global_value);

 }

 

-}  // namespace nplb

-}  // namespace starboard

+SB_ONCE_INITIALIZE_FUNCTION(int, GetIntSingleton);

+TEST(SbOnceTest, InitializeOnceMacroFunction) {

+  int* int_singelton = GetIntSingleton();

+  ASSERT_TRUE(int_singelton);

+  EXPECT_EQ(0, *int_singelton)

+      << "Singleton Macro does not default initialize.";

+}

+

+}  // namespace.

+}  // namespace nplb.

+}  // namespace starboard.

diff --git a/src/starboard/nplb/player_create_test.cc b/src/starboard/nplb/player_create_test.cc
index d81c51c..dffa92c 100644
--- a/src/starboard/nplb/player_create_test.cc
+++ b/src/starboard/nplb/player_create_test.cc
@@ -44,7 +44,12 @@
   SbPlayer player =

       SbPlayerCreate(window, kSbMediaVideoCodecH264, kSbMediaAudioCodecAac,

                      SB_PLAYER_NO_DURATION, kSbDrmSystemInvalid, &audio_header,

-                     NULL, NULL, NULL, NULL);

+                     NULL, NULL, NULL, NULL

+#if SB_VERSION(3)

+                     ,

+                     NULL

+#endif

+                     );  // NOLINT

   EXPECT_TRUE(SbPlayerIsValid(player));

   SbPlayerDestroy(player);

   SbWindowDestroy(window);

diff --git a/src/starboard/nplb/speech_synthesis_basic_test.cc b/src/starboard/nplb/speech_synthesis_basic_test.cc
new file mode 100644
index 0000000..4e01d35
--- /dev/null
+++ b/src/starboard/nplb/speech_synthesis_basic_test.cc
@@ -0,0 +1,28 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/speech_synthesis.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if SB_HAS(SPEECH_SYNTHESIS) && SB_VERSION(3)
+
+TEST(SbSpeechSynthesisBasicTest, Basic) {
+  // An implementation must at least support US English
+  EXPECT_TRUE(SbSpeechSynthesisSetLanguage("en-US"));
+  SbSpeechSynthesisSpeak("Hello");
+  SbSpeechSynthesisCancel();
+}
+
+#endif  // SB_HAS(SPEECH_SYNTHESIS) && SB_VERSION(3)
+
diff --git a/src/starboard/nplb/system_get_property_test.cc b/src/starboard/nplb/system_get_property_test.cc
index de94895..ef4078f 100644
--- a/src/starboard/nplb/system_get_property_test.cc
+++ b/src/starboard/nplb/system_get_property_test.cc
@@ -70,6 +70,9 @@
   BasicTest(kSbSystemPropertyChipsetModelNumber, false, true, __LINE__);
   BasicTest(kSbSystemPropertyFirmwareVersion, false, true, __LINE__);
   BasicTest(kSbSystemPropertyNetworkOperatorName, false, true, __LINE__);
+#if SB_VERSION(2)
+  BasicTest(kSbSystemPropertySpeechApiKey, false, true, __LINE__);
+#endif  // SB_VERSION(2)
 
   if (IsCEDevice(SbSystemGetDeviceType())) {
     BasicTest(kSbSystemPropertyBrandName, true, true, __LINE__);
diff --git a/src/starboard/once.h b/src/starboard/once.h
index 03039c9..8eba6cb 100644
--- a/src/starboard/once.h
+++ b/src/starboard/once.h
@@ -1,43 +1,75 @@
-// Copyright 2015 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.

-

-// Onces represent initializations that should only ever happen once per

-// process, in a thread safe way.

-

-#ifndef STARBOARD_ONCE_H_

-#define STARBOARD_ONCE_H_

-

-#include "starboard/export.h"

-#include "starboard/thread_types.h"

-#include "starboard/types.h"

-

-#ifdef __cplusplus

-extern "C" {

-#endif

-

-// Function pointer type for methods that can be called va the SbOnce() system.

-typedef void (*SbOnceInitRoutine)(void);

-

-// If SbOnce() was never called before on with |once_control|, this function

-// will run |init_routine| in a thread-safe way and then returns true.  If

-// SbOnce() was called before, the function returns (true) immediately.

-// If |once_control| or |init_routine| are invalid, the function returns false.

-SB_EXPORT bool SbOnce(SbOnceControl* once_control,

-                      SbOnceInitRoutine init_routine);

-

-#ifdef __cplusplus

-}

-#endif

-

-#endif  // STARBOARD_ONCE_H_

+// Copyright 2015 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.
+
+// Module Overview: Starboard Once module
+//
+// Onces represent initializations that should only ever happen once per
+// process, in a thread-safe way.
+
+#ifndef STARBOARD_ONCE_H_
+#define STARBOARD_ONCE_H_
+
+#include "starboard/export.h"
+#include "starboard/thread_types.h"
+#include "starboard/types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Function pointer type for methods that can be called via the SbOnce() system.
+typedef void (*SbOnceInitRoutine)(void);
+
+// Thread-safely runs |init_routine| only once.
+// - If this |once_control| has not run a function yet, this function runs
+//   |init_routine| in a thread-safe way and then returns |true|.
+// - If SbOnce() was called with |once_control| before, the function returns
+//   |true| immediately.
+// - If |once_control| or |init_routine| is invalid, the function returns
+//   |false|.
+SB_EXPORT bool SbOnce(SbOnceControl* once_control,
+                      SbOnceInitRoutine init_routine);
+
+#ifdef __cplusplus
+// Defines a function that will initialize the indicated type once and return
+// it. This initialization is thread safe if the type being created is side
+// effect free.
+//
+// These macros CAN ONLY BE USED IN A CC file, never in a header file.
+//
+// Example (in cc file):
+//   SB_ONCE_INITIALIZE_FUNCTION(MyClass, GetOrCreateMyClass)
+//   ..
+//   MyClass* instance = GetOrCreateMyClass();
+//   MyClass* instance2 = GetOrCreateMyClass();
+//   DCHECK_EQ(instance, instance2);
+#define SB_ONCE_INITIALIZE_FUNCTION(Type, FunctionName)    \
+Type* FunctionName() {                                     \
+  static SbOnceControl s_once_flag = SB_ONCE_INITIALIZER;  \
+  static Type* s_singleton = NULL;                         \
+  struct Local {                                           \
+    static void Init() {                                   \
+      s_singleton = new Type();                            \
+    }                                                      \
+  };                                                       \
+  SbOnce(&s_once_flag, Local::Init);                       \
+  return s_singleton;                                      \
+}
+#endif  // __cplusplus
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // STARBOARD_ONCE_H_
diff --git a/src/starboard/player.h b/src/starboard/player.h
index 333c9dd..6fbc381 100644
--- a/src/starboard/player.h
+++ b/src/starboard/player.h
@@ -12,7 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// An interface for controlling playback of media elementary streams.
+// Module Overview: Starboard Player module
+//
+// Defines an interface for controlling playback of media elementary streams.
 
 #ifndef STARBOARD_PLAYER_H_
 #define STARBOARD_PLAYER_H_
@@ -21,6 +23,7 @@
 
 #if SB_HAS(PLAYER)
 
+#include "starboard/decode_target.h"
 #include "starboard/drm.h"
 #include "starboard/export.h"
 #include "starboard/media.h"
@@ -49,7 +52,7 @@
 
 // An indicator of the general playback state.
 typedef enum SbPlayerState {
-  // The player has just been initialized.  It is expecting an SbPlayerSeek()
+  // The player has just been initialized. It is expecting an SbPlayerSeek()
   // call to enter the prerolling state.
   kSbPlayerStateInitialized,
 
@@ -59,8 +62,8 @@
   // Prerolling after a Seek.
   kSbPlayerStatePrerolling,
 
-  // The player is presenting media, and it is either actively playing in
-  // real-time, or it is paused.  Note that the implementation should use this
+  // The player is presenting media, and it is either paused or actively
+  // playing in real-time. Note that the implementation should use this
   // state to signal that the preroll has been finished.
   kSbPlayerStatePresenting,
 
@@ -70,8 +73,8 @@
   // The player has been destroyed, and will send no more callbacks.
   kSbPlayerStateDestroyed,
 
-  // The player encounters an error.  It is expecting an SbPlayerDestroy() call
-  // to tear down the player.  Any call to other functions maybe ignored and
+  // The player encountered an error. It expects an SbPlayerDestroy() call
+  // to tear down the player. Calls to other functions may be ignored and
   // callbacks may not be triggered.
   kSbPlayerStateError,
 } SbPlayerState;
@@ -178,108 +181,146 @@
 
 // Creates a player that will be displayed on |window| for the specified
 // |video_codec| and |audio_codec|, acquiring all resources needed to operate
-// it, and returning an opaque handle to it. |window| can be kSbWindowInvalid
-// for platforms where video will be only displayed on a particular window
-// which the underlying implementation already has access to. If |video_codec|
-// is kSbMediaVideoCodecNone, the player is an audio-only player. Otherwise, the
-// player is an audio/video decoder. |audio_codec| should never be
-// kSbMediaAudioCodecNone. The expectation is that a new player will be created
-// and destroyed for every playback.
+// it, and returning an opaque handle to it. The expectation is that a new
+// player will be created and destroyed for every playback.
 //
-// |duration_pts| is the expected media duration in 90KHz ticks (PTS). It may be
-// set to SB_PLAYER_NO_DURATION for live streams.
+// This function returns the created player. Note the following:
+// - The associated decoder of the returned player should be assumed to not be
+//   in |kSbPlayerDecoderStateNeedsData| until SbPlayerSeek() has been called
+//   on it.
+// - It is expected either that the thread that calls SbPlayerCreate is the same
+//   thread that calls the other |SbPlayer| functions for that player, or that
+//   there is a mutex guarding calls into each |SbPlayer| instance.
+// - If there is a platform limitation on how many players can coexist
+//   simultaneously, then calls made to this function that attempt to exceed
+//   that limit will return |kSbPlayerInvalid|.
 //
-// If the media stream has encrypted portions, then an appropriate DRM system
-// must first be created with SbDrmCreateSystem() and passed into |drm_system|.
-// If not, then |drm_system| may be kSbDrmSystemInvalid.
+// |window|: The window that will display the player. |window| can be
+//   |kSbWindowInvalid| for platforms where video is only displayed on a
+//   particular window that the underlying implementation already has access to.
 //
-// If |audio_codec| is kSbMediaAudioCodecAac, then the caller must provide a
-// populated |audio_header|. Otherwise, this may be NULL.
+// |video_codec|: The video codec used for the player. If |video_codec| is
+//   |kSbMediaVideoCodecNone|, the player is an audio-only player. If
+//   |video_codec| is any other value, the player is an audio/video decoder.
 //
-// If not NULL, the player will call |sample_deallocator_func| on an internal
-// thread to free the sample buffers passed into SbPlayerWriteSample().
+// |audio_codec|: The audio codec used for the player. The value should never
+//   be |kSbMediaAudioCodecNone|. In addition, the caller must provide a
+//   populated |audio_header| if the audio codec is |kSbMediaAudioCodecAac|.
 //
-// If not NULL, the decoder will call |decoder_status_func| on an internal
-// thread to provide an update on the decoder's status. No work should be done
-// on this thread, it should just signal the client thread interacting with the
-// decoder.
+// |duration_pts|: The expected media duration in 90KHz ticks (PTS). It may be
+//   set to |SB_PLAYER_NO_DURATION| for live streams.
 //
-// If not NULL, the player will call |player_status_func| on an internal thread
-// to provide an update on the playback status. No work should be done on this
-// thread, it should just signal the client thread interacting with the decoder.
+// |drm_system|: If the media stream has encrypted portions, then this
+//   parameter provides an appropriate DRM system, created with
+//   |SbDrmCreateSystem()|. If the stream does not have encrypted portions,
+//   then |drm_system| may be |kSbDrmSystemInvalid|.
 //
-// |context| will be passed back into all callbacks, and is generally used to
-// point at a class or struct that contains state associated with the player.
+// |audio_header|: Note that the caller must provide a populated |audio_header|
+//   if the audio codec is |kSbMediaAudioCodecAac|. Otherwise, |audio_header|
+//   can be NULL. See media.h for the format of the |SbMediaAudioHeader| struct.
 //
-// The associated decoder of the returned player should be assumed to be not in
-// kSbPlayerDecoderStateNeedsData until SbPlayerSeek() has been called on it.
+// |sample_deallocator_func|: If not |NULL|, the player calls this function
+//   on an internal thread to free the sample buffers passed into
+//   SbPlayerWriteSample().
 //
-// It is expected that the thread that calls SbPlayerCreate is the same thread
-// that calls the other SbPlayer functions for that player, or that there is a
-// mutex guarding calls into each SbPlayer instance.
+// |decoder_status_func|: If not |NULL|, the decoder calls this function on an
+//   internal thread to provide an update on the decoder's status. No work
+//   should be done on this thread. Rather, it should just signal the client
+//   thread interacting with the decoder.
 //
-// If there is a platform limitation on how many players can coexist
-// simultaneously, then calls made to this function that attempt to exceed that
-// limit will return kSbPlayerInvalid.
-SB_EXPORT SbPlayer
-SbPlayerCreate(SbWindow window,
-               SbMediaVideoCodec video_codec,
-               SbMediaAudioCodec audio_codec,
-               SbMediaTime duration_pts,
-               SbDrmSystem drm_system,
-               const SbMediaAudioHeader* audio_header,
-               SbPlayerDeallocateSampleFunc sample_deallocate_func,
-               SbPlayerDecoderStatusFunc decoder_status_func,
-               SbPlayerStatusFunc player_status_func,
-               void* context);
+// |player_status_func|: If not |NULL|, the player calls this function on an
+//   internal thread to provide an update on the playback status. No work
+//   should be done on this thread. Rather, it should just signal the client
+//   thread interacting with the decoder.
+//
+// |context|: This is passed to all callbacks and is generally used to point
+//   at a class or struct that contains state associated with the player.
+//
+// |provider|: Only present in Starboard version 3 and up.  If not |NULL|,
+//   then when SB_HAS(PLAYER_PRODUCING_TEXTURE) is true, the player MAY use the
+//   provider to create SbDecodeTargets. A provider could also potentially be
+//   required by the player, in which case, if the provider is not given, the
+//   player will fail by returning kSbPlayerInvalid.
+SB_EXPORT SbPlayer SbPlayerCreate(
+    SbWindow window,
+    SbMediaVideoCodec video_codec,
+    SbMediaAudioCodec audio_codec,
+    SbMediaTime duration_pts,
+    SbDrmSystem drm_system,
+    const SbMediaAudioHeader* audio_header,
+    SbPlayerDeallocateSampleFunc sample_deallocate_func,
+    SbPlayerDecoderStatusFunc decoder_status_func,
+    SbPlayerStatusFunc player_status_func,
+    void* context
+#if SB_VERSION(3)
+    ,
+    SbDecodeTargetProvider* provider
+#endif  // SB_VERSION(3)
+    );  // NOLINT
 
 // Destroys |player|, freeing all associated resources. Each callback must
-// receive one more callback to say that the player was destroyed.  Callbacks
+// receive one more callback to say that the player was destroyed. Callbacks
 // may be in-flight when SbPlayerDestroy is called, and should be ignored once
 // this function is called.
 //
-// It is not allowed to pass |player| into any other SbPlayer function once
-// SbPlayerDestroy has been called on it.
+// It is not allowed to pass |player| into any other |SbPlayer| function once
+// SbPlayerDestroy has been called on that player.
+//
+// |player|: The player to be destroyed.
 SB_EXPORT void SbPlayerDestroy(SbPlayer player);
 
-// Tells the player to freeze playback where it is (if it has already started),
-// reset/flush the decoder pipeline, and go back to the Prerolling state. The
-// player should restart playback once it can display the frame at
-// |seek_to_pts|, or the closest it can get (some players can only seek to
-// I-Frames, for example). The client should send no more audio or video samples
-// until SbPlayerDecoderStatusFunc is called back with
-// kSbPlayerDecoderStateNeedsData, for each required media type.
+// Tells the player to freeze playback (if playback has already started),
+// reset or flush the decoder pipeline, and go back to the Prerolling state.
+// The player should restart playback once it can display the frame at
+// |seek_to_pts|, or the closest it can get. (Some players can only seek to
+// I-Frames, for example.)
 //
-// A call to seek may interrupt another seek.
+// - Seek must be called before samples are sent when starting playback for
+//   the first time, or the client never receives the
+//   |kSbPlayerDecoderStateNeedsData| signal.
+// - A call to seek may interrupt another seek.
+// - After this function is called, the client should not send any more audio
+//   or video samples until |SbPlayerDecoderStatusFunc| is called back with
+//   |kSbPlayerDecoderStateNeedsData| for each required media type.
+//   |SbPlayerDecoderStatusFunc| is the |decoder_status_func| callback function
+//   that was specified when the player was created (SbPlayerCreate).
 //
-// |ticket| is a user-supplied unique ID that will be passed to all subsequent
-// SbPlayerDecoderStatusFunc calls. This is used to filter calls that may have
-// been in flight when SbPlayerSeek is called. To be very specific, once
-// SbPlayerSeek has been called with ticket X, a client should ignore all
-// SbPlayerDecoderStatusFunc calls that don't pass in ticket X.
+// |player|: The SbPlayer in which the seek operation is being performed.
+// |seek_to_pts|: The frame at which playback should begin.
+// |ticket|: A user-supplied unique ID that is be passed to all subsequent
+//   |SbPlayerDecoderStatusFunc| calls. (That is the |decoder_status_func|
+//   callback function specified when calling SbPlayerCreate.)
 //
-// Seek must also be called before samples are sent when starting playback for
-// the first time, or the client will never receive the
-// kSbPlayerDecoderStateNeedsData signal.
+//   The |ticket| value is used to filter calls that may have been in flight
+//   when SbPlayerSeek was called. To be very specific, once SbPlayerSeek has
+//   been called with ticket X, a client should ignore all
+//   |SbPlayerDecoderStatusFunc| calls that do not pass in ticket X.
 SB_EXPORT void SbPlayerSeek(SbPlayer player,
                             SbMediaTime seek_to_pts,
                             int ticket);
 
-// Writes a sample of the given media type to |player|'s input stream.
-// |sample_type| is the type of sample, audio or video. |sample_buffer| is a
-// pointer to a buffer with the data for this sample. This buffer is expected to
-// be a portion of a H.264 bytestream, containing a sequence of whole NAL Units
-// for video, or a complete audio frame. |sample_buffer_size| is the number of
-// bytes in the given sample. |sample_pts| is the timestamp of the sample in
-// 90KHz ticks (PTS), and samples MAY be written "slightly" out-of-order.
-// |video_sample_info| must be provided for every call where |sample_type| is
-// kSbMediaTypeVideo, and must be NULL otherwise.  |sample_drm_info| must be
-// provided for encrypted samples, and must be NULL otherwise.
+// Writes a sample of the given media type to |player|'s input stream. The
+// lifetime of |video_sample_info| and |sample_drm_info| (as well as member
+// |subsample_mapping| contained inside it) are not guaranteed past the call
+// to SbPlayerWriteSample. That means that before returning, the implementation
+// must synchronously copy any information it wants to retain from those
+// structures.
 //
-// The lifetime of |video_sample_info| and |sample_drm_info| (as well as member
-// |subsample_mapping| contained inside it) are not guaranteed past the call to
-// SbPlayerWriteSample, so the implementation must copy any information it wants
-// to retain from those structures synchronously, before it returns.
+// |player|: The player to which the sample is written.
+// |sample_type|: The type of sample being written. See the |SbMediaType|
+//   enum in media.h.
+// |sample_buffer|: A pointer to a buffer with the data for this sample. The
+//   buffer is expected to be a portion of a bytestream of the codec type that
+//   the player was created with. The buffer should contain a sequence of whole
+//   NAL Units for video, or a complete audio frame.
+// |sample_buffer_size|: The number of bytes in the given sample.
+// |sample_pts|: The timestamp of the sample in 90KHz ticks (PTS). Note that
+//   samples MAY be written "slightly" out of order.
+// |video_sample_info|: Information about a video sample. This value is
+//   required if |sample_type| is |kSbMediaTypeVideo|. Otherwise, it must be
+//   |NULL|.
+// |sample_drm_info|: The DRM system for the media sample. This value is
+//   required for encrypted samples. Otherwise, it must be |NULL|.
 SB_EXPORT void SbPlayerWriteSample(
     SbPlayer player,
     SbMediaType sample_type,
@@ -289,19 +330,32 @@
     const SbMediaVideoSampleInfo* video_sample_info,
     const SbDrmSampleInfo* sample_drm_info);
 
-// Writes a marker to |player|'s input stream of |stream_type| that there are no
-// more samples for that media type for the remainder of this media stream.
-// This marker is invalidated, along with the rest of the contents of the
-// stream, after a call to SbPlayerSeek.
+// Writes a marker to |player|'s input stream of |stream_type| indicating that
+// there are no more samples for that media type for the remainder of this
+// media stream. This marker is invalidated, along with the rest of the stream's
+// contents, after a call to SbPlayerSeek.
+//
+// |player|: The player to which the marker is written.
+// |stream_type|: The type of stream for which the marker is written.
 SB_EXPORT void SbPlayerWriteEndOfStream(SbPlayer player,
                                         SbMediaType stream_type);
 
 #if SB_IS(PLAYER_PUNCHED_OUT)
-// Sets the player bounds to the given graphics plane coordinates. Will not take
-// effect until the next graphics frame buffer swap. The default bounds for a
-// player are the full screen. This function should be expected to be called up
-// to once per frame, so implementors should take care to avoid related
-// performance concerns with such frequent calls.
+// Sets the player bounds to the given graphics plane coordinates. The changes
+// do not take effect until the next graphics frame buffer swap. The default
+// bounds for a player is the full screen.
+//
+// This function is called on every graphics frame that changes the video
+// bounds. For example, if the video bounds are being animated, then this will
+// be called at up to 60 Hz. Since the function could be called up to once per
+// frame, implementors should take care to avoid related performance concerns
+// with such frequent calls.
+//
+// |player|: The player that is being resized.
+// |x|: The x-coordinate of the upper-left corner of the player.
+// |y|: The y-coordinate of the upper-left corner of the player.
+// |width|: The width of the player, in pixels.
+// |height|: The height of the player, in pixels.
 SB_EXPORT void SbPlayerSetBounds(SbPlayer player,
                                  int x,
                                  int y,
@@ -309,30 +363,42 @@
                                  int height);
 #endif
 
-// Sets the pause status for |player|. If |player| is in kPlayerStatePrerolling,
-// this will set the initial pause state for the current seek target.
+// Pauses or unpauses the |player|. If the |player|'s state is
+// |kPlayerStatePrerolling|, this function sets the initial pause state for
+// the current seek target.
 SB_EXPORT void SbPlayerSetPause(SbPlayer player, bool pause);
 
-// Sets the volume for |player|, in [0.0, 1.0]. 0.0 means the audio should be
-// muted, and 1.0 means it should be played at full volume.
+// Sets the player's volume.
+//
+// |player|: The player in which the volume is being adjusted.
+// |volume|: The new player volume. The value must be between |0.0| and |1.0|,
+//   inclusive. A value of |0.0| means that the audio should be muted, and a
+//   value of |1.0| means that it should be played at full volume.
 SB_EXPORT void SbPlayerSetVolume(SbPlayer player, double volume);
 
-// Gets a snapshot of the current player state and writes it into
-// |out_player_info|. This function is expected to be inexpensive, and may be
-// called very frequently.
+// Gets a snapshot of the current player state and writes it to
+// |out_player_info|. This function may be called very frequently and is
+// expected to be inexpensive.
+//
+// |player|: The player about which information is being retrieved.
+// |out_player_info|: The information retrieved for the player.
 SB_EXPORT void SbPlayerGetInfo(SbPlayer player, SbPlayerInfo* out_player_info);
 
 #if SB_IS(PLAYER_COMPOSITED)
 // Gets a handle that represents the player's video output, for the purpose of
-// composing with SbCompositor (currently undefined).
+// composing with |SbCompositor|, which is currently undefined.
+//
+// |player|: The player for which the video output handle is retrieved.
 SB_EXPORT SbPlayerCompositionHandle
 SbPlayerGetCompositionHandle(SbPlayer player);
 #endif
 
 #if SB_IS(PLAYER_PRODUCING_TEXTURE)
 // Gets an OpenGL texture ID that points to the player's video output frame at
-// the time it was called. This can be called once, and the same texture ID will
-// be appropriately mapped to the current video frame when drawn.
+// the time it was called. This function can be called once, and the texture ID
+// will be appropriately remapped to the current video frame when it is drawn.
+//
+// |player|: The player for which the texture ID is retrieved.
 SB_EXPORT uint32_t SbPlayerGetTextureId(SbPlayer player);
 #endif
 
diff --git a/src/starboard/queue.h b/src/starboard/queue.h
index 65127f0..53f7633 100644
--- a/src/starboard/queue.h
+++ b/src/starboard/queue.h
@@ -12,9 +12,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// A C++-only synchronized queue implementation, built entirely on top of
-// Starboard synchronization primitives. Can be safely used by both clients and
-// implementations.
+// Module Overview: Starboard Queue module
+//
+// Defines a C++-only synchronized queue implementation, built entirely on top
+// of Starboard synchronization primitives. It can be safely used by both
+// clients and implementations.
 
 #ifndef STARBOARD_QUEUE_H_
 #define STARBOARD_QUEUE_H_
diff --git a/src/starboard/raspi/1/starboard_platform.gyp b/src/starboard/raspi/1/starboard_platform.gyp
index c33f33d..4f3603f 100644
--- a/src/starboard/raspi/1/starboard_platform.gyp
+++ b/src/starboard/raspi/1/starboard_platform.gyp
@@ -34,7 +34,13 @@
         '<(DEPTH)/starboard/raspi/1/system_get_property.cc',
         '<(DEPTH)/starboard/raspi/shared/application_dispmanx.cc',
         '<(DEPTH)/starboard/raspi/shared/audio_sink_is_audio_sample_type_supported.cc',
+        '<(DEPTH)/starboard/raspi/shared/dispmanx_util.cc',
+        '<(DEPTH)/starboard/raspi/shared/dispmanx_util.h',
         '<(DEPTH)/starboard/raspi/shared/main.cc',
+        '<(DEPTH)/starboard/raspi/shared/open_max/open_max_component.cc',
+        '<(DEPTH)/starboard/raspi/shared/open_max/open_max_component.h',
+        '<(DEPTH)/starboard/raspi/shared/open_max/video_decoder.cc',
+        '<(DEPTH)/starboard/raspi/shared/open_max/video_decoder.h',
         '<(DEPTH)/starboard/raspi/shared/window_create.cc',
         '<(DEPTH)/starboard/raspi/shared/window_destroy.cc',
         '<(DEPTH)/starboard/raspi/shared/window_get_platform_handle.cc',
@@ -58,8 +64,6 @@
         '<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_audio_decoder.h',
         '<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_common.cc',
         '<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_common.h',
-        '<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc',
-        '<(DEPTH)/starboard/shared/ffmpeg/ffmpeg_video_decoder.h',
         '<(DEPTH)/starboard/shared/gcc/atomic_gcc.h',
         '<(DEPTH)/starboard/shared/iso/character_is_alphanumeric.cc',
         '<(DEPTH)/starboard/shared/iso/character_is_digit.cc',
@@ -179,6 +183,7 @@
         '<(DEPTH)/starboard/shared/posix/system_get_number_of_processors.cc',
         '<(DEPTH)/starboard/shared/posix/thread_sleep.cc',
         '<(DEPTH)/starboard/shared/posix/time_get_monotonic_now.cc',
+        '<(DEPTH)/starboard/shared/posix/time_get_monotonic_thread_now.cc',
         '<(DEPTH)/starboard/shared/posix/time_get_now.cc',
         '<(DEPTH)/starboard/shared/posix/time_zone_get_current.cc',
         '<(DEPTH)/starboard/shared/posix/time_zone_get_dst_name.cc',
@@ -270,12 +275,19 @@
         '<(DEPTH)/starboard/shared/starboard/system_get_random_uint64.cc',
         '<(DEPTH)/starboard/shared/starboard/system_request_stop.cc',
         '<(DEPTH)/starboard/shared/starboard/window_set_default_options.cc',
+        '<(DEPTH)/starboard/shared/stub/decode_target_create_egl.cc',
+        '<(DEPTH)/starboard/shared/stub/decode_target_destroy.cc',
+        '<(DEPTH)/starboard/shared/stub/decode_target_get_format.cc',
+        '<(DEPTH)/starboard/shared/stub/decode_target_get_plane_egl.cc',
+        '<(DEPTH)/starboard/shared/stub/decode_target_is_opaque.cc',
         '<(DEPTH)/starboard/shared/stub/drm_close_session.cc',
         '<(DEPTH)/starboard/shared/stub/drm_create_system.cc',
         '<(DEPTH)/starboard/shared/stub/drm_destroy_system.cc',
         '<(DEPTH)/starboard/shared/stub/drm_generate_session_update_request.cc',
         '<(DEPTH)/starboard/shared/stub/drm_system_internal.h',
         '<(DEPTH)/starboard/shared/stub/drm_update_session.cc',
+        '<(DEPTH)/starboard/shared/stub/image_decode.cc',
+        '<(DEPTH)/starboard/shared/stub/image_is_decode_supported.cc',
         '<(DEPTH)/starboard/shared/stub/media_is_supported.cc',
         '<(DEPTH)/starboard/shared/stub/system_clear_platform_error.cc',
         '<(DEPTH)/starboard/shared/stub/system_get_total_gpu_memory.cc',
diff --git a/src/starboard/raspi/1/system_get_property.cc b/src/starboard/raspi/1/system_get_property.cc
index 6b5cee9..50f9d92 100644
--- a/src/starboard/raspi/1/system_get_property.cc
+++ b/src/starboard/raspi/1/system_get_property.cc
@@ -47,6 +47,7 @@
     case kSbSystemPropertyModelName:
     case kSbSystemPropertyModelYear:
     case kSbSystemPropertyNetworkOperatorName:
+    case kSbSystemPropertySpeechApiKey:
       return false;
 
     case kSbSystemPropertyFriendlyName:
diff --git a/src/starboard/raspi/shared/application_dispmanx.cc b/src/starboard/raspi/shared/application_dispmanx.cc
index ae3fb8e..fcaf43f 100644
--- a/src/starboard/raspi/shared/application_dispmanx.cc
+++ b/src/starboard/raspi/shared/application_dispmanx.cc
@@ -36,6 +36,10 @@
 
 using ::starboard::shared::dev_input::DevInput;
 
+namespace {
+const int kVideoLayer = -1;
+}  // namespace
+
 SbWindow ApplicationDispmanx::CreateWindow(const SbWindowOptions* options) {
   if (SbWindowIsValid(window_)) {
     return kSbWindowInvalid;
@@ -44,8 +48,13 @@
   InitializeDispmanx();
 
   SB_DCHECK(IsDispmanxInitialized());
-  window_ = new SbWindowPrivate(display_, options);
+  window_ = new SbWindowPrivate(*display_, options);
   input_ = DevInput::Create(window_);
+
+  // Create the dispmanx element to display video frames.
+  int result = 0;
+  uint32_t vc_image_ptr;
+
   return window_;
 }
 
@@ -76,6 +85,18 @@
   SbAudioSinkPrivate::TearDown();
 }
 
+void ApplicationDispmanx::AcceptFrame(SbPlayer player,
+                                      const VideoFrame& frame,
+                                      int x,
+                                      int y,
+                                      int width,
+                                      int height) {
+  if (!video_renderer_) {
+    video_renderer_.reset(new DispmanxVideoRenderer(*display_, kVideoLayer));
+  }
+  video_renderer_->Update(frame);
+}
+
 bool ApplicationDispmanx::MayHaveSystemEvents() {
   return input_ != NULL;
 }
@@ -102,8 +123,7 @@
     return;
   }
 
-  bcm_host_init();
-  display_ = vc_dispmanx_display_open(0);
+  display_.reset(new DispmanxDisplay);
   SB_DCHECK(IsDispmanxInitialized());
 }
 
@@ -113,10 +133,8 @@
   }
 
   SB_DCHECK(!SbWindowIsValid(window_));
-  int result = vc_dispmanx_display_close(display_);
-  SB_DCHECK(result == 0);
-  display_ = DISPMANX_NO_HANDLE;
-  bcm_host_deinit();
+
+  display_.reset();
 }
 
 }  // namespace shared
diff --git a/src/starboard/raspi/shared/application_dispmanx.h b/src/starboard/raspi/shared/application_dispmanx.h
index 6f6a938..ba49ff5 100644
--- a/src/starboard/raspi/shared/application_dispmanx.h
+++ b/src/starboard/raspi/shared/application_dispmanx.h
@@ -15,11 +15,9 @@
 #ifndef STARBOARD_RASPI_SHARED_APPLICATION_DISPMANX_H_
 #define STARBOARD_RASPI_SHARED_APPLICATION_DISPMANX_H_
 
-#include <bcm_host.h>
-
-#include <vector>
-
+#include "starboard/common/scoped_ptr.h"
 #include "starboard/configuration.h"
+#include "starboard/raspi/shared/dispmanx_util.h"
 #include "starboard/shared/internal_only.h"
 #include "starboard/shared/linux/dev_input/dev_input.h"
 #include "starboard/shared/starboard/application.h"
@@ -35,8 +33,7 @@
 class ApplicationDispmanx
     : public ::starboard::shared::starboard::QueueApplication {
  public:
-  ApplicationDispmanx()
-      : display_(DISPMANX_NO_HANDLE), window_(kSbWindowInvalid), input_(NULL) {}
+  ApplicationDispmanx() : window_(kSbWindowInvalid), input_(NULL) {}
   ~ApplicationDispmanx() SB_OVERRIDE {}
 
   static ApplicationDispmanx* Get() {
@@ -51,6 +48,12 @@
   // --- Application overrides ---
   void Initialize() SB_OVERRIDE;
   void Teardown() SB_OVERRIDE;
+  void AcceptFrame(SbPlayer player,
+                   const VideoFrame& frame,
+                   int x,
+                   int y,
+                   int width,
+                   int height) SB_OVERRIDE;
 
   // --- QueueApplication overrides ---
   bool MayHaveSystemEvents() SB_OVERRIDE;
@@ -60,7 +63,7 @@
 
  private:
   // Returns whether DISPMANX has been initialized.
-  bool IsDispmanxInitialized() { return display_ != DISPMANX_NO_HANDLE; }
+  bool IsDispmanxInitialized() { return display_ != NULL; }
 
   // Ensures that X is up, display is populated and connected.
   void InitializeDispmanx();
@@ -69,7 +72,10 @@
   void ShutdownDispmanx();
 
   // The DISPMANX display.
-  DISPMANX_DISPLAY_HANDLE_T display_;
+  scoped_ptr<DispmanxDisplay> display_;
+
+  // DISPMANX helper to render video frames.
+  scoped_ptr<DispmanxVideoRenderer> video_renderer_;
 
   // The single open window, if any.
   SbWindow window_;
diff --git a/src/starboard/raspi/shared/configuration_public.h b/src/starboard/raspi/shared/configuration_public.h
index 15c18ca..0d4b088 100644
--- a/src/starboard/raspi/shared/configuration_public.h
+++ b/src/starboard/raspi/shared/configuration_public.h
@@ -18,7 +18,7 @@
 #define STARBOARD_RASPI_SHARED_CONFIGURATION_PUBLIC_H_
 
 // The API version implemented by this platform.
-#define SB_API_VERSION 1
+#define SB_API_VERSION 3
 
 // --- System Header Configuration -------------------------------------------
 
@@ -49,6 +49,12 @@
 // Whether the current platform provides the standard header float.h.
 #define SB_HAS_FLOAT_H 1
 
+// Whether the current platform has microphone supported.
+#define SB_HAS_MICROPHONE 0
+
+// Whether the current platform has speech synthesis.
+#define SB_HAS_SPEECH_SYNTHESIS 0
+
 // Type detection for wchar_t.
 #if defined(__WCHAR_MAX__) && \
     (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff)
@@ -371,6 +377,12 @@
 // The maximum number of users that can be signed in at the same time.
 #define SB_USER_MAX_SIGNED_IN 1
 
+// --- Timing API ------------------------------------------------------------
+
+// Whether this platform has an API to retrieve how long the current thread
+// has spent in the executing state.
+#define SB_HAS_TIME_THREAD_NOW 1
+
 // --- Platform Specific Audits ----------------------------------------------
 
 #if !defined(__GNUC__)
diff --git a/src/starboard/raspi/shared/dispmanx_util.cc b/src/starboard/raspi/shared/dispmanx_util.cc
new file mode 100644
index 0000000..88c7f52
--- /dev/null
+++ b/src/starboard/raspi/shared/dispmanx_util.cc
@@ -0,0 +1,105 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/raspi/shared/dispmanx_util.h"
+
+#include "starboard/common/scoped_ptr.h"
+#include "starboard/memory.h"
+
+namespace starboard {
+namespace raspi {
+namespace shared {
+
+namespace {
+
+class DispmanxAutoUpdate {
+ public:
+  DispmanxAutoUpdate() {
+    handle_ = vc_dispmanx_update_start(0 /*screen*/);
+    SB_DCHECK(handle_ != DISPMANX_NO_HANDLE);
+  }
+  ~DispmanxAutoUpdate() {
+    if (handle_ != DISPMANX_NO_HANDLE) {
+      Update();
+    }
+  }
+
+  DISPMANX_UPDATE_HANDLE_T handle() const { return handle_; }
+
+  void Update() {
+    SB_DCHECK(handle_ != DISPMANX_NO_HANDLE);
+    int32_t result = vc_dispmanx_update_submit_sync(handle_);
+    SB_DCHECK(result == 0) << " result=" << result;
+    handle_ = DISPMANX_NO_HANDLE;
+  }
+
+ private:
+  DISPMANX_UPDATE_HANDLE_T handle_;
+
+  SB_DISALLOW_COPY_AND_ASSIGN(DispmanxAutoUpdate);
+};
+
+}  // namespace
+
+void DispmanxYUV420Resource::ClearWithBlack() {
+  scoped_array<uint8_t> data(new uint8_t[width_ * height_ * 3 / 2]);
+  SbMemorySet(data.get(), width_ * height_, 0);
+  SbMemorySet(data.get() + width_ * height_, width_ * height_ / 2, 0x80);
+  WriteData(data.get());
+}
+
+DispmanxElement::DispmanxElement(const DispmanxDisplay& display,
+                                 int32_t layer,
+                                 const DispmanxRect& dest_rect,
+                                 const DispmanxResource& src,
+                                 const DispmanxRect& src_rect) {
+  DispmanxAutoUpdate update;
+  handle_ = vc_dispmanx_element_add(update.handle(), display.handle(), layer,
+                                    &dest_rect, src.handle(), &src_rect,
+                                    DISPMANX_PROTECTION_NONE, NULL /*alpha*/,
+                                    NULL /*clamp*/, DISPMANX_NO_ROTATE);
+  SB_DCHECK(handle_ != DISPMANX_NO_HANDLE);
+}
+
+DispmanxElement::~DispmanxElement() {
+  DispmanxAutoUpdate update;
+  int32_t result = vc_dispmanx_element_remove(update.handle(), handle_);
+  SB_DCHECK(result == 0) << " result=" << result;
+}
+
+void DispmanxVideoRenderer::Update(const VideoFrame& video_frame) {
+  if (video_frame.IsEndOfStream()) {
+    element_.reset();
+    resource_.reset();
+    return;
+  }
+  if (!resource_ || resource_->width() != video_frame.width() ||
+      resource_->height() != video_frame.height()) {
+    element_.reset();
+    resource_.reset();
+
+    DispmanxRect src_rect(0, 0, video_frame.width() << 16,
+                          video_frame.height() << 16);
+    resource_.reset(
+        new DispmanxYUV420Resource(video_frame.width(), video_frame.height()));
+    element_.reset(new DispmanxElement(display_, layer_, DispmanxRect(),
+                                       *resource_, src_rect));
+  }
+
+  resource_->WriteData(video_frame.GetPlane(0).data);
+}
+
+}  // namespace shared
+}  // namespace raspi
+}  // namespace starboard
diff --git a/src/starboard/raspi/shared/dispmanx_util.h b/src/starboard/raspi/shared/dispmanx_util.h
new file mode 100644
index 0000000..c4b65f6
--- /dev/null
+++ b/src/starboard/raspi/shared/dispmanx_util.h
@@ -0,0 +1,145 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_RASPI_SHARED_DISPMANX_UTIL_H_
+#define STARBOARD_RASPI_SHARED_DISPMANX_UTIL_H_
+
+#include <bcm_host.h>
+
+#include "starboard/common/scoped_ptr.h"
+#include "starboard/configuration.h"
+#include "starboard/log.h"
+#include "starboard/shared/internal_only.h"
+#include "starboard/shared/starboard/player/video_frame_internal.h"
+#include "starboard/types.h"
+
+namespace starboard {
+namespace raspi {
+namespace shared {
+
+class DispmanxRect : public VC_RECT_T {
+ public:
+  DispmanxRect() { vc_dispmanx_rect_set(this, 0, 0, 0, 0); }
+  DispmanxRect(uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
+    vc_dispmanx_rect_set(this, x, y, width, height);
+  }
+};
+
+class DispmanxDisplay {
+ public:
+  DispmanxDisplay() {
+    bcm_host_init();
+    handle_ = vc_dispmanx_display_open(0);
+    SB_DCHECK(handle_ != DISPMANX_NO_HANDLE);
+  }
+  ~DispmanxDisplay() {
+    int result = vc_dispmanx_display_close(handle_);
+    SB_DCHECK(result == 0);
+    bcm_host_deinit();
+  }
+
+  DISPMANX_DISPLAY_HANDLE_T handle() const { return handle_; }
+
+ private:
+  DISPMANX_DISPLAY_HANDLE_T handle_;
+
+  SB_DISALLOW_COPY_AND_ASSIGN(DispmanxDisplay);
+};
+
+class DispmanxResource {
+ public:
+  DispmanxResource() : handle_(DISPMANX_NO_HANDLE) {}
+
+  virtual ~DispmanxResource() {
+    if (handle_ != DISPMANX_NO_HANDLE) {
+      int32_t result = vc_dispmanx_resource_delete(handle_);
+      SB_DCHECK(result == 0) << " result=" << result;
+    }
+  }
+
+  DISPMANX_RESOURCE_HANDLE_T handle() const { return handle_; }
+  uint32_t width() const { return width_; }
+  uint32_t height() const { return height_; }
+
+ protected:
+  DispmanxResource(VC_IMAGE_TYPE_T image_type, uint32_t width, uint32_t height)
+      : width_(width), height_(height) {
+    uint32_t vc_image_ptr;
+
+    handle_ =
+        vc_dispmanx_resource_create(image_type, width, height, &vc_image_ptr);
+    SB_DCHECK(handle_ != DISPMANX_NO_HANDLE);
+  }
+
+  DISPMANX_RESOURCE_HANDLE_T handle_;
+  uint32_t width_;
+  uint32_t height_;
+
+  SB_DISALLOW_COPY_AND_ASSIGN(DispmanxResource);
+};
+
+class DispmanxYUV420Resource : public DispmanxResource {
+ public:
+  DispmanxYUV420Resource(uint32_t width, uint32_t height)
+      : DispmanxResource(VC_IMAGE_YUV420, width, height) {}
+
+  void WriteData(const void* data) {
+    SB_DCHECK(handle_ != DISPMANX_NO_HANDLE);
+    DispmanxRect dst_rect(0, 0, width(), height() * 3 / 2);
+    int32_t result = vc_dispmanx_resource_write_data(
+        handle_, VC_IMAGE_YUV420, width(), const_cast<void*>(data), &dst_rect);
+    SB_DCHECK(result == 0);
+  }
+  void ClearWithBlack();
+};
+
+class DispmanxElement {
+ public:
+  DispmanxElement(const DispmanxDisplay& display,
+                  int32_t layer,
+                  const DispmanxRect& dest_rect,
+                  const DispmanxResource& src,
+                  const DispmanxRect& src_rect);
+  ~DispmanxElement();
+
+  DISPMANX_ELEMENT_HANDLE_T handle() const { return handle_; }
+
+ private:
+  DISPMANX_ELEMENT_HANDLE_T handle_;
+
+  SB_DISALLOW_COPY_AND_ASSIGN(DispmanxElement);
+};
+
+class DispmanxVideoRenderer {
+ public:
+  typedef starboard::shared::starboard::player::VideoFrame VideoFrame;
+  DispmanxVideoRenderer(const DispmanxDisplay& display, int32_t layer)
+      : display_(display), layer_(layer) {}
+
+  void Update(const VideoFrame& video_frame);
+
+ private:
+  const DispmanxDisplay& display_;
+  int32_t layer_;
+  scoped_ptr<DispmanxYUV420Resource> resource_;
+  scoped_ptr<DispmanxElement> element_;
+
+  SB_DISALLOW_COPY_AND_ASSIGN(DispmanxVideoRenderer);
+};
+
+}  // namespace shared
+}  // namespace raspi
+}  // namespace starboard
+
+#endif  // STARBOARD_RASPI_SHARED_DISPMANX_UTIL_H_
diff --git a/src/starboard/raspi/shared/open_max/open_max_component.cc b/src/starboard/raspi/shared/open_max/open_max_component.cc
new file mode 100644
index 0000000..eb05825
--- /dev/null
+++ b/src/starboard/raspi/shared/open_max/open_max_component.cc
@@ -0,0 +1,365 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/raspi/shared/open_max/open_max_component.h"
+
+#include <algorithm>
+
+#include "starboard/configuration.h"
+#include "starboard/once.h"
+#include "starboard/thread.h"
+
+namespace starboard {
+namespace raspi {
+namespace shared {
+namespace open_max {
+
+namespace {
+
+const int kInvalidPort = -1;
+
+OMX_INDEXTYPE kPortTypes[] = {OMX_IndexParamAudioInit, OMX_IndexParamVideoInit,
+                              OMX_IndexParamImageInit, OMX_IndexParamOtherInit};
+
+SbOnceControl s_open_max_initialization_once = SB_ONCE_INITIALIZER;
+
+void DoInitializeOpenMax() {
+  OMX_ERRORTYPE error = OMX_Init();
+  SB_DCHECK(error == OMX_ErrorNone);
+}
+
+void InitializeOpenMax() {
+  bool initialized =
+      SbOnce(&s_open_max_initialization_once, DoInitializeOpenMax);
+  SB_DCHECK(initialized);
+}
+
+}  // namespace
+
+OpenMaxComponent::OpenMaxComponent(const char* name, size_t minimum_output_size)
+    : condition_variable_(mutex_),
+      minimum_output_size_(minimum_output_size),
+      handle_(NULL),
+      input_port_(kInvalidPort),
+      output_port_(kInvalidPort),
+      output_setting_changed_(false),
+      output_buffer_(NULL),
+      output_buffer_filled_(false) {
+  InitializeOpenMax();
+
+  OMX_CALLBACKTYPE callbacks;
+  callbacks.EventHandler = OpenMaxComponent::EventHandler;
+  callbacks.EmptyBufferDone = OpenMaxComponent::EmptyBufferDone;
+  callbacks.FillBufferDone = OpenMaxComponent::FillBufferDone;
+
+  OMX_ERRORTYPE error =
+      OMX_GetHandle(&handle_, const_cast<char*>(name), this, &callbacks);
+  SB_DCHECK(error == OMX_ErrorNone);
+
+  for (size_t i = 0; i < SB_ARRAY_SIZE(kPortTypes); ++i) {
+    OMX_PORT_PARAM_TYPE port;
+    port.nSize = sizeof(OMX_PORT_PARAM_TYPE);
+    port.nVersion.nVersion = OMX_VERSION;
+
+    error = OMX_GetParameter(handle_, kPortTypes[i], &port);
+    if (error == OMX_ErrorNone && port.nPorts == 2) {
+      input_port_ = port.nStartPortNumber;
+      output_port_ = input_port_ + 1;
+      SendCommandAndWaitForCompletion(OMX_CommandPortDisable, input_port_);
+      SendCommandAndWaitForCompletion(OMX_CommandPortDisable, output_port_);
+      break;
+    }
+  }
+  SB_CHECK(input_port_ != kInvalidPort);
+  SB_CHECK(output_port_ != kInvalidPort);
+  SB_DLOG(INFO) << "Opened \"" << name << "\" with port " << input_port_
+                << " and " << output_port_;
+
+  SendCommandAndWaitForCompletion(OMX_CommandStateSet, OMX_StateIdle);
+}
+
+OpenMaxComponent::~OpenMaxComponent() {
+  if (!handle_) {
+    return;
+  }
+  SendCommandAndWaitForCompletion(OMX_CommandStateSet, OMX_StateIdle);
+
+  SendCommandAndWaitForCompletion(OMX_CommandFlush, input_port_);
+  SendCommandAndWaitForCompletion(OMX_CommandFlush, output_port_);
+
+  SendCommand(OMX_CommandPortDisable, input_port_);
+  for (BufferHeaders::iterator iter = unused_buffers_.begin();
+       iter != unused_buffers_.end(); ++iter) {
+    OMX_ERRORTYPE error = OMX_FreeBuffer(handle_, input_port_, *iter);
+    SB_DCHECK(error == OMX_ErrorNone);
+  }
+  WaitForCommandCompletion();
+
+  SendCommand(OMX_CommandPortDisable, output_port_);
+  if (output_buffer_) {
+    OMX_ERRORTYPE error = OMX_FreeBuffer(handle_, output_port_, output_buffer_);
+    SB_DCHECK(error == OMX_ErrorNone);
+  }
+  WaitForCommandCompletion();
+
+  SendCommandAndWaitForCompletion(OMX_CommandStateSet, OMX_StateLoaded);
+  OMX_FreeHandle(handle_);
+}
+
+void OpenMaxComponent::Start() {
+  EnableInputPortAndAllocateBuffers();
+  SendCommandAndWaitForCompletion(OMX_CommandStateSet, OMX_StateExecuting);
+}
+
+void OpenMaxComponent::Flush() {
+  SendCommandAndWaitForCompletion(OMX_CommandFlush, input_port_);
+  SendCommandAndWaitForCompletion(OMX_CommandFlush, output_port_);
+}
+
+void OpenMaxComponent::WriteData(const void* data,
+                                 size_t size,
+                                 SbTime timestamp) {
+  size_t offset = 0;
+
+  while (offset != size) {
+    OMX_BUFFERHEADERTYPE* buffer_header = GetUnusedInputBuffer();
+
+    int size_to_append = std::min(size - offset, buffer_header->nAllocLen);
+    buffer_header->nOffset = 0;
+    buffer_header->nFilledLen = size_to_append;
+    buffer_header->nFlags = 0;
+
+    buffer_header->nTimeStamp.nLowPart = timestamp;
+    buffer_header->nTimeStamp.nHighPart = timestamp >> 32;
+
+    memcpy(buffer_header->pBuffer, (const char*)data + offset, size_to_append);
+    offset += size_to_append;
+
+    OMX_ERRORTYPE error = OMX_EmptyThisBuffer(handle_, buffer_header);
+    SB_DCHECK(error == OMX_ErrorNone);
+  }
+}
+
+void OpenMaxComponent::WriteEOS() {
+  OMX_BUFFERHEADERTYPE* buffer_header = GetUnusedInputBuffer();
+
+  buffer_header->nOffset = 0;
+  buffer_header->nFilledLen = 0;
+  buffer_header->nFlags = OMX_BUFFERFLAG_EOS;
+
+  OMX_ERRORTYPE error = OMX_EmptyThisBuffer(handle_, buffer_header);
+  SB_DCHECK(error == OMX_ErrorNone);
+}
+
+bool OpenMaxComponent::ReadVideoFrame(VideoFrame* frame) {
+  {
+    ScopedLock scoped_lock(mutex_);
+    if (output_buffer_ && !output_buffer_filled_) {
+      return false;
+    }
+    if (!output_setting_changed_) {
+      return false;
+    }
+  }
+  SB_DCHECK(output_setting_changed_);
+  if (!output_buffer_) {
+    GetOutputPortParam(&output_port_definition_);
+    SB_DCHECK(output_port_definition_.format.video.eColorFormat ==
+              OMX_COLOR_FormatYUV420PackedPlanar);
+    EnableOutputPortAndAllocateBuffer();
+    return false;
+  }
+
+  if (output_buffer_->nFlags & OMX_BUFFERFLAG_EOS) {
+    *frame = VideoFrame();
+    return true;
+  }
+  SbMediaTime timestamp =
+      ((output_buffer_->nTimeStamp.nHighPart * 0x100000000ull) +
+       output_buffer_->nTimeStamp.nLowPart) *
+      kSbMediaTimeSecond / kSbTimeSecond;
+  int width = output_port_definition_.format.video.nFrameWidth;
+  int height = output_port_definition_.format.video.nSliceHeight;
+  int pitch = output_port_definition_.format.video.nStride;
+  *frame = VideoFrame::CreateYV12Frame(
+      width, height, pitch, timestamp, output_buffer_->pBuffer,
+      output_buffer_->pBuffer + pitch * height,
+      output_buffer_->pBuffer + pitch * height * 5 / 4);
+  output_buffer_filled_ = false;
+  output_buffer_->nFilledLen = 0;
+  OMX_ERRORTYPE error = OMX_FillThisBuffer(handle_, output_buffer_);
+  SB_DCHECK(error == OMX_ErrorNone);
+  return true;
+}
+
+void OpenMaxComponent::SendCommand(OMX_COMMANDTYPE command, int param) {
+  OMX_ERRORTYPE error = OMX_SendCommand(handle_, command, param, NULL);
+  SB_DCHECK(error == OMX_ErrorNone);
+}
+
+void OpenMaxComponent::WaitForCommandCompletion() {
+  for (;;) {
+    ScopedLock scoped_lock(mutex_);
+    for (EventDescriptions::iterator iter = event_descriptions_.begin();
+         iter != event_descriptions_.end(); ++iter) {
+      if (iter->event == OMX_EventCmdComplete) {
+        event_descriptions_.erase(iter);
+        return;
+      }
+      // Special case for OMX_CommandStateSet.
+      if (iter->event == OMX_EventError && iter->data1 == OMX_ErrorSameState) {
+        event_descriptions_.erase(iter);
+        return;
+      }
+    }
+    condition_variable_.Wait();
+  }
+}
+
+void OpenMaxComponent::SendCommandAndWaitForCompletion(OMX_COMMANDTYPE command,
+                                                       int param) {
+  SendCommand(command, param);
+  WaitForCommandCompletion();
+}
+
+void OpenMaxComponent::EnableInputPortAndAllocateBuffers() {
+  SB_DCHECK(unused_buffers_.empty());
+
+  OMXParamPortDefinition port_definition;
+  GetInputPortParam(&port_definition);
+
+  SendCommand(OMX_CommandPortEnable, input_port_);
+
+  unused_buffers_.resize(port_definition.nBufferCountActual);
+  for (int i = 0; i != port_definition.nBufferCountActual; ++i) {
+    OMX_ERRORTYPE error =
+        OMX_AllocateBuffer(handle_, &unused_buffers_[i], input_port_, NULL,
+                           port_definition.nBufferSize);
+    SB_DCHECK(error == OMX_ErrorNone);
+  }
+
+  WaitForCommandCompletion();
+}
+
+void OpenMaxComponent::EnableOutputPortAndAllocateBuffer() {
+  if (output_buffer_ != NULL) {
+    return;
+  }
+
+  SendCommand(OMX_CommandPortEnable, output_port_);
+
+  OMX_ERRORTYPE error = OMX_AllocateBuffer(
+      handle_, &output_buffer_, output_port_, NULL,
+      std::max(output_port_definition_.nBufferSize, minimum_output_size_));
+  SB_DCHECK(error == OMX_ErrorNone);
+  WaitForCommandCompletion();
+
+  error = OMX_FillThisBuffer(handle_, output_buffer_);
+  SB_DCHECK(error == OMX_ErrorNone);
+}
+
+OMX_BUFFERHEADERTYPE* OpenMaxComponent::GetUnusedInputBuffer() {
+  for (;;) {
+    ScopedLock scoped_lock(mutex_);
+    if (!unused_buffers_.empty()) {
+      OMX_BUFFERHEADERTYPE* buffer_header = unused_buffers_.back();
+      unused_buffers_.pop_back();
+      return buffer_header;
+    }
+    SbThreadSleep(kSbTimeMillisecond);
+  }
+  SB_NOTREACHED();
+  return NULL;
+}
+
+OMX_ERRORTYPE OpenMaxComponent::OnEvent(OMX_EVENTTYPE event,
+                                        OMX_U32 data1,
+                                        OMX_U32 data2,
+                                        OMX_PTR event_data) {
+  if (event == OMX_EventError && data1 != OMX_ErrorSameState) {
+    SB_NOTREACHED() << "OMX_EventError received with " << std::hex << data1
+                    << " " << data2;
+    return OMX_ErrorNone;
+  }
+
+  ScopedLock scoped_lock(mutex_);
+  if (event == OMX_EventPortSettingsChanged && data1 == output_port_) {
+    output_setting_changed_ = true;
+    return OMX_ErrorNone;
+  }
+  EventDescription event_desc;
+  event_desc.event = event;
+  event_desc.data1 = data1;
+  event_desc.data2 = data2;
+  event_desc.event_data = event_data;
+  event_descriptions_.push_back(event_desc);
+  condition_variable_.Signal();
+
+  return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE OpenMaxComponent::OnEmptyBufferDone(
+    OMX_BUFFERHEADERTYPE* buffer) {
+  ScopedLock scoped_lock(mutex_);
+  unused_buffers_.push_back(buffer);
+}
+
+void OpenMaxComponent::OnFillBufferDone(OMX_BUFFERHEADERTYPE* buffer) {
+  ScopedLock scoped_lock(mutex_);
+  SB_DCHECK(!output_buffer_filled_);
+  output_buffer_filled_ = true;
+}
+
+// static
+OMX_ERRORTYPE OpenMaxComponent::EventHandler(OMX_HANDLETYPE handle,
+                                             OMX_PTR app_data,
+                                             OMX_EVENTTYPE event,
+                                             OMX_U32 data1,
+                                             OMX_U32 data2,
+                                             OMX_PTR event_data) {
+  SB_DCHECK(app_data != NULL);
+  OpenMaxComponent* component = reinterpret_cast<OpenMaxComponent*>(app_data);
+  SB_DCHECK(handle == component->handle_);
+
+  return component->OnEvent(event, data1, data2, event_data);
+}
+
+// static
+OMX_ERRORTYPE OpenMaxComponent::EmptyBufferDone(OMX_HANDLETYPE handle,
+                                                OMX_PTR app_data,
+                                                OMX_BUFFERHEADERTYPE* buffer) {
+  SB_DCHECK(app_data != NULL);
+  OpenMaxComponent* component = reinterpret_cast<OpenMaxComponent*>(app_data);
+  SB_DCHECK(handle == component->handle_);
+
+  return component->OnEmptyBufferDone(buffer);
+}
+
+// static
+OMX_ERRORTYPE OpenMaxComponent::FillBufferDone(OMX_HANDLETYPE handle,
+                                               OMX_PTR app_data,
+                                               OMX_BUFFERHEADERTYPE* buffer) {
+  SB_DCHECK(app_data != NULL);
+  OpenMaxComponent* component = reinterpret_cast<OpenMaxComponent*>(app_data);
+  SB_DCHECK(handle == component->handle_);
+
+  component->OnFillBufferDone(buffer);
+
+  return OMX_ErrorNone;
+}
+
+}  // namespace open_max
+}  // namespace shared
+}  // namespace raspi
+}  // namespace starboard
diff --git a/src/starboard/raspi/shared/open_max/open_max_component.h b/src/starboard/raspi/shared/open_max/open_max_component.h
new file mode 100644
index 0000000..9085c1b
--- /dev/null
+++ b/src/starboard/raspi/shared/open_max/open_max_component.h
@@ -0,0 +1,154 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_RASPI_SHARED_OPEN_MAX_OPEN_MAX_COMPONENT_H_
+#define STARBOARD_RASPI_SHARED_OPEN_MAX_OPEN_MAX_COMPONENT_H_
+
+// OMX_SKIP64BIT is required for using VC GPU code.
+#define OMX_SKIP64BIT 1
+
+#include <IL/OMX_Broadcom.h>
+#include <interface/vcos/vcos.h>
+#include <interface/vcos/vcos_logging.h>
+#include <interface/vmcs_host/vchost.h>
+#include <vector>
+
+#include "starboard/condition_variable.h"
+#include "starboard/log.h"
+#include "starboard/mutex.h"
+#include "starboard/shared/internal_only.h"
+#include "starboard/shared/starboard/player/video_frame_internal.h"
+#include "starboard/time.h"
+
+namespace starboard {
+namespace raspi {
+namespace shared {
+namespace open_max {
+
+template <typename ParamType, OMX_INDEXTYPE index>
+struct OMXParam : public ParamType {
+  static const OMX_INDEXTYPE Index = index;
+
+  OMXParam() : ParamType() {
+    ParamType::nSize = sizeof(ParamType);
+    ParamType::nVersion.nVersion = OMX_VERSION;
+  }
+};
+
+typedef OMXParam<OMX_PARAM_PORTDEFINITIONTYPE, OMX_IndexParamPortDefinition>
+    OMXParamPortDefinition;
+typedef OMXParam<OMX_VIDEO_PARAM_PORTFORMATTYPE, OMX_IndexParamVideoPortFormat>
+    OMXVideoParamPortFormat;
+
+class OpenMaxComponent {
+ public:
+  typedef starboard::shared::starboard::player::VideoFrame VideoFrame;
+
+  explicit OpenMaxComponent(const char* name, size_t minimum_output_size = 0);
+  ~OpenMaxComponent();
+
+  void Start();
+  void Flush();
+
+  void WriteData(const void* data, size_t size, SbTime timestamp);
+  void WriteEOS();
+
+  bool ReadVideoFrame(VideoFrame* frame);
+
+  template <typename ParamType>
+  void GetInputPortParam(ParamType* param) const {
+    param->nPortIndex = input_port_;
+    OMX_ERRORTYPE error = OMX_GetParameter(handle_, ParamType::Index, param);
+    SB_DCHECK(error == OMX_ErrorNone) << std::hex << "OMX_GetParameter("
+                                      << ParamType::Index
+                                      << ") failed with error " << error;
+  }
+
+  template <typename ParamType>
+  void GetOutputPortParam(ParamType* param) const {
+    param->nPortIndex = output_port_;
+    OMX_ERRORTYPE error = OMX_GetParameter(handle_, ParamType::Index, param);
+    SB_DCHECK(error == OMX_ErrorNone) << std::hex << "OMX_GetParameter("
+                                      << ParamType::Index
+                                      << ") failed with error " << error;
+  }
+
+  template <typename ParamType>
+  void SetPortParam(const ParamType& param) const {
+    OMX_ERRORTYPE error = OMX_SetParameter(handle_, ParamType::Index,
+                                           const_cast<ParamType*>(&param));
+    SB_DCHECK(error == OMX_ErrorNone) << std::hex << "OMX_SetParameter("
+                                      << ParamType::Index
+                                      << ") failed with error " << error;
+  }
+
+ private:
+  typedef std::vector<OMX_BUFFERHEADERTYPE*> BufferHeaders;
+
+  struct EventDescription {
+    OMX_EVENTTYPE event;
+    OMX_U32 data1;
+    OMX_U32 data2;
+    OMX_PTR event_data;
+  };
+
+  typedef std::vector<EventDescription> EventDescriptions;
+
+  void SendCommand(OMX_COMMANDTYPE command, int param);
+  void WaitForCommandCompletion();
+  void SendCommandAndWaitForCompletion(OMX_COMMANDTYPE command, int param);
+  void EnableInputPortAndAllocateBuffers();
+  void EnableOutputPortAndAllocateBuffer();
+  OMX_BUFFERHEADERTYPE* GetUnusedInputBuffer();
+
+  OMX_ERRORTYPE OnEvent(OMX_EVENTTYPE event,
+                        OMX_U32 data1,
+                        OMX_U32 data2,
+                        OMX_PTR event_data);
+  OMX_ERRORTYPE OnEmptyBufferDone(OMX_BUFFERHEADERTYPE* buffer);
+  void OnFillBufferDone(OMX_BUFFERHEADERTYPE* buffer);
+
+  static OMX_ERRORTYPE EventHandler(OMX_HANDLETYPE handle,
+                                    OMX_PTR app_data,
+                                    OMX_EVENTTYPE event,
+                                    OMX_U32 data1,
+                                    OMX_U32 data2,
+                                    OMX_PTR event_data);
+  static OMX_ERRORTYPE EmptyBufferDone(OMX_HANDLETYPE handle,
+                                       OMX_PTR app_data,
+                                       OMX_BUFFERHEADERTYPE* buffer);
+  static OMX_ERRORTYPE FillBufferDone(OMX_HANDLETYPE handle,
+                                      OMX_PTR app_data,
+                                      OMX_BUFFERHEADERTYPE* buffer);
+
+  Mutex mutex_;
+  ConditionVariable condition_variable_;
+  const size_t minimum_output_size_;
+  OMX_HANDLETYPE handle_;
+  int input_port_;
+  int output_port_;
+  bool output_setting_changed_;
+  EventDescriptions event_descriptions_;
+  BufferHeaders unused_buffers_;
+  OMX_BUFFERHEADERTYPE* output_buffer_;
+  OMXParamPortDefinition output_port_definition_;
+  bool output_buffer_filled_;
+};
+
+}  // namespace open_max
+}  // namespace shared
+}  // namespace raspi
+}  // namespace starboard
+
+#endif  // STARBOARD_RASPI_SHARED_OPEN_MAX_OPEN_MAX_COMPONENT_H_
diff --git a/src/starboard/raspi/shared/open_max/video_decoder.cc b/src/starboard/raspi/shared/open_max/video_decoder.cc
new file mode 100644
index 0000000..702a9f8
--- /dev/null
+++ b/src/starboard/raspi/shared/open_max/video_decoder.cc
@@ -0,0 +1,103 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/raspi/shared/open_max/video_decoder.h"
+
+#include "starboard/log.h"
+
+namespace starboard {
+namespace raspi {
+namespace shared {
+namespace open_max {
+
+using starboard::shared::starboard::player::VideoFrame;
+
+namespace {
+
+const char kVideoDecodeComponentName[] = "OMX.broadcom.video_decode";
+const size_t kMaxVideoFrameSize = 1920 * 1088 * 3 / 2;
+
+}  // namespace
+
+VideoDecoder::VideoDecoder(SbMediaVideoCodec video_codec)
+    : component_(kVideoDecodeComponentName, kMaxVideoFrameSize),
+      host_(NULL),
+      stream_ended_(false) {
+  SB_DCHECK(video_codec == kSbMediaVideoCodecH264);
+
+  OMXVideoParamPortFormat port_format;
+  component_.GetInputPortParam(&port_format);
+  port_format.eCompressionFormat = OMX_VIDEO_CodingAVC;
+  component_.SetPortParam(port_format);
+
+  component_.Start();
+}
+
+VideoDecoder::~VideoDecoder() {}
+
+void VideoDecoder::SetHost(Host* host) {
+  SB_DCHECK(host != NULL);
+  SB_DCHECK(host_ == NULL);
+  host_ = host;
+}
+
+void VideoDecoder::WriteInputBuffer(const InputBuffer& input_buffer) {
+  SB_DCHECK(host_ != NULL);
+
+  if (stream_ended_) {
+    SB_LOG(ERROR) << "WriteInputFrame() was called after WriteEndOfStream().";
+    return;
+  }
+  component_.WriteData(input_buffer.data(), input_buffer.size(),
+                       input_buffer.pts() * kSbTimeSecond / kSbMediaTimeSecond);
+
+  VideoFrame frame;
+  if (component_.ReadVideoFrame(&frame)) {
+    host_->OnDecoderStatusUpdate(kNeedMoreInput, &frame);
+  } else {
+    host_->OnDecoderStatusUpdate(kNeedMoreInput, NULL);
+  }
+}
+
+void VideoDecoder::WriteEndOfStream() {
+  SB_DCHECK(!stream_ended_);
+  stream_ended_ = true;
+  component_.WriteEOS();
+}
+
+void VideoDecoder::Reset() {
+  stream_ended_ = false;
+  component_.Flush();
+}
+
+}  // namespace open_max
+}  // namespace shared
+}  // namespace raspi
+
+namespace shared {
+namespace starboard {
+namespace player {
+namespace filter {
+
+// static
+VideoDecoder* VideoDecoder::Create(SbMediaVideoCodec video_codec) {
+  return new raspi::shared::open_max::VideoDecoder(video_codec);
+}
+
+}  // namespace filter
+}  // namespace player
+}  // namespace starboard
+}  // namespace shared
+
+}  // namespace starboard
diff --git a/src/starboard/raspi/shared/open_max/video_decoder.h b/src/starboard/raspi/shared/open_max/video_decoder.h
new file mode 100644
index 0000000..92850da
--- /dev/null
+++ b/src/starboard/raspi/shared/open_max/video_decoder.h
@@ -0,0 +1,56 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_RASPI_SHARED_OPEN_MAX_VIDEO_DECODER_H_
+#define STARBOARD_RASPI_SHARED_OPEN_MAX_VIDEO_DECODER_H_
+
+#include "starboard/media.h"
+#include "starboard/raspi/shared/open_max/open_max_component.h"
+#include "starboard/shared/internal_only.h"
+#include "starboard/shared/starboard/player/filter/video_decoder_internal.h"
+
+namespace starboard {
+namespace raspi {
+namespace shared {
+namespace open_max {
+
+class VideoDecoder
+    : public starboard::shared::starboard::player::filter::VideoDecoder {
+ public:
+  typedef starboard::shared::starboard::player::InputBuffer InputBuffer;
+
+  explicit VideoDecoder(SbMediaVideoCodec video_codec);
+  ~VideoDecoder() SB_OVERRIDE;
+
+  void SetHost(Host* host) SB_OVERRIDE;
+  void WriteInputBuffer(const InputBuffer& input_buffer) SB_OVERRIDE;
+  void WriteEndOfStream() SB_OVERRIDE;
+  void Reset() SB_OVERRIDE;
+
+ private:
+  OpenMaxComponent component_;
+
+  // These variables will be initialized inside ctor or SetHost() and will not
+  // be changed during the life time of this class.
+  Host* host_;
+
+  bool stream_ended_;
+};
+
+}  // namespace open_max
+}  // namespace shared
+}  // namespace raspi
+}  // namespace starboard
+
+#endif  // STARBOARD_RASPI_SHARED_OPEN_MAX_VIDEO_DECODER_H_
diff --git a/src/starboard/raspi/shared/window_internal.cc b/src/starboard/raspi/shared/window_internal.cc
index 532ecd4..cb03c2d 100644
--- a/src/starboard/raspi/shared/window_internal.cc
+++ b/src/starboard/raspi/shared/window_internal.cc
@@ -14,21 +14,19 @@
 
 #include "starboard/raspi/shared/window_internal.h"
 
-#include <bcm_host.h>
-
 #include "starboard/log.h"
 
 namespace {
 const int32_t kLayer = 0;
-const DISPMANX_RESOURCE_HANDLE_T kResource = DISPMANX_NO_HANDLE;
 }  // namespace
 
-SbWindowPrivate::SbWindowPrivate(DISPMANX_DISPLAY_HANDLE_T display,
-                                 const SbWindowOptions* options)
-    : display(display), element(DISPMANX_NO_HANDLE) {
-  VC_RECT_T destination_rect;
-  VC_RECT_T source_rect;
+using starboard::raspi::shared::DispmanxDisplay;
+using starboard::raspi::shared::DispmanxElement;
+using starboard::raspi::shared::DispmanxRect;
+using starboard::raspi::shared::DispmanxResource;
 
+SbWindowPrivate::SbWindowPrivate(const DispmanxDisplay& display,
+                                 const SbWindowOptions* options) {
   uint32_t window_width = 0;
   uint32_t window_height = 0;
   if (options && options->size.width > 0 && options->size.height > 0) {
@@ -41,41 +39,23 @@
     SB_DCHECK(result >= 0);
   }
 
-  destination_rect.x = 0;
-  destination_rect.y = 0;
-  destination_rect.width = window_width;
-  destination_rect.height = window_height;
-
-  source_rect.x = 0;
-  source_rect.y = 0;
-  // This shift is part of the examples, but unexplained. It appears to work.
-  source_rect.width = window_width << 16;
-  source_rect.height = window_height << 16;
-
+  DispmanxRect destination_rect(0, 0, window_width, window_height);
+  // The "<< 16"s are part of the examples, but unexplained. It appears to work.
+  DispmanxRect source_rect(0, 0, window_width << 16, window_height << 16);
+  // The window doesn't have an image resource associated with it.
+  DispmanxResource resource;
   // Creating a window (called an "element" here, created by adding it to the
   // display) must happen within an "update", which seems to represent a sort of
   // window manager transaction.
-  DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0 /*screen*/);
-  SB_DCHECK(update != DISPMANX_NO_HANDLE);
-  element = vc_dispmanx_element_add(update, display, kLayer, &destination_rect,
-                                    kResource, &source_rect,
-                                    DISPMANX_PROTECTION_NONE, NULL /*alpha*/,
-                                    NULL /*clamp*/, DISPMANX_NO_ROTATE);
-  SB_DCHECK(element != DISPMANX_NO_HANDLE);
-  int32_t result = vc_dispmanx_update_submit_sync(update);
-  SB_DCHECK(result == 0) << " result=" << result;
-
+  element.reset(new DispmanxElement(display, kLayer, destination_rect, resource,
+                                    source_rect));
   // We can then populate this struct, a pointer to which is what EGL expects as
   // a "native window" handle.
-  window.element = element;
+  window.element = element->handle();
   window.width = window_width;
   window.height = window_height;
 }
 
 SbWindowPrivate::~SbWindowPrivate() {
-  DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0 /*screen*/);
-  int32_t result = vc_dispmanx_element_remove(update, element);
-  SB_DCHECK(result == 0) << " result=" << result;
-  vc_dispmanx_update_submit_sync(update);
-  element = DISPMANX_NO_HANDLE;
+  element.reset();
 }
diff --git a/src/starboard/raspi/shared/window_internal.h b/src/starboard/raspi/shared/window_internal.h
index 06a77d5..3f51a8a 100644
--- a/src/starboard/raspi/shared/window_internal.h
+++ b/src/starboard/raspi/shared/window_internal.h
@@ -15,19 +15,19 @@
 #ifndef STARBOARD_RASPI_SHARED_WINDOW_INTERNAL_H_
 #define STARBOARD_RASPI_SHARED_WINDOW_INTERNAL_H_
 
-#include <bcm_host.h>
 #include <EGL/egl.h>
 
+#include "starboard/common/scoped_ptr.h"
+#include "starboard/raspi/shared/dispmanx_util.h"
 #include "starboard/shared/internal_only.h"
 #include "starboard/window.h"
 
 struct SbWindowPrivate {
-  SbWindowPrivate(DISPMANX_DISPLAY_HANDLE_T display,
+  SbWindowPrivate(const starboard::raspi::shared::DispmanxDisplay& display,
                   const SbWindowOptions* options);
   ~SbWindowPrivate();
 
-  DISPMANX_DISPLAY_HANDLE_T display;
-  DISPMANX_ELEMENT_HANDLE_T element;
+  starboard::scoped_ptr<starboard::raspi::shared::DispmanxElement> element;
   EGL_DISPMANX_WINDOW_T window;
 };
 
diff --git a/src/starboard/shared/dlmalloc/memory_map.cc b/src/starboard/shared/dlmalloc/memory_map.cc
index 59730fc..c5d3829 100644
--- a/src/starboard/shared/dlmalloc/memory_map.cc
+++ b/src/starboard/shared/dlmalloc/memory_map.cc
@@ -13,9 +13,11 @@
 // limitations under the License.
 
 #include "starboard/memory.h"
-
+#include "starboard/shared/starboard/memory_reporter_internal.h"
 #include "starboard/shared/dlmalloc/page_internal.h"
 
 void* SbMemoryMap(int64_t size_bytes, int flags, const char* name) {
-  return SbPageMap(size_bytes, flags, name);
+  void* memory = SbPageMap(size_bytes, flags, name);
+  SbMemoryReporterReportMappedMemory(memory, size_bytes);
+  return memory;
 }
diff --git a/src/starboard/shared/dlmalloc/memory_unmap.cc b/src/starboard/shared/dlmalloc/memory_unmap.cc
index ff45918..dc32164 100644
--- a/src/starboard/shared/dlmalloc/memory_unmap.cc
+++ b/src/starboard/shared/dlmalloc/memory_unmap.cc
@@ -13,9 +13,10 @@
 // limitations under the License.
 
 #include "starboard/memory.h"
-
+#include "starboard/shared/starboard/memory_reporter_internal.h"
 #include "starboard/shared/dlmalloc/page_internal.h"
 
 bool SbMemoryUnmap(void* virtual_address, int64_t size_bytes) {
+  SbMemoryReporterReportUnmappedMemory(virtual_address, size_bytes);
   return SbPageUnmap(virtual_address, size_bytes);
 }
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc
index 618b9e3..1444180 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc
+++ b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc
@@ -14,6 +14,7 @@
 
 #include "starboard/shared/ffmpeg/ffmpeg_audio_decoder.h"
 
+#include "starboard/audio_sink.h"
 #include "starboard/log.h"
 
 namespace starboard {
@@ -22,15 +23,23 @@
 
 namespace {
 
-// The required output format for the decoder is interleaved float.  However
-// the output of the ffmpeg decoder can be in other formats.  So libavresample
-// is used to convert the output into the required format.
-void ConvertToInterleavedFloat(int source_sample_format,
-                               int channel_layout,
-                               int sample_rate,
-                               int samples_per_channel,
-                               uint8_t** input_buffer,
-                               uint8_t* output_buffer) {
+SbMediaAudioSampleType GetSupportedSampleType() {
+  if (SbAudioSinkIsAudioSampleTypeSupported(kSbMediaAudioSampleTypeFloat32)) {
+    return kSbMediaAudioSampleTypeFloat32;
+  }
+  return kSbMediaAudioSampleTypeInt16;
+}
+
+// The required output format and the output of the ffmpeg decoder can be
+// different.  In this case libavresample is used to convert the ffmpeg output
+// into the required format.
+void ConvertSamples(int source_sample_format,
+                    int target_sample_format,
+                    int channel_layout,
+                    int sample_rate,
+                    int samples_per_channel,
+                    uint8_t** input_buffer,
+                    uint8_t* output_buffer) {
   AVAudioResampleContext* context = avresample_alloc_context();
   SB_DCHECK(context != NULL);
 
@@ -39,7 +48,7 @@
   av_opt_set_int(context, "in_sample_rate", sample_rate, 0);
   av_opt_set_int(context, "out_sample_rate", sample_rate, 0);
   av_opt_set_int(context, "in_sample_fmt", source_sample_format, 0);
-  av_opt_set_int(context, "out_sample_fmt", AV_SAMPLE_FMT_FLT, 0);
+  av_opt_set_int(context, "out_sample_fmt", target_sample_format, 0);
   av_opt_set_int(context, "internal_sample_fmt", source_sample_format, 0);
 
   int result = avresample_open(context);
@@ -58,7 +67,8 @@
 
 AudioDecoder::AudioDecoder(SbMediaAudioCodec audio_codec,
                            const SbMediaAudioHeader& audio_header)
-    : codec_context_(NULL),
+    : sample_type_(GetSupportedSampleType()),
+      codec_context_(NULL),
       av_frame_(NULL),
       stream_ended_(false),
       audio_header_(audio_header) {
@@ -72,7 +82,7 @@
 }
 
 void AudioDecoder::Decode(const InputBuffer& input_buffer,
-                          std::vector<float>* output) {
+                          std::vector<uint8_t>* output) {
   SB_CHECK(output != NULL);
   SB_CHECK(codec_context_ != NULL);
 
@@ -105,11 +115,16 @@
   audio_header_.samples_per_second = codec_context_->sample_rate;
 
   if (decoded_audio_size > 0) {
-    output->resize(decoded_audio_size / sizeof(float));
-    ConvertToInterleavedFloat(
-        codec_context_->sample_fmt, codec_context_->channel_layout,
-        audio_header_.samples_per_second, av_frame_->nb_samples,
-        av_frame_->extended_data, reinterpret_cast<uint8_t*>(&(*output)[0]));
+    output->resize(codec_context_->channels * av_frame_->nb_samples *
+                   (sample_type_ == kSbMediaAudioSampleTypeInt16 ? 2 : 4));
+    if (codec_context_->sample_fmt == codec_context_->request_sample_fmt) {
+      memcpy(&(*output)[0], av_frame_->extended_data, output->size());
+    } else {
+      ConvertSamples(
+          codec_context_->sample_fmt, codec_context_->request_sample_fmt,
+          codec_context_->channel_layout, audio_header_.samples_per_second,
+          av_frame_->nb_samples, av_frame_->extended_data, &(*output)[0]);
+    }
   } else {
     // TODO: Consider fill it with silence.
     SB_LOG(ERROR) << "Decoded audio frame is empty.";
@@ -127,7 +142,11 @@
   stream_ended_ = false;
 }
 
-int AudioDecoder::GetSamplesPerSecond() {
+SbMediaAudioSampleType AudioDecoder::GetSampleType() const {
+  return sample_type_;
+}
+
+int AudioDecoder::GetSamplesPerSecond() const {
   return audio_header_.samples_per_second;
 }
 
@@ -144,7 +163,11 @@
   codec_context_->codec_type = AVMEDIA_TYPE_AUDIO;
   codec_context_->codec_id = AV_CODEC_ID_AAC;
   // Request_sample_fmt is set by us, but sample_fmt is set by the decoder.
-  codec_context_->request_sample_fmt = AV_SAMPLE_FMT_FLT;  // interleaved float
+  if (sample_type_ == kSbMediaAudioSampleTypeInt16) {
+    codec_context_->request_sample_fmt = AV_SAMPLE_FMT_S16;
+  } else {
+    codec_context_->request_sample_fmt = AV_SAMPLE_FMT_FLT;
+  }
 
   codec_context_->channels = audio_header_.number_of_channels;
   codec_context_->sample_rate = audio_header_.samples_per_second;
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.h b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.h
index 3eda447..c2a78db 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.h
+++ b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.h
@@ -35,10 +35,11 @@
   ~AudioDecoder() SB_OVERRIDE;
 
   void Decode(const InputBuffer& input_buffer,
-              std::vector<float>* output) SB_OVERRIDE;
+              std::vector<uint8_t>* output) SB_OVERRIDE;
   void WriteEndOfStream() SB_OVERRIDE;
   void Reset() SB_OVERRIDE;
-  int GetSamplesPerSecond() SB_OVERRIDE;
+  SbMediaAudioSampleType GetSampleType() const SB_OVERRIDE;
+  int GetSamplesPerSecond() const SB_OVERRIDE;
 
   bool is_valid() const { return codec_context_ != NULL; }
 
@@ -46,6 +47,7 @@
   void InitializeCodec();
   void TeardownCodec();
 
+  SbMediaAudioSampleType sample_type_;
   AVCodecContext* codec_context_;
   AVFrame* av_frame_;
 
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc b/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc
index 0d04361..7b9efed 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc
+++ b/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc
@@ -78,6 +78,8 @@
   frame->height = codec_context->height;
   frame->format = codec_context->pix_fmt;
 
+  frame->reordered_opaque = codec_context->reordered_opaque;
+
   return 0;
 }
 
@@ -180,6 +182,7 @@
       packet.data = const_cast<uint8_t*>(event.input_buffer.data());
       packet.size = event.input_buffer.size();
       packet.pts = event.input_buffer.pts();
+      codec_context_->reordered_opaque = packet.pts;
 
       DecodePacket(&packet);
       host_->OnDecoderStatusUpdate(kNeedMoreInput, NULL);
@@ -221,8 +224,9 @@
   int pitch = AlignUp(av_frame_->width, kAlignment * 2);
 
   VideoFrame frame = VideoFrame::CreateYV12Frame(
-      av_frame_->width, av_frame_->height, pitch, av_frame_->pkt_pts,
-      av_frame_->data[0], av_frame_->data[1], av_frame_->data[2]);
+      av_frame_->width, av_frame_->height, pitch,
+      codec_context_->reordered_opaque, av_frame_->data[0], av_frame_->data[1],
+      av_frame_->data[2]);
   host_->OnDecoderStatusUpdate(kBufferFull, &frame);
   return true;
 }
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.h b/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.h
index 8c5e99a..6fcc2f1 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.h
+++ b/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.h
@@ -34,7 +34,7 @@
   typedef starboard::player::InputBuffer InputBuffer;
   typedef starboard::player::VideoFrame VideoFrame;
 
-  explicit VideoDecoder(SbMediaVideoCodec);
+  explicit VideoDecoder(SbMediaVideoCodec video_codec);
   ~VideoDecoder() SB_OVERRIDE;
 
   void SetHost(Host* host) SB_OVERRIDE;
diff --git a/src/starboard/shared/posix/time_get_monotonic_thread_now.cc b/src/starboard/shared/posix/time_get_monotonic_thread_now.cc
new file mode 100644
index 0000000..7050050
--- /dev/null
+++ b/src/starboard/shared/posix/time_get_monotonic_thread_now.cc
@@ -0,0 +1,30 @@
+// 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/time.h"
+
+#include <time.h>
+
+#include "starboard/log.h"
+#include "starboard/shared/posix/time_internal.h"
+
+SbTimeMonotonic SbTimeGetMonotonicThreadNow() {
+  struct timespec time;
+  if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &time) != 0) {
+    SB_NOTREACHED() << "clock_gettime(CLOCK_THREAD_CPUTIME_ID) failed.";
+    return 0;
+  }
+
+  return FromTimespecDelta(&time);
+}
diff --git a/src/starboard/shared/pthread/thread_create.cc b/src/starboard/shared/pthread/thread_create.cc
index 8718ba4..f2ab13d 100644
--- a/src/starboard/shared/pthread/thread_create.cc
+++ b/src/starboard/shared/pthread/thread_create.cc
@@ -61,19 +61,19 @@
 int SbThreadPriorityToNice(SbThreadPriority priority) {
   switch (priority) {
     case kSbThreadPriorityLowest:
-      return 10;
+      return 19;
     case kSbThreadPriorityLow:
-      return 5;
+      return 18;
     case kSbThreadNoPriority:
     // Fall through on purpose to default to kThreadPriority_Normal.
     case kSbThreadPriorityNormal:
-      return -5;
+      return 10;
     case kSbThreadPriorityHigh:
-      return -15;
+      return 2;
     case kSbThreadPriorityHighest:
-      return -18;
+      return 1;
     case kSbThreadPriorityRealTime:
-      return -19;
+      return 0;
     default:
       SB_NOTREACHED();
       return 0;
diff --git a/src/starboard/shared/starboard/application.cc b/src/starboard/shared/starboard/application.cc
index 1adc590..96efbdb 100644
--- a/src/starboard/shared/starboard/application.cc
+++ b/src/starboard/shared/starboard/application.cc
@@ -130,7 +130,7 @@
 
 #if SB_HAS(PLAYER) && SB_IS(PLAYER_PUNCHED_OUT)
 void Application::HandleFrame(SbPlayer player,
-                              const player::VideoFrame& frame,
+                              const VideoFrame& frame,
                               int x,
                               int y,
                               int width,
diff --git a/src/starboard/shared/starboard/application.h b/src/starboard/shared/starboard/application.h
index 7328f2e..f8609ce 100644
--- a/src/starboard/shared/starboard/application.h
+++ b/src/starboard/shared/starboard/application.h
@@ -38,6 +38,8 @@
 // dispatching events to the Starboard event handler, SbEventHandle.
 class Application {
  public:
+  typedef player::VideoFrame VideoFrame;
+
   // You can use a void(void *) function to signal that a state-transition event
   // has completed.
   typedef SbEventDataDestructor EventHandledCallback;
@@ -200,7 +202,7 @@
   // used when the application needs to composite video frames with punch-out
   // video manually (should be rare). Will be called from an external thread.
   void HandleFrame(SbPlayer player,
-                   const player::VideoFrame& frame,
+                   const VideoFrame& frame,
                    int x,
                    int y,
                    int width,
@@ -222,7 +224,7 @@
   // Subclasses may override this method to accept video frames from the media
   // system. Will be called from an external thread.
   virtual void AcceptFrame(SbPlayer player,
-                           const player::VideoFrame& frame,
+                           const VideoFrame& frame,
                            int x,
                            int y,
                            int width,
diff --git a/src/starboard/shared/starboard/memory_reporter_internal.h b/src/starboard/shared/starboard/memory_reporter_internal.h
new file mode 100644
index 0000000..72b2bef
--- /dev/null
+++ b/src/starboard/shared/starboard/memory_reporter_internal.h
@@ -0,0 +1,40 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_SHARED_STARBOARD_MEMORY_REPORTER_INTERNAL_H_
+#define STARBOARD_SHARED_STARBOARD_MEMORY_REPORTER_INTERNAL_H_
+
+#include "starboard/export.h"
+#include "starboard/shared/internal_only.h"
+#include "starboard/types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Internal function used to track mapped memory. This is used internally by
+// implementations of SbMemoryMap().
+SB_EXPORT void SbMemoryReporterReportMappedMemory(const void* memory,
+                                                  size_t size);
+
+// Internal function used to track mapped memory. This is used internally by
+// implementations of SbMemoryUnmap().
+SB_EXPORT void SbMemoryReporterReportUnmappedMemory(const void* memory,
+                                                    size_t size);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // STARBOARD_SHARED_STARBOARD_MEMORY_REPORTER_INTERNAL_H_
diff --git a/src/starboard/shared/starboard/player/filter/audio_decoder_internal.h b/src/starboard/shared/starboard/player/filter/audio_decoder_internal.h
index b8bdafe..cb1850c 100644
--- a/src/starboard/shared/starboard/player/filter/audio_decoder_internal.h
+++ b/src/starboard/shared/starboard/player/filter/audio_decoder_internal.h
@@ -20,6 +20,7 @@
 #include "starboard/media.h"
 #include "starboard/shared/internal_only.h"
 #include "starboard/shared/starboard/player/input_buffer_internal.h"
+#include "starboard/types.h"
 
 namespace starboard {
 namespace shared {
@@ -35,7 +36,7 @@
   // Decode the encoded audio data stored in |input_buffer| and store the
   // result in |output|.
   virtual void Decode(const InputBuffer& input_buffer,
-                      std::vector<float>* output) = 0;
+                      std::vector<uint8_t>* output) = 0;
   // Note that there won't be more input data unless Reset() is called.
   virtual void WriteEndOfStream() = 0;
   // Clear any cached buffer of the codec and reset the state of the codec.
@@ -43,10 +44,13 @@
   // data from previous buffers are cleared.
   virtual void Reset() = 0;
 
+  // Return the sample type of the decoded pcm data.
+  virtual SbMediaAudioSampleType GetSampleType() const = 0;
+
   // Return the sample rate of the incoming audio.  This should be used by the
   // audio renderer as the sample rate of the underlying audio stream can be
   // different than the sample rate stored in the meta data.
-  virtual int GetSamplesPerSecond() = 0;
+  virtual int GetSamplesPerSecond() const = 0;
 
   // Individual implementation has to implement this function to create an
   // audio decoder.
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_internal.cc b/src/starboard/shared/starboard/player/filter/audio_renderer_internal.cc
index 3a53533..105e23f 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_internal.cc
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_internal.cc
@@ -33,10 +33,13 @@
 AudioRenderer::AudioRenderer(scoped_ptr<AudioDecoder> decoder,
                              const SbMediaAudioHeader& audio_header)
     : channels_(audio_header.number_of_channels),
+      bytes_per_frame_(
+          (decoder->GetSampleType() == kSbMediaAudioSampleTypeInt16 ? 2 : 4) *
+          channels_),
       paused_(true),
       seeking_(false),
       seeking_to_pts_(0),
-      frame_buffer_(kMaxCachedFrames * audio_header.number_of_channels),
+      frame_buffer_(kMaxCachedFrames * bytes_per_frame_),
       frames_in_buffer_(0),
       offset_in_frames_(0),
       frames_consumed_(0),
@@ -61,7 +64,7 @@
   }
 
   SbMediaTime input_pts = input_buffer.pts();
-  std::vector<float> decoded_audio;
+  std::vector<uint8_t> decoded_audio;
   decoder_->Decode(input_buffer, &decoded_audio);
   if (decoded_audio.empty()) {
     SB_DLOG(ERROR) << "decoded_audio contains no frames.";
@@ -76,9 +79,9 @@
       }
     }
 
-    AppendFrames(&decoded_audio[0], decoded_audio.size() / channels_);
+    AppendFrames(&decoded_audio[0], decoded_audio.size() / bytes_per_frame_);
 
-    if (seeking_ && frame_buffer_.size() > kPrerollFrames * channels_) {
+    if (seeking_ && frame_buffer_.size() > kPrerollFrames * bytes_per_frame_) {
       seeking_ = false;
     }
   }
@@ -91,7 +94,7 @@
               SbAudioSinkGetNearestSupportedSampleFrequency(sample_rate));
     // TODO: Handle sink creation failure.
     audio_sink_ = SbAudioSinkCreate(
-        channels_, sample_rate, kSbMediaAudioSampleTypeFloat32,
+        channels_, sample_rate, decoder_->GetSampleType(),
         kSbMediaAudioFrameStorageTypeInterleaved,
         reinterpret_cast<SbAudioSinkFrameBuffers>(frame_buffers_),
         kMaxCachedFrames, &AudioRenderer::UpdateSourceStatusFunc,
@@ -220,23 +223,23 @@
   frames_consumed_ += frames_consumed;
 }
 
-void AudioRenderer::AppendFrames(const float* source_buffer,
+void AudioRenderer::AppendFrames(const uint8_t* source_buffer,
                                  int frames_to_append) {
   SB_DCHECK(frames_in_buffer_ + frames_to_append <= kMaxCachedFrames);
 
   int offset_to_append =
       (offset_in_frames_ + frames_in_buffer_) % kMaxCachedFrames;
   if (frames_to_append > kMaxCachedFrames - offset_to_append) {
-    SbMemoryCopy(
-        &frame_buffer_[offset_to_append * channels_], source_buffer,
-        (kMaxCachedFrames - offset_to_append) * sizeof(float) * channels_);
-    source_buffer += (kMaxCachedFrames - offset_to_append) * channels_;
+    SbMemoryCopy(&frame_buffer_[offset_to_append * bytes_per_frame_],
+                 source_buffer,
+                 (kMaxCachedFrames - offset_to_append) * bytes_per_frame_);
+    source_buffer += (kMaxCachedFrames - offset_to_append) * bytes_per_frame_;
     frames_to_append -= kMaxCachedFrames - offset_to_append;
     frames_in_buffer_ += kMaxCachedFrames - offset_to_append;
     offset_to_append = 0;
   }
-  SbMemoryCopy(&frame_buffer_[offset_to_append * channels_], source_buffer,
-               frames_to_append * sizeof(float) * channels_);
+  SbMemoryCopy(&frame_buffer_[offset_to_append * bytes_per_frame_],
+               source_buffer, frames_to_append * bytes_per_frame_);
   frames_in_buffer_ += frames_to_append;
 }
 
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_internal.h b/src/starboard/shared/starboard/player/filter/audio_renderer_internal.h
index c85f1fe..e14457c 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_internal.h
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_internal.h
@@ -25,6 +25,7 @@
 #include "starboard/shared/internal_only.h"
 #include "starboard/shared/starboard/player/filter/audio_decoder_internal.h"
 #include "starboard/shared/starboard/player/input_buffer_internal.h"
+#include "starboard/types.h"
 
 namespace starboard {
 namespace shared {
@@ -76,17 +77,18 @@
                           bool* is_eos_reached);
   void ConsumeFrames(int frames_consumed);
 
-  void AppendFrames(const float* source_buffer, int frames_to_append);
+  void AppendFrames(const uint8_t* source_buffer, int frames_to_append);
 
   const int channels_;
+  const int bytes_per_frame_;
 
   Mutex mutex_;
   bool paused_;
   bool seeking_;
   SbMediaTime seeking_to_pts_;
 
-  std::vector<float> frame_buffer_;
-  float* frame_buffers_[1];
+  std::vector<uint8_t> frame_buffer_;
+  uint8_t* frame_buffers_[1];
   int frames_in_buffer_;
   int offset_in_frames_;
 
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc b/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc
index 3898af5..65ee800 100644
--- a/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc
+++ b/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc
@@ -33,19 +33,24 @@
 }
 
 void VideoRenderer::WriteSample(const InputBuffer& input_buffer) {
-  ScopedLock lock(mutex_);
+  SB_DCHECK(thread_checker_.CalledOnValidThread());
 
   if (end_of_stream_written_) {
     SB_LOG(ERROR) << "Appending video sample at " << input_buffer.pts()
                   << " after EOS reached.";
     return;
   }
-  need_more_input_ = false;
+
+  {
+    ScopedLock lock(mutex_);
+    need_more_input_ = false;
+  }
+
   decoder_->WriteInputBuffer(input_buffer);
 }
 
 void VideoRenderer::WriteEndOfStream() {
-  ScopedLock lock(mutex_);
+  SB_DCHECK(thread_checker_.CalledOnValidThread());
 
   SB_LOG_IF(WARNING, end_of_stream_written_)
       << "Try to write EOS after EOS is reached";
@@ -57,6 +62,7 @@
 }
 
 void VideoRenderer::Seek(SbMediaTime seek_to_pts) {
+  SB_DCHECK(thread_checker_.CalledOnValidThread());
   SB_DCHECK(seek_to_pts >= 0);
 
   decoder_->Reset();
@@ -74,7 +80,7 @@
 }
 
 const VideoFrame& VideoRenderer::GetCurrentFrame(SbMediaTime media_time) {
-  ScopedLock lock(mutex_);
+  SB_DCHECK(thread_checker_.CalledOnValidThread());
 
   if (frames_.empty()) {
     return seeking_frame_;
@@ -89,18 +95,18 @@
 }
 
 bool VideoRenderer::IsEndOfStreamPlayed() const {
-  ScopedLock lock(mutex_);
+  SB_DCHECK(thread_checker_.CalledOnValidThread());
   return end_of_stream_written_ && frames_.size() <= 1;
 }
 
 bool VideoRenderer::CanAcceptMoreData() const {
-  ScopedLock lock(mutex_);
+  SB_DCHECK(thread_checker_.CalledOnValidThread());
   return frames_.size() < kMaxCachedFrames && !end_of_stream_written_ &&
          need_more_input_;
 }
 
 bool VideoRenderer::IsSeekingInProgress() const {
-  ScopedLock lock(mutex_);
+  SB_DCHECK(thread_checker_.CalledOnValidThread());
   return seeking_;
 }
 
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_internal.h b/src/starboard/shared/starboard/player/filter/video_renderer_internal.h
index 43f899b..8450e59 100644
--- a/src/starboard/shared/starboard/player/filter/video_renderer_internal.h
+++ b/src/starboard/shared/starboard/player/filter/video_renderer_internal.h
@@ -25,6 +25,7 @@
 #include "starboard/shared/starboard/player/filter/video_decoder_internal.h"
 #include "starboard/shared/starboard/player/input_buffer_internal.h"
 #include "starboard/shared/starboard/player/video_frame_internal.h"
+#include "starboard/shared/starboard/thread_checker.h"
 
 namespace starboard {
 namespace shared {
@@ -66,6 +67,7 @@
   void OnDecoderStatusUpdate(VideoDecoder::Status status,
                              VideoFrame* frame) SB_OVERRIDE;
 
+  ThreadChecker thread_checker_;
   ::starboard::Mutex mutex_;
 
   bool seeking_;
diff --git a/src/starboard/shared/starboard/player/player_create.cc b/src/starboard/shared/starboard/player/player_create.cc
index 5581ca8..c09f526 100644
--- a/src/starboard/shared/starboard/player/player_create.cc
+++ b/src/starboard/shared/starboard/player/player_create.cc
@@ -15,6 +15,7 @@
 #include "starboard/player.h"
 
 #include "starboard/configuration.h"
+#include "starboard/decode_target.h"
 #include "starboard/log.h"
 #include "starboard/shared/starboard/player/filter/filter_based_player_worker_handler.h"
 #include "starboard/shared/starboard/player/player_internal.h"
@@ -33,8 +34,16 @@
                         SbPlayerDeallocateSampleFunc sample_deallocate_func,
                         SbPlayerDecoderStatusFunc decoder_status_func,
                         SbPlayerStatusFunc player_status_func,
-                        void* context) {
+                        void* context
+#if SB_VERSION(3)
+                        ,
+                        SbDecodeTargetProvider* provider
+#endif
+                        ) {
   SB_UNREFERENCED_PARAMETER(window);
+#if SB_VERSION(3)
+  SB_UNREFERENCED_PARAMETER(provider);
+#endif
 
   if (audio_codec != kSbMediaAudioCodecAac) {
     SB_LOG(ERROR) << "Unsupported audio codec " << audio_codec;
diff --git a/src/starboard/shared/starboard/player/video_frame_internal.cc b/src/starboard/shared/starboard/player/video_frame_internal.cc
index d1a0099..793066d 100644
--- a/src/starboard/shared/starboard/player/video_frame_internal.cc
+++ b/src/starboard/shared/starboard/player/video_frame_internal.cc
@@ -183,6 +183,8 @@
 

   int y_plane_size_in_bytes = height * pitch_in_bytes;

   int uv_plane_size_in_bytes = uv_height * uv_pitch_in_bytes;

+  frame.pixel_buffer_.reserve(y_plane_size_in_bytes +

+                              uv_plane_size_in_bytes * 2);

   frame.pixel_buffer_.assign(y, y + y_plane_size_in_bytes);

   frame.pixel_buffer_.insert(frame.pixel_buffer_.end(), u,

                              u + uv_plane_size_in_bytes);

diff --git a/src/starboard/shared/stub/decode_target_is_opaque.cc b/src/starboard/shared/stub/decode_target_is_opaque.cc
new file mode 100644
index 0000000..1798975
--- /dev/null
+++ b/src/starboard/shared/stub/decode_target_is_opaque.cc
@@ -0,0 +1,24 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/configuration.h"
+#include "starboard/decode_target.h"
+
+#if !(SB_VERSION(3) && SB_HAS(GRAPHICS))
+#error "SbDecodeTargetIsOpaque requires SB_VERSION(3) and SB_HAS(GRAPHICS)."
+#endif
+
+bool SbDecodeTargetIsOpaque(SbDecodeTarget decode_target) {
+  return false;
+}
diff --git a/src/starboard/shared/stub/image_decode.cc b/src/starboard/shared/stub/image_decode.cc
new file mode 100644
index 0000000..ca1ff97
--- /dev/null
+++ b/src/starboard/shared/stub/image_decode.cc
@@ -0,0 +1,28 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/configuration.h"
+#include "starboard/image.h"
+
+#if !(SB_VERSION(3) && SB_HAS(GRAPHICS))
+#error "SbImageDecode requires SB_VERSION(3) and SB_HAS(GRAPHICS)."
+#endif
+
+SbDecodeTarget SbImageDecode(SbDecodeTargetProvider* provider,
+                             void* data,
+                             int data_size,
+                             const char* mime_type,
+                             SbDecodeTargetFormat format) {
+  return kSbDecodeTargetInvalid;
+}
diff --git a/src/starboard/shared/stub/image_is_decode_supported.cc b/src/starboard/shared/stub/image_is_decode_supported.cc
new file mode 100644
index 0000000..2b0b367
--- /dev/null
+++ b/src/starboard/shared/stub/image_is_decode_supported.cc
@@ -0,0 +1,25 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/configuration.h"
+#include "starboard/image.h"
+
+#if !(SB_VERSION(3) && SB_HAS(GRAPHICS))
+#error "SbImageIsDecodeSupported requires SB_VERSION(3) and SB_HAS(GRAPHICS)."
+#endif
+
+bool SbImageIsDecodeSupported(const char* mime_type,
+                              SbDecodeTargetFormat format) {
+  return false;
+}
diff --git a/src/starboard/shared/stub/microphone_get_available.cc b/src/starboard/shared/stub/microphone_get_available.cc
index 126149d..5fdb309 100644
--- a/src/starboard/shared/stub/microphone_get_available.cc
+++ b/src/starboard/shared/stub/microphone_get_available.cc
@@ -18,7 +18,7 @@
 
 int SbMicrophoneGetAvailable(SbMicrophoneInfo* out_info_array,
                              int info_array_size) {
-  return -1;
+  return 0;
 }
 
 #endif  // SB_HAS(MICROPHONE) && SB_VERSION(2)
diff --git a/src/starboard/shared/stub/microphone_read.cc b/src/starboard/shared/stub/microphone_read.cc
index 430195f..2965831 100644
--- a/src/starboard/shared/stub/microphone_read.cc
+++ b/src/starboard/shared/stub/microphone_read.cc
@@ -19,7 +19,7 @@
 int SbMicrophoneRead(SbMicrophone microphone,
                      void* out_audio_data,
                      int audio_data_size) {
-  return 0;
+  return -1;
 }
 
 #endif  // SB_HAS(MICROPHONE) && SB_VERSION(2)
diff --git a/src/starboard/shared/stub/player_create.cc b/src/starboard/shared/stub/player_create.cc
index c9cb1e8..639315c 100644
--- a/src/starboard/shared/stub/player_create.cc
+++ b/src/starboard/shared/stub/player_create.cc
@@ -14,6 +14,10 @@
 
 #include "starboard/player.h"
 
+#if !SB_HAS(PLAYER)
+#error "SbPlayerCreate requires SB_HAS(PLAYER)."
+#endif
+
 SbPlayer SbPlayerCreate(SbWindow /*window*/,
                         SbMediaVideoCodec /*video_codec*/,
                         SbMediaAudioCodec /*audio_codec*/,
@@ -23,6 +27,11 @@
                         SbPlayerDeallocateSampleFunc /*sample_deallocate_func*/,
                         SbPlayerDecoderStatusFunc /*decoder_status_func*/,
                         SbPlayerStatusFunc /*player_status_func*/,
-                        void* /*context*/) {
+                        void* /*context*/
+#if SB_VERSION(3)
+                        ,
+                        SbDecodeTargetProvider* /*provider*/
+#endif
+                        ) {
   return kSbPlayerInvalid;
 }
diff --git a/src/starboard/shared/stub/speech_synthesis_cancel.cc b/src/starboard/shared/stub/speech_synthesis_cancel.cc
new file mode 100644
index 0000000..5a4cf19
--- /dev/null
+++ b/src/starboard/shared/stub/speech_synthesis_cancel.cc
@@ -0,0 +1,22 @@
+// 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/speech_synthesis.h"
+
+#if !SB_HAS(SPEECH_SYNTHESIS) && SB_VERSION(3)
+#error If speech synthesis not enabled on this platform, please exclude it\
+       from the build
+#endif
+
+void SbSpeechSynthesisCancel() {}
diff --git a/src/starboard/shared/stub/speech_synthesis_set_language.cc b/src/starboard/shared/stub/speech_synthesis_set_language.cc
new file mode 100644
index 0000000..383239b
--- /dev/null
+++ b/src/starboard/shared/stub/speech_synthesis_set_language.cc
@@ -0,0 +1,24 @@
+// 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/speech_synthesis.h"
+
+#if !SB_HAS(SPEECH_SYNTHESIS) && SB_VERSION(3)
+#error If speech synthesis not enabled on this platform, please exclude it\
+       from the build
+#endif
+
+bool SbSpeechSynthesisSetLanguage(const char* lang) {
+  return false;
+}
diff --git a/src/starboard/shared/stub/speech_synthesis_speak.cc b/src/starboard/shared/stub/speech_synthesis_speak.cc
new file mode 100644
index 0000000..53cd5f5
--- /dev/null
+++ b/src/starboard/shared/stub/speech_synthesis_speak.cc
@@ -0,0 +1,22 @@
+// 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/speech_synthesis.h"
+
+#if !SB_HAS(SPEECH_SYNTHESIS) && SB_VERSION(3)
+#error If speech synthesis not enabled on this platform, please exclude it\
+       from the build
+#endif
+
+void SbSpeechSynthesisSpeak(const char* text) {}
diff --git a/src/starboard/shared/stub/time_get_monotonic_thread_now.cc b/src/starboard/shared/stub/time_get_monotonic_thread_now.cc
new file mode 100644
index 0000000..feee2b6
--- /dev/null
+++ b/src/starboard/shared/stub/time_get_monotonic_thread_now.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/time.h"
+
+SbTimeMonotonic SbTimeGetMonotonicThreadNow() {
+  return SbTimeMonotonic(0);
+}
diff --git a/src/starboard/socket.h b/src/starboard/socket.h
index b61bb3d..d2893ba 100644
--- a/src/starboard/socket.h
+++ b/src/starboard/socket.h
@@ -12,14 +12,19 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Starboard socket I/O. Starboard supports IPv4 and IPv6, TCP and UDP, server
-// and client sockets. Some platforms may not support IPv6, some may not support
-// listening sockets, and some may not support any kind of sockets at all (or
-// only allow them in debug builds). Starboard ONLY supports non-blocking socket
-// I/O, so all sockets are non-blocking at creation time.
-// Note that, on some platforms, API calls on one end of a socket connection may
-// not be instantaneously aware of manipulations on the socket at the other end
-// of the connection, thus requiring use of either an SbSocketWaiter or
+// Module Overview: Starboard Socket module
+//
+// Defines Starboard socket I/O functions. Starboard supports IPv4 and IPv6,
+// TCP and UDP, server and client sockets. Some platforms may not support IPv6,
+// some may not support listening sockets, and some may not support any kind
+// of sockets at all (or only allow them in debug builds).
+//
+// Starboard ONLY supports non-blocking socket I/O, so all sockets are
+// non-blocking at creation time.
+//
+// Note that, on some platforms, API calls on one end of a socket connection
+// may not be instantaneously aware of manipulations on the socket at the other
+// end of the connection, thus requiring use of either an SbSocketWaiter or
 // spin-polling.
 //
 // TODO: For platforms that do not support sockets at all, they must
@@ -48,9 +53,11 @@
 // A handle to a socket.
 typedef SbSocketPrivate* SbSocket;
 
-// Enumeration of all Starboard socket operation results.
+// Enumeration of all Starboard socket operation results. Despite the enum
+// name, note that the value actually describes the outcome of an operation,
+// which is not always an error.
 typedef enum SbSocketError {
-  // The operation succeeded. Yep.
+  // The operation succeeded.
   kSbSocketOk = 0,
 
   // The operation is blocked on I/O. Either try again "later," or be very
@@ -128,161 +135,249 @@
 }
 
 // Creates a new non-blocking socket for protocol |protocol| using address
-// family |address_type|. Returns the newly created handle, if successful, or
-// kSbSocketInvalid, if not. If unsuccessful, sets the last system error
-// appropriately.
+// family |address_type|.
+//
+// - If successful, this function returns the newly created handle.
+// - If unsuccessful, this function returns |kSbSocketInvalid| and also sets
+//   the last system error appropriately.
+//
+// |address_type|: The type of IP address to use for the socket.
+// |protocol|: The protocol to use for the socket.
 SB_EXPORT SbSocket SbSocketCreate(SbSocketAddressType address_type,
                                   SbSocketProtocol protocol);
 
-// Destroys |socket|. Flushes the socket, closes any connection that may be
-// active on |socket|, and reclaims any resources associated with |socket|,
-// including any registration with an SbSocketWaiter. Returns whether the
-// destruction was successful. Even if this function returns false, you
-// shouldn't be able to use the socket anymore.
+// Destroys the |socket| by flushing it, closing any connection that may be
+// active on it, and reclaiming any resources associated with it, including
+// any registration with an |SbSocketWaiter|.
+//
+// The return value indicates whether the destruction was successful. However,
+// even if this function returns |false|, you should not be able to use the
+// socket any more.
+//
+// |socket|: The SbSocket to be destroyed.
 SB_EXPORT bool SbSocketDestroy(SbSocket socket);
 
 // Opens a connection of |socket|'s type to the host and port specified by
-// |address|. Sets and returns the socket error if unable to bind to
-// |local_address|.
+// |address|. This function sets and returns the socket error if it is unable
+// to connect to |address|. (It returns |kSbSocketOk| if it creates the
+// connection successfully.)
+//
+// |socket|: The type of connection that should be opened.
+// |address|: The host and port to which the socket should connect.
 SB_EXPORT SbSocketError SbSocketConnect(SbSocket socket,
                                         const SbSocketAddress* address);
 
 // Binds |socket| to a specific local interface and port specified by
-// |local_address|, which must not be NULL. Port 0 means choose a port for me
-// and IP address 0.0.0.0 means bind to all interfaces. Sets and returns the
-// socket error if unable to bind to |local_address|.
+// |local_address|. This function sets and returns the socket error if it
+// is unable to bind to |local_address|.
+//
+// |socket|: The SbSocket to be bound to the local interface.
+// |local_address|: The local address to which the socket is to be bound.
+//   This value must not be |NULL|.
+// - Setting the local address to port |0| (or not specifying a port) indicates
+//   that the function should choose a port for you.
+// - Setting the IP address to |0.0.0.0| means that the socket should be bound
+//   to all interfaces.
 SB_EXPORT SbSocketError SbSocketBind(SbSocket socket,
                                      const SbSocketAddress* local_address);
 
-// Causes |socket| to listen on |local_address|. Sets and returns the socket
-// error if unable to listen for some reason.
+// Causes |socket| to listen on the local address that |socket| was previously
+// bound to by SbSocketBind. This function sets and returns the socket error if
+// it is unable to listen for some reason. (It returns |kSbSocketOk| if it
+// creates the connection successfully.)
+//
+// |socket|: The SbSocket on which the function operates.
 SB_EXPORT SbSocketError SbSocketListen(SbSocket socket);
 
-// Accepts a pending connection on |socket|, returning a new SbSocket
-// representing that connection. Sets the error on |socket| and returns
-// kSbSocketInvalid if unable to accept a new connection.
+// Accepts a pending connection on |socket| and returns a new SbSocket
+// representing that connection. This function sets the error on |socket|
+// and returns |kSbSocketInvalid| if it is unable to accept a new connection.
+//
+// |socket|: The SbSocket that is accepting a pending connection.
 SB_EXPORT SbSocket SbSocketAccept(SbSocket socket);
 
-// Returns whether |socket| is connected to anything. Invalid sockets are not
+// Indicates whether |socket| is connected to anything. Invalid sockets are not
 // connected.
+//
+// |socket|: The SbSocket to be checked.
 SB_EXPORT bool SbSocketIsConnected(SbSocket socket);
 
-// Returns whether |socket| is connected to anything, and whether it is
+// Returns whether |socket| is connected to anything, and, if so, whether it is
 // receiving any data.
+//
+// |socket|: The SbSocket to be checked.
 SB_EXPORT bool SbSocketIsConnectedAndIdle(SbSocket socket);
 
-// Returns the last error set on |socket|. If |socket| is not valid, always
-// returns kSbSocketErrorFailed.
+// Returns the last error set on |socket|. If |socket| is not valid, this
+// function returns |kSbSocketErrorFailed|.
+//
+// |socket|: The SbSocket that the last error is returned for.
 SB_EXPORT SbSocketError SbSocketGetLastError(SbSocket socket);
 
-// Clears the last error set on |socket|. Returns whether the socket error was
-// cleared.
+// Clears the last error set on |socket|. The return value indicates whether
+// the socket error was cleared.
 SB_EXPORT bool SbSocketClearLastError(SbSocket socket);
 
 // Gets the address that this socket is bound to locally, if the socket is
-// connected. Returns whether getting the address was successful.
+// connected. The return value indicates whether the address was retrieved
+// successfully.
+//
+// |socket|: The SbSocket for which the local address is retrieved.
+// |out_address|: The SbSocket's local address.
 SB_EXPORT bool SbSocketGetLocalAddress(SbSocket socket,
                                        SbSocketAddress* out_address);
 
-// Reads up to |data_size| bytes from |socket| into |out_data|. Also places the
-// source address of the packet in |out_source|, if out_source is not NULL.
-// Returns the number of bytes read, or a negative number on error.
-// SbSocketGetLastError can provide the precise error encountered.
+// Reads up to |data_size| bytes from |socket| into |out_data| and places the
+// source address of the packet in |out_source| if out_source is not NULL.
+// Returns the number of bytes read, or a negative number if there is an error,
+// in which case SbSocketGetLastError can provide the precise error encountered.
 //
-// Note that this function is NOT specified to (but MAY) make a best effort to
-// read all data on all platforms, it just reads however many bytes are
-// available conveniently. Can be run in a loop until pending to make it a
-// best-effort read (but still only up to not blocking, unless you want to
-// spin).
+// Note that this function is NOT specified to make a best effort to read all
+// data on all platforms, but it MAY still do so. It is specified to read
+// however many bytes are available conveniently, meaning that it should avoid
+// blocking until there is data. It can be run in a loop until
+// SbSocketGetLastError returns |kSbSocketPending| to make it a best-effort
+// read (but still only up to not blocking, unless you want to spin).
 //
-// The primary use of |out_source| is for receiving datagram packets from
+// The primary use of |out_source| is to receive datagram packets from
 // multiple sources on a UDP server socket. TCP has two endpoints connected
 // persistently, so the address is unnecessary, but allowed.
+//
+// |socket|: The SbSocket from which data is read.
+// |out_data|: The data read from the socket.
+// |data_size|: The number of bytes to read.
+// |out_source|: The source address of the packet.
 SB_EXPORT int SbSocketReceiveFrom(SbSocket socket,
                                   char* out_data,
                                   int data_size,
                                   SbSocketAddress* out_source);
 
 // Writes up to |data_size| bytes of |data| to |destination| via
-// |socket|. Returns the number of bytes written, or a negative number on
-// error. SbSocketGetLastError can provide the precise error encountered.
-// |destination| must be NULL for TCP connections, which can only have a single
-// endpoint.
+// |socket|. Returns the number of bytes written, or a negative number if
+// there is an error, in which case |SbSocketGetLastError| can provide the
+// precise error encountered.
 //
-// Note that this function is NOT specified to (but MAY) make a best effort to
-// write all data on all platforms, it just writes however many bytes that are
-// conveniently. Can be run in a loop until pending to make it a best-effort
-// write (but still only up to not blocking, unless you want to spin).
+// Note that this function is NOT specified to make a best effort to write all
+// data on all platforms, but it MAY still do so. It is specified to write
+// however many bytes are available conveniently. It can be run in a loop
+// until SbSocketGetLastError returns |kSbSocketPending| to make it a
+// best-effort write (but still only up to not blocking, unless you want to
+// spin).
 //
-// The primary use of |destination| is to send datagram packets, which can go
-// out to multiple sources from a single UDP server socket. TCP has two
-// endpoints connected persistently, so |destination| cannot be set when sending
-// to a TCP socket -- it will cause an error.
+// |socket|: The SbSocket to use to write data.
+// |data|: The data read from the socket.
+// |data_size|: The number of bytes of |data| to write.
+// |destination|: The location to which data is written. This value must be
+//   |NULL| for TCP connections, which can only have a single endpoint.
+//
+//   The primary use of |destination| is to send datagram packets, which can
+//   go out to multiple sources from a single UDP server socket. TCP has two
+//   endpoints connected persistently, so setting |destination| when sending
+//   to a TCP socket will cause an error.
 SB_EXPORT int SbSocketSendTo(SbSocket socket,
                              const char* data,
                              int data_size,
                              const SbSocketAddress* destination);
 
-// Sets the SO_BROADCAST, or equivalent, option to |value| on |socket|. Returns
-// whether the option was actually set.
+// Sets the |SO_BROADCAST|, or equivalent, option to |value| on |socket|. The
+// return value indicates whether the option was actually set.
 //
-// This option is only meaningful for UDP sockets, and will allow the socket to
+// This option is only meaningful for UDP sockets and allows the socket to
 // send to the broadcast address.
+//
+// |socket|: The SbSocket for which the option is set.
+// |value|: The new value for the option.
 SB_EXPORT bool SbSocketSetBroadcast(SbSocket socket, bool value);
 
-// Sets the SO_REUSEADDR, or equivalent, option to |value| on |socket|. Returns
-// whether the option was actually set.
+// Sets the |SO_REUSEADDR|, or equivalent, option to |value| on |socket|.
+// The return value indicates whether the option was actually set.
 //
 // This option allows a bound address to be reused if a socket isn't actively
 // bound to it.
+//
+// |socket|: The SbSocket for which the option is set.
+// |value|: The new value for the option.
 SB_EXPORT bool SbSocketSetReuseAddress(SbSocket socket, bool value);
 
-// Sets SO_RCVBUF, or equivalent, option to |size| on |socket|.
+// Sets the |SO_RCVBUF|, or equivalent, option to |size| on |socket|. The
+// return value indicates whether the option was actually set.
+//
+// |socket|: The SbSocket for which the option is set.
+// |size|: The value for the option.
 SB_EXPORT bool SbSocketSetReceiveBufferSize(SbSocket socket, int32_t size);
 
-// Sets SO_SNDBUF, or equivalent, option to |size| on |socket|.
+// Sets the |SO_SNDBUF|, or equivalent, option to |size| on |socket|. The
+// return value indicates whether the option was actually set.
+//
+// |socket|: The SbSocket for which the option is set.
+// |size|: The value for the option.
 SB_EXPORT bool SbSocketSetSendBufferSize(SbSocket socket, int32_t size);
 
-// Sets the SO_KEEPALIVE, or equivalent, option to |value| on |socket|. If
-// |value| is true, then |period| specifies the minimum time (SbTime is always
-// in microseconds) between keep-alive packets, otherwise |period| is
-// ignored. Returns whether the option was actually set.
+// Sets the |SO_KEEPALIVE|, or equivalent, option to |value| on |socket|. The
+// return value indicates whether the option was actually set.
+//
+// |socket|: The SbSocket for which the option is set.
+// |value|: If set to |true|, then |period| specifies the minimum time
+//   (SbTime) is always in microseconds) between keep-alive packets. If
+//   set to |false|, |period| is ignored.
+// |period|: The time between keep-alive packets. This value is only relevant
+//   if |value| is |true|.
 SB_EXPORT bool SbSocketSetTcpKeepAlive(SbSocket socket,
                                        bool value,
                                        SbTime period);
 
-// Sets the TCP_NODELAY, or equivalent, option to |value| on |socket|.  Returns
-// whether the option was actually set.
+// Sets the |TCP_NODELAY|, or equivalent, option to |value| on |socket|. The
+// return value indicates whether the option was actually set.
 //
-// This disables the Nagle algorithm for reducing the number of packets sent
-// when converting from a stream to packets. Disabling Nagle will generally put
-// the data for each Send call into its own packet, but does not guarantee that
-// behavior.
+// This function disables the Nagle algorithm for reducing the number of
+// packets sent when converting from a stream to packets. Disabling Nagle
+// generally puts the data for each Send call into its own packet, but does
+// not guarantee that behavior.
+//
+// |socket|: The SbSocket for which the option is set.
+// |value|: Indicates whether the Nagle algorithm should be disabled
+//   (|value|=|true|).
 SB_EXPORT bool SbSocketSetTcpNoDelay(SbSocket socket, bool value);
 
-// Sets SO_WINSCALE, or equivalent, option to |value| on |socket|.
+// Sets the |SO_WINSCALE|, or equivalent, option to |value| on |socket|. The
+// return value indicates whether the option was actually set.
+//
+// |socket|: The SbSocket for which the option is set.
+// |value|: The value for the option.
 SB_EXPORT bool SbSocketSetTcpWindowScaling(SbSocket socket, bool value);
 
 // Joins |socket| to an IP multicast group identified by |address|. The
-// equivalent of IP_ADD_MEMBERSHIP.
+// equivalent of IP_ADD_MEMBERSHIP. The return value indicates whether the
+// socket was joined to the group successfully.
+//
+// |socket|: The SbSocket to be joined to the IP multicast group.
+// |address|: The location of the IP multicast group.
 SB_EXPORT bool SbSocketJoinMulticastGroup(SbSocket socket,
                                           const SbSocketAddress* address);
 
-// Gets the address of the local IPv4 network interface. Does not include
-// loopback (or IPv6) addresses.
+// Gets the address of the local IPv4 network interface. The return value
+// indicates whether the address was retrieved successfully.
+//
+// |out_address|: The retrieved address. The address does not include loopback
+//   (or IPv6) addresses.
 SB_EXPORT bool SbSocketGetLocalInterfaceAddress(SbSocketAddress* out_address);
 
-// Synchronously resolves |hostname| into an SbSocketResolution, filtered by
-// |filters|, which is a mask of SbSocketResolveFilter values. If no IP address
-// family filter is specified in |filters|, all address families will be
-// included, but if one is specified, only that address familiy will be
-// included. Unrecognized filter bits are ignored. Returns NULL if unable to
-// resolve |hostname|. The returned SbSocketResolution must be freed with
-// SbSocketFreeResolution.
+// Synchronously resolves |hostname| into the returned SbSocketResolution,
+// which must be freed with SbSocketFreeResolution. The function returns
+// |NULL| if it is unable to resolve |hostname|.
+//
+// |hostname|: The hostname to be resolved.
+// |filters|: A mask of SbSocketResolveFilter values used to filter the
+//   resolution. If |filters| does not specify an IP address family filter,
+//   all address families are included. However, if one IP address family filter
+//   is specified, only that address family is included. The function ignores
+//   unrecognized filter bits.
 SB_EXPORT SbSocketResolution* SbSocketResolve(const char* hostname,
                                               int filters);
 
 // Frees a resolution allocated by SbSocketResolve.
+//
+// |resolution|: The resolution to be freed.
 SB_EXPORT void SbSocketFreeResolution(SbSocketResolution* resolution);
 
 #ifdef __cplusplus
diff --git a/src/starboard/socket_waiter.h b/src/starboard/socket_waiter.h
index c964d6f..51fce0f 100644
--- a/src/starboard/socket_waiter.h
+++ b/src/starboard/socket_waiter.h
@@ -12,17 +12,19 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Allows a thread to wait on many sockets at once. The standard usage pattern
-// would be for a single I/O thread to:
-//   1. Create its own SbSocketWaiter.
-//   2. Wait on the SbSocketWaiter, indefinitely if no scheduled tasks, or timed
-//      if there are scheduled future tasks.
-//   3. While waiting, the SbSocketWaiter will call back to service ready
-//      SbSockets.
-//   4. Wake up, if signaled to do so.
-//   5. If ready to exit, go to 7.
-//   6. Add and remove SbSockets to and from the SbSocketWaiter, and go to 2.
-//   7. Destroy its SbSocketWaiter and exit.
+// Module Overview: Starboard Socket Waiter module
+//
+// Allows a thread to wait on many sockets at once. The standard
+// usage pattern would be for a single I/O thread to:
+// 1. Create its own SbSocketWaiter.
+// 2. Wait on the SbSocketWaiter, indefinitely if no scheduled tasks, or timed
+//    if there are scheduled future tasks.
+// 3. While waiting, the SbSocketWaiter will call back to service ready
+//    SbSockets.
+// 4. Wake up, if signaled to do so.
+// 5. If ready to exit, go to 7.
+// 6. Add and remove SbSockets to and from the SbSocketWaiter, and go to 2.
+// 7. Destroy its SbSocketWaiter and exit.
 //
 // If another thread wants to queue immediate or schedule future work on the I/O
 // thread, it needs to call SbSocketWaiterWakeUp() on the SbSocketWaiter after
@@ -41,7 +43,7 @@
 extern "C" {
 #endif
 
-// Private structure representing a waiter which can wait for many sockets at
+// Private structure representing a waiter that can wait for many sockets at
 // once on a single thread.
 typedef struct SbSocketWaiterPrivate SbSocketWaiterPrivate;
 
@@ -86,39 +88,50 @@
   return watcher != kSbSocketWaiterInvalid;
 }
 
-// Creates a new socket waiter for the current thread. A socket waiter should
-// have a 1-1 relationship to a thread that wants to wait for socket
-// activity. There is no reason to create multiple waiters for a single thread,
-// because the thread can only block on one waiter at a time. The results of two
-// threads waiting on the same waiter is undefined (and definitely won't work,
-// so don't do it). SbSocketWaiters are not thread-safe, except for the
-// SbSocketWaiterWakeUp() function, and don't expect to be modified
-// concurrently.
+// Creates and returns a new SbSocketWaiter for the current thread. A socket
+// waiter should have a 1:1 relationship to a thread that wants to wait for
+// socket activity. There is no reason to create multiple waiters for a single
+// thread because the thread can only block on one waiter at a time.
+
+// The results of two threads waiting on the same waiter is undefined and will
+// not work. Except for the SbSocketWaiterWakeUp() function, SbSocketWaiters
+// are not thread-safe and don't expect to be modified concurrently.
 SB_EXPORT SbSocketWaiter SbSocketWaiterCreate();
 
-// Destroys a socket waiter. This will also remove all sockets still registered
-// by way of SbSocketWaiterAdd. This function may be called on any thread, but
-// only if there is no worry of concurrent access to the waiter.
+// Destroys |waiter| and removes all sockets still registered by way of
+// SbSocketWaiterAdd. This function may be called on any thread as long as
+// there is no risk of concurrent access to the waiter.
+//
+// |waiter|: The SbSocketWaiter to be destroyed.
 SB_EXPORT bool SbSocketWaiterDestroy(SbSocketWaiter waiter);
 
 // Adds a new socket to be waited on by the |waiter| with a bitfield of
-// |interests|. When the event fires, |callback| will be called with |waiter|,
-// |socket|, and |context|, as well as a bitfield of which interests the socket
-// is actually ready for. This should only be called on the thread that
+// |interests|. This function should only be called on the thread that
 // waits on this waiter.
 //
 // If |socket| is already registered with this or another waiter, the function
-// will do nothing and return false. The client must remove the socket and then
+// does nothing and returns |false|. The client must remove the socket and then
 // add it back with the new |interests|.
 //
-// If |socket| is already ready for one or more operations set in the
+// If |socket| is already ready for one or more of the operations set in the
 // |interests| mask, then the callback will be called on the next call to
-// SbSocketWaiterWait() or SbSocketWaiterWaitTimed().
+// either SbSocketWaiterWait() or SbSocketWaiterWaitTimed().
 //
-// If |persistent| is true, then |socket| will stay registered with |waiter|
-// until SbSocketWaiterRemove() is called with |waiter| and |socket|. Otherwise,
-// |socket| will be removed after the next call to |callback|, even if not all
-// registered |interests| became ready.
+// |waiter|: An SbSocketWaiter that waits on the socket for the specified set
+//   of operations (|interests|).
+// |socket|: The SbSocket on which the waiter waits.
+// |context|:
+// |callback|: The function that is called when the event fires. The |waiter|,
+//   |socket|, |context| are all passed to the callback, along with a bitfield
+//   of |interests| that the socket is actually ready for.
+// |interests|: A bitfield that identifies operations for which the socket is
+//   waiting.
+// |persistent|: Identifies the procedure that will be followed for removing
+//   the socket:
+// - If |persistent| is |true|, then |socket| stays registered with |waiter|
+//   until SbSocketWaiterRemove() is called with |waiter| and |socket|.
+// - If |persistent| is |false|, then |socket| is removed after the next call
+//   to |callback|, even if not all registered |interests| became ready.
 SB_EXPORT bool SbSocketWaiterAdd(SbSocketWaiter waiter,
                                  SbSocket socket,
                                  void* context,
@@ -126,38 +139,52 @@
                                  int interests,
                                  bool persistent);
 
-// Removes |socket| from |waiter|, previously added with SbSocketWaiterAdd. If
-// |socket| wasn't registered with |waiter|, then this does nothing. This should
-// only be called on the thread that waits on this waiter.
+// Removes a socket, previously added with SbSocketWaiterAdd(), from a waiter.
+// This function should only be called on the thread that waits on this waiter.
+//
+// The return value indicates whether the waiter still waits on the socket.
+// If |socket| wasn't registered with |waiter|, then the function is a no-op
+// and returns |true|.
+//
+// |waiter|: The waiter from which the socket is removed.
+// |socket|: The socket to remove from the waiter.
 SB_EXPORT bool SbSocketWaiterRemove(SbSocketWaiter waiter, SbSocket socket);
 
 // Waits on all registered sockets, calling the registered callbacks if and when
 // the corresponding sockets become ready for an interested operation. This
-// version exits only after SbSocketWaiterWakeUp() is called. This should only
-// be called on the thread that waits on this waiter.
+// version exits only after SbSocketWaiterWakeUp() is called. This function
+// should only be called on the thread that waits on this waiter.
 SB_EXPORT void SbSocketWaiterWait(SbSocketWaiter waiter);
 
-// Behaves the same as SbSocketWaiterWait(), waking up when
-// SbSocketWaiterWakeUp(), but also exits on its own after at least |duration|
-// has passed, whichever comes first, returning an indicator of which one
-// happened. Note that, as with SbThreadSleep(), it may wait longer than
-// |duration|. For example if the timeout expires while a callback is being
-// fired. This should only be called on the thread that waits on this waiter.
+// Behaves similarly to SbSocketWaiterWait(), but this function also causes
+// |waiter| to exit on its own after at least |duration| has passed if
+// SbSocketWaiterWakeUp() it not called by that time.
+//
+// The return value indicates the reason that the socket waiter exited.
+// This function should only be called on the thread that waits on this waiter.
+//
+// |duration|: The minimum amount of time after which the socket waiter should
+//   exit if it is not woken up before then. As with SbThreadSleep() (see
+//   thread.h), this function may wait longer than |duration|, such as if the
+//   timeout expires while a callback is being fired.
 SB_EXPORT SbSocketWaiterResult SbSocketWaiterWaitTimed(SbSocketWaiter waiter,
                                                        SbTime duration);
 
-// Wakes up |waiter| once. Can be called from a SbSocketWaiterCallback to wake
-// up its own waiter. Can also be called from another thread at any time, it's
-// the only thread-safe waiter function. In either case, the waiter will exit
-// the next wait gracefully, first completing any in-progress callback.
+// Wakes up |waiter| once. This is the only thread-safe waiter function.
+// It can can be called from a SbSocketWaiterCallback to wake up its own waiter,
+// and it can also be called from another thread at any time. In either case,
+// the waiter will exit the next wait gracefully, first completing any
+// in-progress callback.
 //
-// For every time this function is called, it will cause the waiter to wake up
-// one time. This is true whether the waiter is currently waiting or not. If not
-// waiting, it will just take affect immediately the next time the waiter
-// waits. The number of wake-ups accumulate and are only consumed by waiting and
-// getting woken up. e.g. If you call this function 7 times, then
-// SbSocketWaiterWait() and WaitTimed() will not block the next 7 times they are
-// called.
+// Each time this function is called, it causes the waiter to wake up once,
+// regardless of whether the waiter is currently waiting. If the waiter is not
+// waiting, the function takes effect immediately the next time the waiter
+// waits. The number of wake-ups accumulates, and the queue is only consumed
+// as the waiter waits and then is subsequently woken up again. For example,
+// if you call this function 7 times, then SbSocketWaiterWait() and WaitTimed()
+// will not block the next 7 times they are called.
+//
+// |waiter|: The socket waiter to be woken up.
 SB_EXPORT void SbSocketWaiterWakeUp(SbSocketWaiter waiter);
 
 #ifdef __cplusplus
diff --git a/src/starboard/speech_synthesis.h b/src/starboard/speech_synthesis.h
new file mode 100644
index 0000000..2852920
--- /dev/null
+++ b/src/starboard/speech_synthesis.h
@@ -0,0 +1,65 @@
+// 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.
+
+// Module Overview: Starboard Speech Synthesis API
+//
+// A basic text-to-speech API intended to be used for audio accessibilty.
+//
+// Implementations of this API should audibly play back text to assist
+// users in non-visual navigation of the application.
+//
+// Note that these functions do not have to be thread-safe. They must
+// only be called from a single application thread.
+
+#ifndef STARBOARD_SPEECH_SYNTHESIS_H_
+#define STARBOARD_SPEECH_SYNTHESIS_H_
+
+#include "starboard/configuration.h"
+#include "starboard/export.h"
+#include "starboard/types.h"
+
+#if SB_HAS(SPEECH_SYNTHESIS) && SB_VERSION(3)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Sets a language for speech synthesis.
+//
+// Must be called before any other function in this module,
+// or subsequent calls are allowed to fail silently.
+//
+// |lang| should be a BCP 47 language string, eg "en-US".
+// Return true if language is supported, false if not.
+SB_EXPORT bool SbSpeechSynthesisSetLanguage(const char* lang);
+
+// Enqueues |text|, a UTF-8 string, to be spoken the currently
+// selected language. Returns immediately.
+//
+// If audio from previous SbSpeechSynthesisSpeak() invocations is still
+// processing, the current speaking should continue and this new
+// text should be queued to play when the previous utterances are complete.
+SB_EXPORT void SbSpeechSynthesisSpeak(const char* text);
+
+// Cancels all speaking and queued speech synthesis audio. Must
+// return immediately.
+SB_EXPORT void SbSpeechSynthesisCancel();
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // SB_HAS(SPEECH_SYNTHESIS) && SB_VERSION(3)
+
+#endif  // STARBOARD_SPEECH_SYNTHESIS_H_
diff --git a/src/starboard/spin_lock.h b/src/starboard/spin_lock.h
index 60c9843..bdc4cdb 100644
--- a/src/starboard/spin_lock.h
+++ b/src/starboard/spin_lock.h
@@ -12,8 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// A C++-only spin-lock implementation, built entirely on top of
-// Starboard atomics and threads. Can be safely used by both clients and
+// Module Overview: Starboard Spin Lock module
+//
+// Defines a C++-only spin-lock implementation, built entirely on top of
+// Starboard atomics and threads. It can be safely used by both clients and
 // implementations.
 
 #ifndef STARBOARD_SPIN_LOCK_H_
diff --git a/src/starboard/starboard_base_target.gypi b/src/starboard/starboard_base_target.gypi
index 3137a1b..dd66b79 100644
--- a/src/starboard/starboard_base_target.gypi
+++ b/src/starboard/starboard_base_target.gypi
@@ -36,6 +36,11 @@
         'SB_ABORT_ON_ALLOCATION_FAILURE',
       ],
     }],
+    ['sb_allows_memory_tracking==1', {
+      'defines': [
+        'STARBOARD_ALLOWS_MEMORY_TRACKING',
+      ],
+    }],
     ['starboard_path == ""', {
       'defines': [
         # There doesn't appear to be any way to use the C preprocessor to do
diff --git a/src/starboard/storage.h b/src/starboard/storage.h
index c90c438..37ccc10 100644
--- a/src/starboard/storage.h
+++ b/src/starboard/storage.h
@@ -12,14 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// User-based Storage API. This is a simple all-at-once BLOB storage and
-// retrieval API that is intended for robust long-term, per-user storage. Some
-// platforms have different mechanisms for this kind of storage, so this API
-// exists to allow a client application to access this kind of storage.
-
-// Only a single open record can exist for each user. Attempting to open a
+// Module Overview: Starboard Storage module
+//
+// Defines a user-based Storage API. This is a simple, all-at-once BLOB storage
+// and retrieval API that is intended for robust long-term, per-user storage.
+// Some platforms have different mechanisms for this kind of storage, so this
+// API exists to allow a client application to access this kind of storage.
+//
+// Note that there can be only one storage record per user and, thus, a maximum
+// of one open storage record can exist for each user. Attempting to open a
 // second record for a user will result in undefined behavior.
-
+//
 // These APIs are NOT expected to be thread-safe, so either call them from a
 // single thread, or perform proper synchronization around all calls.
 
@@ -48,42 +51,67 @@
   return record != kSbStorageInvalidRecord;
 }
 
-// Opens the storage record for |user|, providing a handle to the opened
-// record. |user| must be a valid SbUser, or kSbStorageInvalidRecord will be
-// returned. Performs blocking I/O on the calling thread.
+// Opens and returns a SbStorageRecord for |user|, blocking I/O on the calling
+// thread until it returns. If |user| is not a valid |SbUser|, the function
+// returns |kSbStorageInvalidRecord|.
+//
+// |user|: The user for which the storage record is opened.
 SB_EXPORT SbStorageRecord SbStorageOpenRecord(SbUser user);
 
-// Closes |record|, synchronously ensuring all written data is flushed, and
-// returning whether the operation was successful. Storage writes should be as
-// atomic as possible, so either the record should be fully written, or it
-// should delete the record (or, even better, leave it untouched). |record| will
-// be invalidated after this point, and subsequent calls to |record| will
-// fail. Performs blocking I/O on the calling thread.
+// Closes |record|, synchronously ensuring that all written data is flushed.
+// This function performs blocking I/O on the calling thread.
+//
+// The return value indicates whether the operation succeeded. Storage writes
+// should be as atomic as possible, so the record should either be fully
+// written or deleted (or, even better, untouched).
+//
+// |record|: The storage record to close. |record| is invalid after this point,
+// and subsequent calls referring to |record| will fail.
 SB_EXPORT bool SbStorageCloseRecord(SbStorageRecord record);
 
-// Returns the size of |record|, or -1 on error. Performs blocking I/O on the
-// calling thread.
+// Returns the size of |record|, or |-1| if there is an error. This function
+// performs blocking I/O on the calling thread.
+//
+// |record|: The record to retrieve the size of.
 SB_EXPORT int64_t SbStorageGetRecordSize(SbStorageRecord record);
 
-// Reads up to |data_size| bytes from |record| into |out_data|, starting at the
-// beginning of the record. Returns the number of actual bytes read, which must
-// be <= |size|, or -1 on error. This function makes a best-effort and performs
-// blocking I/O on the calling thread.
+// Reads up to |data_size| bytes from |record|, starting at the beginning of
+// the record. The function returns the actual number of bytes read, which
+// must be <= |data_size|. The function returns |-1| in the event of an error.
+// This function makes a best-effort to read the entire record, and it performs
+// blocking I/O on the calling thread until the entire record is read or an
+// error is encountered.
+//
+// |record|: The record to be read.
+// |out_data|: The data read from the record.
+// |data_size|: The amount of data, in bytes, to read.
 SB_EXPORT int64_t SbStorageReadRecord(SbStorageRecord record,
                                       char* out_data,
                                       int64_t data_size);
 
-// Replaces the data in |record| with |size| bytes from |data|. This always
-// deletes any previous data in that record. Returns whether the write
-// succeeded. This function makes a best-effort and performs blocking I/O on the
-// calling thread.
+// Replaces the data in |record| with |data_size| bytes from |data|. This
+// function always deletes any previous data in that record. The return value
+// indicates whether the write succeeded. This function makes a best-effort
+// to read the entire record, and it performs performs blocking I/O on the
+// calling thread until the entire record is read or an error is encountered.
+//
+// |record|: The record to be written to.
+// |data|: The data to write to the record.
+// |data_size|: The amount of |data|, in bytes, to write to the record. Thus,
+//   if |data_size| is smaller than the total size of |data|, only part of
+//   |data| is written to the record.
 SB_EXPORT bool SbStorageWriteRecord(SbStorageRecord record,
                                     const char* data,
                                     int64_t data_size);
 
-// Deletes |user|'s storage record, returning whether the record both existed
-// and was successfully deleted. This must not be called while |user|'s storage
-// record is open. This function performs blocking I/O on the calling thread.
+// Deletes the |SbStorageRecord| for the specified user. The return value
+// indicates whether the record existed and was successfully deleted. If the
+// record did not exist or could not be deleted, the function returns |false|.
+//
+// This function must not be called while the user's storage record is open.
+// This function performs blocking I/O on the calling thread.
+//
+// |user|: The user for whom the record is deleted.
 SB_EXPORT bool SbStorageDeleteRecord(SbUser user);
 
 #ifdef __cplusplus
diff --git a/src/starboard/string.h b/src/starboard/string.h
index 5782023..430c6b6 100644
--- a/src/starboard/string.h
+++ b/src/starboard/string.h
@@ -12,7 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Functions for interacting with c-style strings.
+// Module Overview: Starboard String module
+//
+// Defines functions for interacting with c-style strings.
 
 #ifndef STARBOARD_STRING_H_
 #define STARBOARD_STRING_H_
@@ -27,103 +29,171 @@
 extern "C" {
 #endif
 
-// Returns the length, in characters, of |str|, a zero-terminated ASCII string.
+// Returns the length, in characters, of |str|.
+//
+// |str|: A zero-terminated ASCII string.
 SB_EXPORT size_t SbStringGetLength(const char* str);
 
-// Same as SbStringGetLength but for wide characters. This assumes that there
-// are no multi-element characters.
+// Returns the length of a wide character string. (This function is the same
+// as SbStringGetLength, but for a string comprised of wide characters.) This
+// function assumes that there are no multi-element characters.
+//
+// |str|: A zero-terminated ASCII string.
 SB_EXPORT size_t SbStringGetLengthWide(const wchar_t* str);
 
-// Copies as much |source| as possible into |out_destination| and
-// null-terminates it, given that it has |destination_size| characters of
-// storage available.  Returns the length of |source|.  Meant to be a drop-in
-// replacement for strlcpy
+// Copies as much of a |source| string as possible and null-terminates it,
+// given that |destination_size| characters of storage are available. This
+// function is meant to be a drop-in replacement for |strlcpy|.
+//
+// The return value specifies the length of |source|.
+//
+// |out_destination|: The location to which the string is copied.
+// |source|: The string to be copied.
+// |destination_size|: The amount of the source string to copy.
 SB_EXPORT int SbStringCopy(char* out_destination,
                            const char* source,
                            int destination_size);
 
-// Inline wrapper for an unsafe SbStringCopy that assumes |out_destination| is
-// big enough. Meant to be a drop-in replacement for strcpy.
+// An inline wrapper for an unsafe SbStringCopy that assumes that the
+// destination provides enough storage space for the entire string. The return
+// value is a pointer to the destination string. This function is meant to be
+// a drop-in replacement for |strcpy|.
+//
+// |out_destination|: The location to which the string is copied.
+// |source|: The string to be copied.
 static SB_C_INLINE char* SbStringCopyUnsafe(char* out_destination,
                                             const char* source) {
   SbStringCopy(out_destination, source, INT_MAX);
   return out_destination;
 }
 
-// Same as SbStringCopy but for wide characters.
+// Identical to SbStringCopy, but for wide characters.
+//
+// |out_destination|: The location to which the string is copied.
+// |source|: The string to be copied.
+// |destination_size|: The amount of the source string to copy.
 SB_EXPORT int SbStringCopyWide(wchar_t* out_destination,
                                const wchar_t* source,
                                int destination_size);
 
-// Concatenates |source| onto the end of |out_destination|, presuming it has
-// |destination_size| total characters of storage available. Returns
-// length of |source|. Meant to be a drop-in replacement for strlcpy
-// Note: This function's signature is NOT compatible with strncat
+// Appends |source| to |out_destination| as long as |out_destination| has
+// enough storage space to hold the concatenated string.
+//
+// This function is meant to be a drop-in replacement for |strlcat|. Also note
+// that this function's signature is NOT compatible with |strncat|.
+//
+// |out_destination|: The string to which the |source| string is appended.
+// |source|: The string to be appended to the destination string.
+// |destination_size|: The amount of storage space available for the
+//   concatenated string.
 SB_EXPORT int SbStringConcat(char* out_destination,
                              const char* source,
                              int destination_size);
 
-// Inline wrapper for an unsafe SbStringConcat that assumes |out_destination| is
-// big enough.
-// Note: This function's signature is NOT compatible with strcat.
+// An inline wrapper for an unsafe SbStringConcat that assumes that the
+// |out_destination| provides enough storage space for the concatenated string.
+// Note that this function's signature is NOT compatible with |strcat|.
+//
+// |out_destination|: The string to which the |source| string is appended.
+// |source|: The string to be appended to the destination string.
 static SB_C_INLINE int SbStringConcatUnsafe(char* out_destination,
                                             const char* source) {
   return SbStringConcat(out_destination, source, INT_MAX);
 }
 
-// Same as SbStringConcat but for wide characters.
+// Identical to SbStringCat, but for wide characters.
+//
+// |out_destination|: The string to which the |source| string is appended.
+// |source|: The string to be appended to the destination string.
+// |destination_size|: The amount of storage space available for the
+//   concatenated string.
 SB_EXPORT int SbStringConcatWide(wchar_t* out_destination,
                                  const wchar_t* source,
                                  int destination_size);
 
-// Copies the string |source| into a buffer allocated by this function that can
-// be freed with SbMemoryDeallocate. Meant to be a drop-in replacement for
-// strdup.
+// Copies |source| into a buffer that is allocated by this function and that
+// can be freed with SbMemoryDeallocate. This function is meant to be a drop-in
+// replacement for |strdup|.
+//
+// |source|: The string to be copied.
 SB_EXPORT char* SbStringDuplicate(const char* source);
 
-// Finds the first occurrence of |character| in |str|, returning a pointer to
-// the found character in the given string, or NULL if not found.
-// NOTE: The function signature of this function does NOT match the function
-// strchr.
+// Finds the first occurrence of a |character| in |str|. The return value is a
+// pointer to the found character in the given string or |NULL| if the
+// character is not found. Note that this function's signature does NOT match
+// that of the |strchr| function.
+//
+// |str|: The string to search for the character.
+// |character|: The character to find in the string.
 SB_EXPORT const char* SbStringFindCharacter(const char* str, char character);
 
-// Finds the last occurrence of |character| in |str|, returning a pointer to the
-// found character in the given string, or NULL if not found.
-// NOTE: The function signature of this function does NOT match the function
-// strrchr.
+// Finds the last occurrence of a specified character in a string.
+// The return value is a pointer to the found character in the given string or
+// |NULL| if the character is not found. Note that this function's signature
+// does NOT match that of the |strrchr| function.
+//
+// |str|: The string to search for the character.
+// |character|: The character to find in the string.
 SB_EXPORT const char* SbStringFindLastCharacter(const char* str,
                                                 char character);
 
-// Finds the first occurrence of |str2| in |str1|, returning a pointer to the
-// beginning of the found occurrencein |str1|, or NULL if not found.  Meant to
-// be a drop-in replacement for strstr.
+// Finds the first occurrence of |str2| in |str1|. The return value is a
+// pointer to the beginning of the found string or |NULL| if the string is
+// not found. This function is meant to be a drop-in replacement for |strstr|.
+//
+// |str1|: The string in which to search for the presence of |str2|.
+// |str2|: The string to locate in |str1|.
 SB_EXPORT const char* SbStringFindString(const char* str1, const char* str2);
 
-// Compares |string1| and |string2|, ignoring differences in case. Returns < 0
-// if |string1| is ASCII-betically lower than |string2|, 0 if they are equal,
-// and > 0 if |string1| is ASCII-betically higher than |string2|. Meant to be a
-// drop-in replacement for strcasecmp.
+// Compares two strings, ignoring differences in case. The return value is:
+// - |< 0| if |string1| is ASCII-betically lower than |string2|.
+// - |0| if the two strings are equal.
+// - |> 0| if |string1| is ASCII-betically higher than |string2|.
+//
+// This function is meant to be a drop-in replacement for |strcasecmp|.
+//
+// |string1|: The first string to compare.
+// |string2|: The second string to compare.
 SB_EXPORT int SbStringCompareNoCase(const char* string1, const char* string2);
 
-// Compares the first |count| characters of |string1| and |string2|, ignoring
-// differences in case. Returns < 0 if |string1| is ASCII-betically lower than
-// |string2|, 0 if they are equal, and > 0 if |string1| is ASCII-betically
-// higher than |string2|. Meant to be a drop-in replacement for strncasecmp.
+// Compares the first |count| characters of two strings, ignoring differences
+// in case. The return value is:
+// - |< 0| if |string1| is ASCII-betically lower than |string2|.
+// - |0| if the two strings are equal.
+// - |> 0| if |string1| is ASCII-betically higher than |string2|.
+//
+// This function is meant to be a drop-in replacement for |strncasecmp|.
+//
+// |string1|: The first string to compare.
+// |string2|: The second string to compare.
+// |count|: The number of characters to compare.
 SB_EXPORT int SbStringCompareNoCaseN(const char* string1,
                                      const char* string2,
                                      size_t count);
 
-// Formats the given |format| and |arguments|, placing as much of the result
-// will fit in |out_buffer|, whose size is specified by |buffer_size|. Returns
-// the number of characters the format would produce if |buffer_size| was
-// infinite. Meant to be a drop-in replacement for vsnprintf.
+// Produces a string formatted with |format| and |arguments|, placing as much
+// of the result that will fit into |out_buffer|. The return value specifies
+// the number of characters that the format would produce if |buffer_size| were
+// infinite.
+//
+// This function is meant to be a drop-in replacement for |vsnprintf|.
+//
+// |out_buffer|: The location where the formatted string is stored.
+// |buffer_size|: The size of |out_buffer|.
+// |format|: A string that specifies how the data should be formatted.
+// |arguments|: Variable arguments used in the string.
 SB_EXPORT int SbStringFormat(char* out_buffer,
                              size_t buffer_size,
                              const char* format,
                              va_list arguments) SB_PRINTF_FORMAT(3, 0);
 
-// Inline wrapper of SbStringFormat to convert from ellipsis to va_args.
-// Meant to be a drop-in replacement for snprintf.
+// An inline wrapper of SbStringFormat that converts from ellipsis to va_args.
+// This function is meant to be a drop-in replacement for |snprintf|.
+//
+// |out_buffer|: The location where the formatted string is stored.
+// |buffer_size|: The size of |out_buffer|.
+// |format|: A string that specifies how the data should be formatted.
+// |...|: Arguments used in the string.
 static SB_C_INLINE int SbStringFormatF(char* out_buffer,
                                        size_t buffer_size,
                                        const char* format,
@@ -139,8 +209,12 @@
   return result;
 }
 
-// Inline wrapper of SbStringFormat to be a drop-in replacement for the unsafe
-// but commonly used sprintf.
+// An inline wrapper of SbStringFormat that is meant to be a drop-in
+// replacement for the unsafe but commonly used |sprintf|.
+//
+// |out_buffer|: The location where the formatted string is stored.
+// |format|: A string that specifies how the data should be formatted.
+// |...|: Arguments used in the string.
 static SB_C_INLINE int SbStringFormatUnsafeF(char* out_buffer,
                                              const char* format,
                                              ...) SB_PRINTF_FORMAT(2, 3);
@@ -154,14 +228,25 @@
   return result;
 }
 
-// Same as SbStringFormat, but for wide characters. Meant to be a drop-in
-// replacement for vswprintf.
+// This function is identical to SbStringFormat, but is for wide characters.
+// It is meant to be a drop-in replacement for |vswprintf|.
+//
+// |out_buffer|: The location where the formatted string is stored.
+// |buffer_size|: The size of |out_buffer|.
+// |format|: A string that specifies how the data should be formatted.
+// |arguments|: Variable arguments used in the string.
 SB_EXPORT int SbStringFormatWide(wchar_t* out_buffer,
                                  size_t buffer_size,
                                  const wchar_t* format,
                                  va_list arguments);
 
-// Inline wrapper of SbStringFormatWide to convert from ellipsis to va_args.
+// An inline wrapper of SbStringFormatWide that converts from ellipsis to
+// |va_args|.
+//
+// |out_buffer|: The location where the formatted string is stored.
+// |buffer_size|: The size of |out_buffer|.
+// |format|: A string that specifies how the data should be formatted.
+// |...|: Arguments used in the string.
 static SB_C_INLINE int SbStringFormatWideF(wchar_t* out_buffer,
                                            size_t buffer_size,
                                            const wchar_t* format,
@@ -173,38 +258,65 @@
   return result;
 }
 
-// Compares the first |count| characters of |string1| and |string2|, which are
-// 16-bit character strings. Returns < 0 if |string1| is ASCII-betically lower
-// than |string2|, 0 if they are equal, and > 0 if |string1| is ASCII-betically
-// higher than |string2|. Meant to be a drop-in replacement of wcsncmp.
+// Compares the first |count| characters of two 16-bit character strings.
+// The return value is:
+// - |< 0| if |string1| is ASCII-betically lower than |string2|.
+// - |0| if the two strings are equal.
+// - |> 0| if |string1| is ASCII-betically higher than |string2|.
+//
+// This function is meant to be a drop-in replacement for |wcsncmp|.
+//
+// |string1|: The first 16-bit character string to compare.weird
+// |string2|: The second 16-bit character string to compare.
+// |count|: The number of characters to compare.
 SB_EXPORT int SbStringCompareWide(const wchar_t* string1,
                                   const wchar_t* string2,
                                   size_t count);
 
-// Compares the first |count| characters of |string1| and |string2|, which are
-// 8-bit character strings. Returns < 0 if |string1| is ASCII-betically lower
-// than |string2|, 0 if they are equal, and > 0 if |string1| is ASCII-betically
-// higher than |string2|. Meant to be a drop-in replacement of strncmp.
+// Compares the first |count| characters of two 8-bit character strings.
+// The return value is:
+// - |< 0| if |string1| is ASCII-betically lower than |string2|.
+// - |0| if the two strings are equal.
+// - |> 0| if |string1| is ASCII-betically higher than |string2|.
+//
+// This function is meant to be a drop-in replacement for |strncmp|.
+//
+// |string1|: The first 8-bit character string to compare.
+// |string2|: The second 8-bit character string to compare.
+// |count|: The number of characters to compare.
 SB_EXPORT int SbStringCompare(const char* string1,
                               const char* string2,
                               size_t count);
 
-// Compares all the characters of |string1| and |string2|, which are 8-bit
-// character strings, up to their natural termination. Returns < 0 if |string1|
-// is ASCII-betically lower than |string2|, 0 if they are equal, and > 0 if
-// |string1| is ASCII-betically higher than |string2|. Meant to be a drop-in
-// replacement of strcmp.
+// Compares two entire 8-bit character strings. The return value is:
+// - |< 0| if |string1| is ASCII-betically lower than |string2|.
+// - |0| if the two strings are equal.
+// - |> 0| if |string1| is ASCII-betically higher than |string2|.
+//
+// This function is meant to be a drop-in replacement for |strcmp|.
+//
+// |string1|: The first 8-bit character string to compare.
+// |string2|: The second 8-bit character string to compare.
 SB_EXPORT int SbStringCompareAll(const char* string1, const char* string2);
 
 // Scans |buffer| for |pattern|, placing the extracted values in |arguments|.
-// Returns the number of successfully matched items, which may be zero. Meant to
-// be a drop-in replacement for vsscanf.
+// The return value specifies the number of successfully matched items, which
+// may be |0|.
+//
+// This function is meant to be a drop-in replacement for |vsscanf|.
+//
+// |buffer|: The string to scan for the pattern.
+// |pattern|: The string to search for in |buffer|.
+// |arguments|: Values matching |pattern| that were extracted from |buffer|.
 SB_EXPORT int SbStringScan(const char* buffer,
                            const char* pattern,
                            va_list arguments);
 
-// Inline wrapper of SbStringScan to convert from ellipsis to va_args. Meant to
-// be a drop-in replacement for sscanf.
+// An inline wrapper of SbStringScan that converts from ellipsis to |va_args|.
+// This function is meant to be a drop-in replacement for |sscanf|.
+// |buffer|: The string to scan for the pattern.
+// |pattern|: The string to search for in |buffer|.
+// |...|: Values matching |pattern| that were extracted from |buffer|.
 static SB_C_INLINE int SbStringScanF(const char* buffer,
                                      const char* pattern,
                                      ...) {
@@ -215,49 +327,77 @@
   return result;
 }
 
-// Parses a string at the beginning of |start| into a signed integer in the
-// given |base|.  It will place the pointer to the end of the consumed portion
-// of the string in |out_end|, if it is provided. Meant to be a drop-in
-// replacement for strtol.
+// Extracts a string that represents an integer from the beginning of |start|
+// into a signed integer in the given |base|. This function is meant to be a
+// drop-in replacement for |strtol|.
+//
+// |start|: The string that begins with the number to be converted.
+// |out_end|: If provided, the function places a pointer to the end of the
+//   consumed portion of the string into |out_end|.
+// |base|: The base into which the number will be converted. The value must
+//   be between |2| and |36|, inclusive.
 // NOLINTNEXTLINE(runtime/int)
 SB_EXPORT long SbStringParseSignedInteger(const char* start,
                                           char** out_end,
                                           int base);
 
-// Shorthand replacement for atoi. Parses |value| into a base-10 int.
+// Parses a string into a base-10 integer. This is a shorthand replacement for
+// |atoi|.
+//
+// |value|: The string to be converted.
 static SB_C_INLINE int SbStringAToI(const char* value) {
   // NOLINTNEXTLINE(readability/casting)
   return (int)SbStringParseSignedInteger(value, NULL, 10);
 }
 
-// Shorthand replacement for atol. Parses |value| into a base-10 int.
+// Parses a string into a base-10, long integer. This is a shorthand
+// replacement for |atol|.
+//
+// |value|: The string to be converted.
 // NOLINTNEXTLINE(runtime/int)
 static SB_C_INLINE long SbStringAToL(const char* value) {
   // NOLINTNEXTLINE(readability/casting)
   return SbStringParseSignedInteger(value, NULL, 10);
 }
 
-// Parses a string at the beginning of |start| into a unsigned integer in the
-// given |base|.  It will place the pointer to the end of the consumed portion
-// of the string in |out_end|, if it is provided. Meant to be a drop-in
-// replacement for strtoul.
+// Extracts a string that represents an integer from the beginning of |start|
+// into an unsigned integer in the given |base|.
+// This function is meant to be a drop-in replacement for |strtoul|.
+//
+// |start|: The string that begins with the number to be converted.
+// |out_end|: If provided, the function places a pointer to the end of the
+//   consumed portion of the string into |out_end|.
+// |base|: The base into which the number will be converted. The value must
+//   be between |2| and |36|, inclusive.
 // NOLINTNEXTLINE(runtime/int)
 SB_EXPORT unsigned long SbStringParseUnsignedInteger(const char* start,
                                                      char** out_end,
                                                      int base);
 
-// Parses a string at the beginning of |start| into a unsigned 64-bit integer in
-// the given |base|.  It will place the pointer to the end of the consumed
-// portion of the string in |out_end|, if it is provided. Meant to be a drop-in
-// replacement for strtoull, but explicity declared to return uint64_t.
+// Extracts a string that represents an integer from the beginning of |start|
+// into an unsigned 64-bit integer in the given |base|.
+//
+// This function is meant to be a drop-in replacement for |strtoull|, except
+// that it is explicitly declared to return |uint64_t|.
+//
+// |start|: The string that begins with the number to be converted.
+// |out_end|: If provided, the function places a pointer to the end of the
+//   consumed portion of the string into |out_end|.
+// |base|: The base into which the number will be converted. The value must
+//   be between |2| and |36|, inclusive.
 SB_EXPORT uint64_t SbStringParseUInt64(const char* start,
                                        char** out_end,
                                        int base);
 
-// Parses a string at the beginning of |start| into a double.
-// It will place the pointer to the end of the consumed
-// portion of the string in |out_end|, if it is provided. Meant to be a drop-in
-// replacement for strtod, but explicity declared to return double.
+// Extracts a string that represents an integer from the beginning of |start|
+// into a double.
+//
+// This function is meant to be a drop-in replacement for |strtod|, except
+// that it is explicitly declared to return a double.
+//
+// |start|: The string that begins with the number to be converted.
+// |out_end|: If provided, the function places a pointer to the end of the
+//   consumed portion of the string into |out_end|.
 SB_EXPORT double SbStringParseDouble(const char* start, char** out_end);
 
 #ifdef __cplusplus
diff --git a/src/starboard/stub/configuration_public.h b/src/starboard/stub/configuration_public.h
index 75b5256..036175e 100644
--- a/src/starboard/stub/configuration_public.h
+++ b/src/starboard/stub/configuration_public.h
@@ -128,6 +128,9 @@
 // Whether the current platform has microphone supported.
 #define SB_HAS_MICROPHONE 1
 
+// Whether the current platform has speech synthesis.
+#define SB_HAS_SPEECH_SYNTHESIS 1
+
 // Type detection for wchar_t.
 #if defined(__WCHAR_MAX__) && \
     (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff)
@@ -456,6 +459,12 @@
 // The maximum number of users that can be signed in at the same time.
 #define SB_USER_MAX_SIGNED_IN 1
 
+// --- Timing API ------------------------------------------------------------
+
+// Whether this platform has an API to retrieve how long the current thread
+// has spent in the executing state.
+#define SB_HAS_TIME_THREAD_NOW 1
+
 // --- Platform Specific Audits ----------------------------------------------
 
 #if !defined(__GNUC__)
diff --git a/src/starboard/stub/starboard_platform.gyp b/src/starboard/stub/starboard_platform.gyp
index bfacb36..438e4df 100644
--- a/src/starboard/stub/starboard_platform.gyp
+++ b/src/starboard/stub/starboard_platform.gyp
@@ -102,7 +102,6 @@
         '<(DEPTH)/starboard/shared/stub/microphone_create.cc',
         '<(DEPTH)/starboard/shared/stub/microphone_destroy.cc',
         '<(DEPTH)/starboard/shared/stub/microphone_get_available.cc',
-        '<(DEPTH)/starboard/shared/stub/microphone_get_speech_api_key.cc',
         '<(DEPTH)/starboard/shared/stub/microphone_is_sample_rate_supported.cc',
         '<(DEPTH)/starboard/shared/stub/microphone_open.cc',
         '<(DEPTH)/starboard/shared/stub/microphone_read.cc',
@@ -152,6 +151,9 @@
         '<(DEPTH)/starboard/shared/stub/socket_waiter_wait.cc',
         '<(DEPTH)/starboard/shared/stub/socket_waiter_wait_timed.cc',
         '<(DEPTH)/starboard/shared/stub/socket_waiter_wake_up.cc',
+        '<(DEPTH)/starboard/shared/stub/speech_synthesis_cancel.cc',
+        '<(DEPTH)/starboard/shared/stub/speech_synthesis_set_language.cc',
+        '<(DEPTH)/starboard/shared/stub/speech_synthesis_speak.cc',
         '<(DEPTH)/starboard/shared/stub/storage_close_record.cc',
         '<(DEPTH)/starboard/shared/stub/storage_delete_record.cc',
         '<(DEPTH)/starboard/shared/stub/storage_get_record_size.cc',
@@ -222,6 +224,7 @@
         '<(DEPTH)/starboard/shared/stub/thread_types_public.h',
         '<(DEPTH)/starboard/shared/stub/thread_yield.cc',
         '<(DEPTH)/starboard/shared/stub/time_get_monotonic_now.cc',
+        '<(DEPTH)/starboard/shared/stub/time_get_monotonic_thread_now.cc',
         '<(DEPTH)/starboard/shared/stub/time_get_now.cc',
         '<(DEPTH)/starboard/shared/stub/time_zone_get_current.cc',
         '<(DEPTH)/starboard/shared/stub/time_zone_get_dst_name.cc',
diff --git a/src/starboard/system.h b/src/starboard/system.h
index c52a4e1..2d5a1a2 100644
--- a/src/starboard/system.h
+++ b/src/starboard/system.h
@@ -12,8 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// A broad set of APIs that allow the client application to query build and
-// runtime properties of the enclosing system.
+// Module Overview: Starboard System module
+//
+// Defines a broad set of APIs that allow the client application to query
+// build and runtime properties of the enclosing system.
 
 #ifndef STARBOARD_SYSTEM_H_
 #define STARBOARD_SYSTEM_H_
@@ -94,6 +96,14 @@
 
   // A universally-unique ID for the current user.
   kSbSystemPropertyPlatformUuid,
+
+#if SB_VERSION(2)
+  // The Google Speech API key. The platform manufacturer is responsible
+  // for registering a Google Speech API key for their products. In the API
+  // Console (http://developers.google.com/console), you can enable the
+  // Speech APIs and generate a Speech API key.
+  kSbSystemPropertySpeechApiKey,
+#endif  // SB_VERSION(2)
 } SbSystemPropertyId;
 
 // Enumeration of device types.
@@ -136,9 +146,9 @@
 } SbSystemConnectionType;
 
 // Runtime capabilities are boolean properties of a platform that can't be
-// determined at compile-time, and may vary from device to device, but will not
-// change over the course of a single execution. They often specify particular
-// behavior of other APIs within the bounds of their operating range.
+// determined at compile-time. They may vary from device to device, but they
+// will not change over the course of a single execution. They often specify
+// particular behavior of other APIs within the bounds of their operating range.
 typedef enum SbSystemCapabilityId {
   // Whether this system has reversed Enter and Back keys.
   kSbSystemCapabilityReversedEnterAndBack,
@@ -196,77 +206,87 @@
   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.
+// Cobalt calls this function to notify the platform that an error has occurred
+// in the application that the platform may need to handle. The platform is
+// expected to then notify the user of the error and to provide a means for
+// any required interaction, such as 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
+// The return value is a handle that may be used in a subsequent call to
+// |SbClearPlatformError|. For example, the handle could be used to
+// programatically dismiss a dialog that was 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. Note that if the
+// platform cannot respond to the error, then this function should return
 // |kSbSystemPlatformErrorInvalid|.
+//
+// This function may be called from any thread, and it is the platform's
+// responsibility to decide how to handle an error received while a previous
+// error is still pending. If that platform can only handle one error at a
+// time, then it may queue the second error or ignore it by returning
+// |kSbSystemPlatformErrorInvalid|.
+//
+// |type|: An error type, from the SbSystemPlatformErrorType enum,
+//    that defines the error.
+// |callback|: A function that may be called by the platform to let the caller
+//   know that the user has reacted to the error.
+// |user_data|: An opaque pointer that the platform should pass as an argument
+//   to the callback function, if it is called.
 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.
+// |SbSystemRaisePlatformError|. The platform may use this, for example,
+// to close a dialog that was opened in response to the error.
+//
+// |handle|: The platform error to be cleared.
 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).
+// Pointer to a function to compare two items. The return value uses standard
+// |*cmp| semantics:
+// - |< 0| if |a| is less than |b|
+// - |0| if the two items are equal
+// - |> 1| if |a| is greater than |b|
+//
+// |a|: The first value to compare.
+// |b|: The second value to compare.
 typedef int (*SbSystemComparator)(const void* a, const void* b);
 
-// Breaks the current program into the debugger, if a debugger is
-// attached. Aborts the program otherwise.
+// Breaks the current program into the debugger, if a debugger is attached.
+// If a debugger is not attached, this function aborts the program.
 SB_EXPORT void SbSystemBreakIntoDebugger();
 
-// Attempts to determine if the current program is running inside or attached to
-// a debugger.
+// Attempts to determine whether the current program is running inside or
+// attached to a debugger. The function returns |false| if neither of those
+// cases is true.
 SB_EXPORT bool SbSystemIsDebuggerAttached();
 
 // Returns the number of processor cores available to this application. If the
-// process is sandboxed to a subset of the physical cores, it will return that
-// sandboxed limit.
+// process is sandboxed to a subset of the physical cores, the function returns
+// that sandboxed limit.
 SB_EXPORT int SbSystemGetNumberOfProcessors();
 
-// Gets the total CPU memory (in bytes) potentially available to this
-// application. If the process is sandboxed to a maximum allowable limit, it
-// will return the lesser of the physical and sandbox limits.
+// Returns the total CPU memory (in bytes) potentially available to this
+// application. If the process is sandboxed to a maximum allowable limit,
+// the function returns the lesser of the physical and sandbox limits.
 SB_EXPORT int64_t SbSystemGetTotalCPUMemory();
 
 // Returns the total physical CPU memory (in bytes) used by this application.
-// This value should always be less than (or in particularly exciting
+// This value should always be less than (or, in particularly exciting
 // situations, equal to) SbSystemGetTotalCPUMemory().
 SB_EXPORT int64_t SbSystemGetUsedCPUMemory();
 
-// Returns the total GPU memory available (in bytes) for use by this
-// application.
-// This function may only be called if true is the return value for calls to
-// SbSystemHasCapability(kSbSystemCapabilityCanQueryGPUMemoryStats).
+// Returns the total GPU memory (in bytes) available for use by this
+// application. This function may only be called the return value for calls to
+// SbSystemHasCapability(kSbSystemCapabilityCanQueryGPUMemoryStats) is |true|.
 SB_EXPORT int64_t SbSystemGetTotalGPUMemory();
 
 // Returns the current amount of GPU memory (in bytes) that is currently being
-// used by this application.
-// This function may only be called if true is the return value for calls to
-// SbSystemHasCapability(kSbSystemCapabilityCanQueryGPUMemoryStats).
+// used by this application. This function may only be called if the return
+// value for calls to
+// SbSystemHasCapability(kSbSystemCapabilityCanQueryGPUMemoryStats) is |true|.
 SB_EXPORT int64_t SbSystemGetUsedGPUMemory();
 
 // Returns the type of the device.
@@ -275,59 +295,83 @@
 // Returns the device's current network connection type.
 SB_EXPORT SbSystemConnectionType SbSystemGetConnectionType();
 
-// Gets the platform-defined system path specified by |path_id|, placing it as a
-// zero-terminated string into the user-allocated |out_path|, unless it is
-// longer than |path_length| - 1. Returns false if |path_id| is invalid for this
-// platform, or if |path_length| is too short for the given result, or if
-// |out_path| is NULL. On failure, |out_path| will not be changed.
-// Implementation must be thread-safe.
+// Retrieves the platform-defined system path specified by |path_id| and
+// places it as a zero-terminated string into the user-allocated |out_path|
+// unless it is longer than |path_length| - 1. This implementation must be
+// thread-safe.
+//
+// This function returns |true| if the path is retrieved successfully. It
+// returns |false| under any of the following conditions and, in any such
+// case, |out_path| is not changed:
+// - |path_id| is invalid for this platform
+// - |path_length| is too short for the given result
+// - |out_path| is NULL
+//
+// |path_id|: The system path to be retrieved.
+// |out_path|: The platform-defined system path specified by |path_id|.
+// |path_length|: The length of the system path.
 SB_EXPORT bool SbSystemGetPath(SbSystemPathId path_id,
                                char* out_path,
                                int path_length);
 
-// Gets the platform-defined system property specified by |property_id|, placing
-// it as a zero-terminated string into the user-allocated |out_value|, unless it
-// is longer than |value_length| - 1. Returns false if |property_id| is invalid
-// for this platform, or if |value_length| is too short for the given result, or
-// if |out_value| is NULL. On failure, |out_value| will not be changed.
-// Implementation must be thread-safe.
+// Retrieves the platform-defined system property specified by |property_id| and
+// places its value as a zero-terminated string into the user-allocated
+// |out_value| unless it is longer than |value_length| - 1. This implementation
+// must be thread-safe.
+//
+// This function returns |true| if the property is retrieved successfully. It
+// returns |false| under any of the following conditions and, in any such
+// case, |out_value| is not changed:
+// - |property_id| is invalid for this platform
+// - |value_length| is too short for the given result
+// - |out_value| is NULL
+//
+// |property_id|: The system path to be retrieved.
+// |out_value|: The platform-defined system property specified by |property_id|.
+// |value_length|: The length of the system property.
 SB_EXPORT bool SbSystemGetProperty(SbSystemPropertyId property_id,
                                    char* out_value,
                                    int value_length);
 
 // Returns whether the platform has the runtime capability specified by
-// |capability_id|. Returns false for any unknown capabilities. Implementation
-// must be thread-safe.
+// |capability_id|. Returns false for any unknown capabilities. This
+// implementation must be thread-safe.
+//
+// |capability_id|: The runtime capability to check.
 SB_EXPORT bool SbSystemHasCapability(SbSystemCapabilityId capability_id);
 
 // Gets the system's current POSIX-style Locale ID. The locale represents the
 // location, language, and cultural conventions that the system wants to use,
-// which affects which text is displayed to the user, and how display numbers,
-// dates, currency, and the like are formatted.
+// which affects which text is displayed to the user as well as how displayed
+// numbers, dates, currency, and similar values are formatted.
 //
-// At its simplest, it can just be a BCP 47 language code, like "en_US". These
-// days, POSIX also wants to include the encoding, like "en_US.UTF8". POSIX
-// additionally allows a couple very bare-bones locales, like "C" or "POSIX",
-// but they are not supported here. POSIX also supports different locale
-// settings for a few different purposes, but Starboard only exposes a single
+// At its simplest, the locale ID can just be a BCP 47 language code, like
+// |en_US|. Currently, POSIX also wants to include the encoding as in
+// |en_US.UTF8|. POSIX also allows a couple very bare-bones locales, like "C"
+// or "POSIX", but they are not supported here. POSIX also supports different
+// locale settings for a few different purposes, but Starboard only exposes one
 // locale at a time.
 //
-// RFC 5646 describing BCP 47 language codes:
+// RFC 5646 describes BCP 47 language codes:
 // https://tools.ietf.org/html/bcp47
 //
-// For more information than you want on POSIX locales:
+// For more information than you probably want about POSIX locales, see:
 // http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html
 SB_EXPORT const char* SbSystemGetLocaleId();
 
-// Gets sixty-four random bits returned as an uint64_t. This is expected to be a
-// cryptographically secure random number generator, and doesn't require manual
+// A cryptographically secure random number generator that gets 64 random bits
+// and returns them as an |uint64_t|. This function does not require manual
 // seeding.
 SB_EXPORT uint64_t SbSystemGetRandomUInt64();
 
-// Produces an arbitrary non-negative number, |buffer_size|, of random bytes
-// which must not be negative, placing the result in |out_buffer|, which must
-// not be null. This is expected to be a cryptographically secure random number
-// generator, and doesn't require manual seeding.
+// A cryptographically secure random number generator that produces an
+// arbitrary, non-negative number of |buffer_size| random, non-negative bytes.
+// The generated number is placed in |out_buffer|. This function does not
+// require manual seeding.
+//
+// |out_buffer|: A pointer for the generated random number. This value must
+//   not be null.
+// |buffer_size|: The size of the random number, in bytes.
 SB_EXPORT void SbSystemGetRandomData(void* out_buffer, int buffer_size);
 
 // Gets the last platform-specific error code produced by any Starboard call in
@@ -338,48 +382,73 @@
 // Clears the last error set by a Starboard call in the current thread.
 SB_EXPORT void SbSystemClearLastError();
 
-// Writes a human-readable string for |error|, up to |string_length| bytes, into
-// the provided |out_string|. Returns the total desired length of the string.
-// |out_string| may be null, in which case just the total desired length of the
-// string is returned. |out_string| is always terminated with a null byte.
+// Generates a human-readable string for an error. The return value specifies
+// the total desired length of the string.
+//
+// |error|: The error for which a human-readable string is generated.
+// |out_string|: The generated string. This value may be null, and it is
+//   always terminated with a null byte.
+// |string_length|: The maximum length of the error string.
 SB_EXPORT int SbSystemGetErrorString(SbSystemError error,
                                      char* out_string,
                                      int string_length);
 
 // Places up to |stack_size| instruction pointer addresses of the current
-// execution stack into |out_stack|, returning the number of entries
-// populated. |out_stack| must point to a non-NULL array of void * of at least
-// |stack_size| entries. The returned stack frames will be in "downward" order
-// from the calling frame towards the entry point of the thread. So, if all the
-// stack frames do not fit, the ones truncated will be the less interesting ones
-// towards the thread entry point. This function must be async-signal-safe on
-// platforms that support signals, as it will be used in crash signal handlers.
+// execution stack into |out_stack|. The return value specifies the number
+// of entries added.
 //
-// See the following about what it means to be async-signal-safe on POSIX:
+// The returned stack frames are in "downward" order from the calling frame
+// toward the entry point of the thread. So, if all the stack frames do not
+// fit, the ones truncated will be the less interesting ones toward the thread
+// entry point.
+//
+// This function is used in crash signal handlers and, therefore, it must
+// be async-signal-safe on platforms that support signals. The following
+// document discusses what it means to be async-signal-safe on POSIX:
 // http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html#tag_02_04_03
+//
+// |out_stack|: A non-NULL array of |void *| of at least |stack_size| entries.
+// |stack_size|: The maximum number of instruction pointer addresses to be
+//   placed into |out_stack| from the current execution stack.
 SB_EXPORT int SbSystemGetStack(void** out_stack, int stack_size);
 
-// Looks up |address| as an instruction pointer and places up to |buffer_size| -
-// 1 characters of the symbol associated with it in |out_buffer|, which must not
-// be NULL. |out_buffer| will be NULL-terminated. Returns whether it found a
-// reasonable match for |address|. If the return value is false, |out_buffer|
-// will not be modified. This function must be async-signal-safe on platforms
-// that support signals, as it will be used in crash signal handlers.
+// Looks up |address| as an instruction pointer and places up to
+// (|buffer_size - 1|) characters of the symbol associated with it in
+// |out_buffer|, which must not be NULL. |out_buffer| will be NULL-terminated.
+//
+// The return value indicates whether the function found a reasonable match
+// for |address|. If the return value is |false|, then |out_buffer| is not
+// modified.
+//
+// This function is used in crash signal handlers and, therefore, it must
+// be async-signal-safe on platforms that support signals.
 SB_EXPORT bool SbSystemSymbolize(const void* address,
                                  char* out_buffer,
                                  int buffer_size);
 
-// Requests that the application be terminated gracefully at the next convenient
-// point. Some work may continue to be done, and unrelated system events
-// dispatched, in the meantime. This will eventually result in a
-// kSbEventTypeStop event being dispatched to the application.  When the process
-// finally terminates, it will return |error_level|, if that has any meaning on
-// the current platform.
+// Requests that the application be terminated gracefully at the next
+// convenient point. In the meantime, some work may continue to be done, and
+// unrelated system events may be dispatched. This function eventually causes
+// a |kSbEventTypeStop| event to be dispatched to the application. When the
+// process finally terminates, it returns |error_level|, if that has any
+// meaning on the current platform.
+//
+// |error_level|: An integer that serves as the return value for the process
+//   that is eventually terminated as a result of a call to this function.
 SB_EXPORT void SbSystemRequestStop(int error_level);
 
 // Binary searches a sorted table |base| of |element_count| objects, each
 // element |element_width| bytes in size for an element that |comparator|
-// compares equal to |key|. Meant to be a drop-in replacement for bsearch.
+// compares equal to |key|.
+//
+// This function is meant to be a drop-in replacement for |bsearch|.
+//
+// |key|: The key to search for in the table.
+// |base|: The sorted table of elements to be searched.
+// |element_count|: The number of elements in the table.
+// |element_width|: The size, in bytes, of each element in the table.
+// |comparator|: A value that indicates how the element in the table should
+//   compare to the specified |key|.
 SB_EXPORT void* SbSystemBinarySearch(const void* key,
                                      const void* base,
                                      size_t element_count,
@@ -388,13 +457,19 @@
 
 // Sorts an array of elements |base|, with |element_count| elements of
 // |element_width| bytes each, using |comparator| as the comparison function.
-// Meant to be a drop-in replacement for qsort.
+//
+// This function is meant to be a drop-in replacement for |qsort|.
+//
+// |base|: The array of elements to be sorted.
+// |element_count|: The number of elements in the array.
+// |element_width|: The size, in bytes, of each element in the array.
+// |comparator|: A value that indicates how the array should be sorted.
 SB_EXPORT void SbSystemSort(void* base,
                             size_t element_count,
                             size_t element_width,
                             SbSystemComparator comparator);
 
-// Hides the system splash screen, on systems that support a splash screen that
+// Hides the system splash screen on systems that support a splash screen that
 // is displayed while the application is loading. This function may be called
 // from any thread and must be idempotent.
 SB_EXPORT void SbSystemHideSplashScreen();
diff --git a/src/starboard/thread.h b/src/starboard/thread.h
index 2ad1006..d2138e0 100644
--- a/src/starboard/thread.h
+++ b/src/starboard/thread.h
@@ -12,7 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Thread creation and cleanup.
+// Module Overview: Starboard Thread module
+//
+// Defines functionality related to thread creation and cleanup.
 
 #ifndef STARBOARD_THREAD_H_
 #define STARBOARD_THREAD_H_
@@ -128,22 +130,29 @@
   return key != kSbThreadLocalKeyInvalid;
 }
 
-// Creates a new thread, which starts immediately. The |stack_size| parameter
-// can be 0 to indicate that the default stack size should be used. |priority|
-// can be set to kSbThreadNoPriority to use the default priority for the
-// platform (e.g. possibly a fixed, standard priority, or possibly a priority
-// inherited from the thread that is calling SbThreadCreate()). |affinity| can
-// be set to kSbThreadNoAffinity to use the default affinity for the platform.
-// |joinable| sets whether the thread can be joined, or should start out
-// "detached." |name| is mainly used for debugging, may be NULL, and may not
-// even be used in production builds. Returns a handle to the newly created
-// thread upon success, and returns kSbThreadInvalid if not. |entry_point| will
-// be executed on the newly created thread, and passed |context|.
+// Creates a new thread, which starts immediately.
+// - If the function succeeds, the return value is a handle to the newly
+//   created thread.
+// - If the function fails, the return value is |kSbThreadInvalid|.
 //
-// NOTE: For joinable threads, when you are done with the thread handle, you
-// must call SbThreadJoin to release system resources associated with the
-// thread. This is not necessary for detached threads, but a detached thread
-// cannot be joined.
+// |stack_size|: The amount of memory reserved for the thread. Set the value
+//   to |0| to indicate that the default stack size should be used.
+// |priority|: The thread's priority. This value can be set to
+//   |kSbThreadNoPriority| to use the platform's default priority. As examples,
+//   it could be set to a fixed, standard priority or to a priority inherited
+//   from the thread that is calling SbThreadCreate(), or to something else.
+// |affinity|: The thread's affinity. This value can be set to
+//   |kSbThreadNoAffinity| to use the platform's default affinity.
+// |joinable|: Indicates whether the thread can be joined (|true|) or should
+//   start out "detached" (|false|). Note that for joinable threads, when
+//   you are done with the thread handle, you must call |SbThreadJoin| to
+//   release system resources associated with the thread. This is not necessary
+//   for detached threads, but detached threads cannot be joined.
+// |name|: A name used to identify the thread. This value is used mainly for
+//   debugging, it can be |NULL|, and it might not be used in production builds.
+// |entry_point|: A pointer to a function that will be executed on the newly
+//   created thread.
+// |context|: This value will be passed to the |entry_point| function.
 SB_EXPORT SbThread SbThreadCreate(int64_t stack_size,
                                   SbThreadPriority priority,
                                   SbThreadAffinity affinity,
@@ -152,73 +161,100 @@
                                   SbThreadEntryPoint entry_point,
                                   void* context);
 
-// Joins with joinable |thread|, created with SbThreadCreate.  This function
-// blocks the caller until the designated thread exits, and then cleans up that
-// thread's resources.  Returns true on success, false if |thread| is invalid or
-// detached. This will essentially detach |thread|. Each joinable thread must be
-// joined to be fully cleaned up. If |out_return| is not NULL, the return value
-// of the thread's main function is placed there.
+// Joins the thread on which this function is called with joinable |thread|.
+// This function blocks the caller until the designated thread exits, and then
+// cleans up that thread's resources. The cleanup process essentially detaches
+// thread.
 //
-// Each joinable thread can only be joined once. Once SbThreadJoin is called,
-// the thread behaves as if it was detached to all threads other than the
-// joining thread.
+// The return value is |true| if the function is successful and |false| if
+// |thread| is invalid or detached.
+//
+// Each joinable thread can only be joined once and must be joined to be fully
+// cleaned up. Once SbThreadJoin is called, the thread behaves as if it were
+// detached to all threads other than the joining thread.
+//
+// |thread|: The thread to which the current thread will be joined. The
+//   |thread| must have been created with SbThreadCreate.
+// |out_return|: If this is not |NULL|, then the SbThreadJoin function populates
+//   it with the return value of the thread's |main| function.
 SB_EXPORT bool SbThreadJoin(SbThread thread, void** out_return);
 
 // Detaches |thread|, which prevents it from being joined. This is sort of like
-// a non-blocking join. Does nothing if the thread is already detached, or is
-// already being joined by another thread.
+// a non-blocking join. This function is a no-op if the thread is already
+// detached or if the thread is already being joined by another thread.
+//
+// |thread|: The thread to be detached.
 SB_EXPORT void SbThreadDetach(SbThread thread);
 
 // Yields the currently executing thread, so another thread has a chance to run.
 SB_EXPORT void SbThreadYield();
 
-// Sleeps the currently executing thread for at least the given |duration| in
-// microseconds. A negative duration does nothing.
+// Sleeps the currently executing thread.
+//
+// |duration|: The minimum amount of time, in microseconds, that the currently
+//   executing thread should sleep. The function is a no-op if this value is
+//   negative or |0|.
 SB_EXPORT void SbThreadSleep(SbTime duration);
 
-// Gets the handle of the currently executing thread.
+// Returns the handle of the currently executing thread.
 SB_EXPORT SbThread SbThreadGetCurrent();
 
-// Gets the Thread ID of the currently executing thread.
+// Returns the Thread ID of the currently executing thread.
 SB_EXPORT SbThreadId SbThreadGetId();
 
-// Returns whether |thread1| and |thread2| refer to the same thread.
+// Indicates whether |thread1| and |thread2| refer to the same thread.
+//
+// |thread1|: The first thread to compare.
+// |thread2|: The second thread to compare.
 SB_EXPORT bool SbThreadIsEqual(SbThread thread1, SbThread thread2);
 
-// Gets the debug name of the currently executing thread.
+// Returns the debug name of the currently executing thread.
 SB_EXPORT void SbThreadGetName(char* buffer, int buffer_size);
 
-// Sets the debug name of the currently executing thread. Will copy the
+// Sets the debug name of the currently executing thread by copying the
 // specified name string.
+//
+// |name|: The name to assign to the thread.
 SB_EXPORT void SbThreadSetName(const char* name);
 
-// Creates a new, unique key for thread local data with given optional
-// |destructor|. |destructor| may be NULL if there is no clean up
-// needed. Returns kSbThreadLocalKeyInvalid if creation was unsuccessful.
+// Creates and returns a new, unique key for thread local data. If the function
+// does not succeed, the function returns |kSbThreadLocalKeyInvalid|.
 //
-// When does |destructor| get called? It can only be called in the owning
-// thread, and let's just say thread interruption isn't viable. The destructor,
-// if specified, is called on every thread's local values when the thread exits,
-// if and only if the value in the key is non-NULL.
+// If |destructor| is specified, it will be called in the owning thread, and
+// only in the owning thread, when the thread exits. In that case, it is called
+// on the local value associated with the key in the current thread as long as
+// the local value is not NULL.
+//
+// |destructor|: A pointer to a function. The value may be NULL if no clean up
+//   is needed.
 SB_EXPORT SbThreadLocalKey
 SbThreadCreateLocalKey(SbThreadLocalDestructor destructor);
 
-// Destroys thread local data |key|. Does nothing if key is
-// kSbThreadLocalKeyInvalid or has already been destroyed. This does NOT call
-// the destructor on any stored values.
+// Destroys thread local data for the specified key. The function is a no-op
+// if the key is invalid (kSbThreadLocalKeyInvalid|) or has already been
+// destroyed. This function does NOT call the destructor on any stored values.
+//
+// |key|: The key for which to destroy thread local data.
 SB_EXPORT void SbThreadDestroyLocalKey(SbThreadLocalKey key);
 
-// Gets the pointer-sized value for |key| in the currently executing thread's
-// local storage. Returns NULL if key is kSbThreadLocalKeyInvalid or has already
-// been destroyed.
+// Returns the pointer-sized value for |key| in the currently executing thread's
+// local storage. Returns |NULL| if key is |kSbThreadLocalKeyInvalid| or if the
+// key has already been destroyed.
+//
+// |key|: The key for which to return the value.
 SB_EXPORT void* SbThreadGetLocalValue(SbThreadLocalKey key);
 
 // Sets the pointer-sized value for |key| in the currently executing thread's
-// local storage. Returns whether |key| is valid and has not already been
-// destroyed.
+// local storage. The return value indicates whether |key| is valid and has
+// not already been destroyed.
+//
+// |key|: The key for which to set the key value.
+// |value|: The new pointer-sized key value.
 SB_EXPORT bool SbThreadSetLocalValue(SbThreadLocalKey key, void* value);
 
 // Returns whether |thread| is the current thread.
+//
+// |thread|: The thread to check.
 SB_C_INLINE bool SbThreadIsCurrent(SbThread thread) {
   return SbThreadGetCurrent() == thread;
 }
diff --git a/src/starboard/thread_types.h b/src/starboard/thread_types.h
index 36c8868..0c3c3ff 100644
--- a/src/starboard/thread_types.h
+++ b/src/starboard/thread_types.h
@@ -12,8 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+// Module Overview: Starboard Thread Types module
+//
 // Defines platform-specific threading and synchronization primitive types and
-// initializers. We hide but pass-through the platform's primitives to avoid
+// initializers. We hide, but pass through, the platform's primitives to avoid
 // doing a lot of work to replicate initialization-less synchronization
 // primitives.
 
diff --git a/src/starboard/time.h b/src/starboard/time.h
index e98a07e..bae41d4 100644
--- a/src/starboard/time.h
+++ b/src/starboard/time.h
@@ -12,7 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Access to system time and timers.
+// Module Overview: Starboard Time module
+//
+// Provides access to system time and timers.
 
 #ifndef STARBOARD_TIME_H_
 #define STARBOARD_TIME_H_
@@ -60,28 +62,44 @@
 // microseconds since the POSIX epoch.
 #define kSbTimeToPosixDelta (SB_INT64_C(-11644473600) * kSbTimeSecond)
 
-// Converts an SbTime into microseconds from the POSIX epoch.
+// Converts |SbTime| into microseconds from the POSIX epoch.
+//
+// |time|: A time that is either measured in microseconds since the epoch of
+//   January 1, 1601, UTC, or that measures the number of microseconds
+//   between two times.
 static SB_C_FORCE_INLINE int64_t SbTimeToPosix(SbTime time) {
   return time + kSbTimeToPosixDelta;
 }
 
-// Converts microseconds from the POSIX epoch into an SbTime.
+// Converts microseconds from the POSIX epoch into an |SbTime|.
+//
+// |time|: A time that measures the number of microseconds since
+//   January 1, 1970, 00:00:00, UTC.
 static SB_C_FORCE_INLINE SbTime SbTimeFromPosix(int64_t time) {
   return time - kSbTimeToPosixDelta;
 }
 
-// Safely narrows a number from a more-precise unit to a less-precise one. This
-// rounds negative values towards negative infinity.
+// Safely narrows a number from a more precise unit to a less precise one. This
+// function rounds negative values toward negative infinity.
 static SB_C_FORCE_INLINE int64_t SbTimeNarrow(int64_t time, int64_t divisor) {
   return time >= 0 ? time / divisor : (time - divisor + 1) / divisor;
 }
 
-// Gets the current system time as a SbTime.
+// Gets the current system time as an |SbTime|.
 SB_EXPORT SbTime SbTimeGetNow();
 
 // Gets a monotonically increasing time representing right now.
 SB_EXPORT SbTimeMonotonic SbTimeGetMonotonicNow();
 
+#if SB_VERSION(3) && SB_HAS(TIME_THREAD_NOW)
+// Gets a monotonically increasing time representing how long the current
+// thread has been in the executing state (i.e. not pre-empted nor waiting
+// on an event). This is not necessarily total time and is intended to allow
+// measuring thread execution time between two timestamps. If this is not
+// available then SbTimeGetMonotonicNow() should be used.
+SB_EXPORT SbTimeMonotonic SbTimeGetMonotonicThreadNow();
+#endif
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/src/starboard/types.h b/src/starboard/types.h
index 746689a..04a1263 100644
--- a/src/starboard/types.h
+++ b/src/starboard/types.h
@@ -12,8 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// A suite of standard types that should be universally available on all
-// platforms, specifically focused on explicitly-sized integer types and
+// Module Overview: Starboard Types module
+//
+// Provides a suite of standard types that should be universally available on
+// all platforms, specifically focused on explicitly-sized integer types and
 // booleans. This module also includes some related ubiquitous definitions like
 // limits of the explicitly-sized integer types, and standard pointer and int32
 // sentinel values.
diff --git a/src/starboard/user.h b/src/starboard/user.h
index 04443ee..b05d7de 100644
--- a/src/starboard/user.h
+++ b/src/starboard/user.h
@@ -12,9 +12,13 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// User management API. Platforms that do not have users must still implement
-// this API, always reporting a single user current and signed in.
-
+// Module Overview: Starboard User module
+//
+// Defines a user management API. This module defines functions only for
+// managing signed-in users. Platforms that do not have users must still
+// implement this API, always reporting a single user that is current and
+// signed in.
+//
 // These APIs are NOT expected to be thread-safe, so either call them from a
 // single thread, or perform proper synchronization around all calls.
 
@@ -81,29 +85,45 @@
   return user != kSbUserInvalid;
 }
 
-// Gets a list of up to |users_size| signed-in users, placing the results in
-// |out_users|, and returning the number of actual users signed in, whether
-// greater or less than |users_size|. It is expected that there will be a unique
-// SbUser per signed in user, and that the referenced objects will persist for
-// the lifetime of the app.
+// Gets a list of up to |users_size| signed-in users and places the results in
+// |out_users|. The return value identifies the actual number of signed-in
+// users, which may be greater or less than |users_size|.
+//
+// It is expected that there will be a unique |SbUser| per signed-in user and
+// that the referenced objects will persist for the lifetime of the app.
+//
+// |out_users|: Handles for the retrieved users.
+// |users_size|: The maximum number of signed-in users to retrieve.
 SB_EXPORT int SbUserGetSignedIn(SbUser* out_users, int users_size);
 
-// Gets the current primary user, if any. This is the user that is determined,
-// in a platform specific way, to be the primary user controlling the
-// application. This may be because that user launched the app, or using
-// whatever criteria is appropriate for the platform. It is expected that there
-// will be a unique SbUser per signed in user, and that the referenced objects
-// will persist for the lifetime of the app.
+// Gets the current primary user, if one exists. This is the user that is
+// determined, in a platform-specific way, to be the primary user controlling
+// the application. For example, the determination might be made because that
+// user launched the app, though it should be made using whatever criteria are
+// appropriate for the platform.
+//
+// It is expected that there will be a unique SbUser per signed-in user, and
+// that the referenced objects will persist for the lifetime of the app.
 SB_EXPORT SbUser SbUserGetCurrent();
 
-// Gets the size of the value of |property_id| for |user|, INCLUDING the
-// terminating null character. Returns 0 if if |user| is invalid, |property_id|
-// isn't recognized, supported, or set for |user|.
+// Returns the size of the value of |property_id| for |user|, INCLUDING the
+// terminating null character. The function returns |0| if |user| is invalid
+// or if |property_id| is not recognized, supported, or set for the user.
+//
+// |user|: The user for which property size data is being retrieved.
+// |property_id|: The property for which the data is requested.
 SB_EXPORT int SbUserGetPropertySize(SbUser user, SbUserPropertyId property_id);
 
-// Gets the value of |property_id| for |user|, and places it in |out_value|,
-// returning false if |user| is invalid, |property_id| isn't recognized,
-// supported, or set for |user|, or if |value_size| is too small.
+// Retrieves the value of |property_id| for |user| and places it in |out_value|.
+// The function returns:
+// - |true| if the property value is retrieved successfully
+// - |false| if |user| is invalid; if |property_id| isn't recognized, supported,
+//   or set for |user|; or if |value_size| is too small.
+//
+// |user|: The user for which property size data is being retrieved.
+// |property_id|: The property for which the data is requested.
+// |out_value|: The retrieved property value.
+// |value_size|: The size of the retrieved property value.
 SB_EXPORT bool SbUserGetProperty(SbUser user,
                                  SbUserPropertyId property_id,
                                  char* out_value,
diff --git a/src/starboard/window.h b/src/starboard/window.h
index 44bb3e1..370109e 100644
--- a/src/starboard/window.h
+++ b/src/starboard/window.h
@@ -12,7 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Display Window creation and management.
+// Module Overview: Starboard Window module
+//
+// Provides functionality to handle Window creation and management.
 
 #ifndef STARBOARD_WINDOW_H_
 #define STARBOARD_WINDOW_H_
@@ -81,39 +83,52 @@
   return window != kSbWindowInvalid;
 }
 
-// Creates a new system window with the given |options|, which may be
-// NULL. Returns kSbWindowInvalid if unable to create the requested SbWindow,
-// either due to policy, or unsatisfiable options.
+// Creates and returns a new system window with the given |options|, which may
+// be |NULL|. The function returns |kSbWindowInvalid| if it cannot create the
+// requested |SbWindow| due to policy, unsatisfiable options, or any other
+// reason.
 //
-// If options are not specified, this function will use all defaults, which must
+// If |options| are not specified, this function uses all defaults, which must
 // work on every platform. In general, it defaults to creating a fullscreen
-// window at the highest 16:9 resolution that it can. If the platform does not
-// support fullscreen windows, then it will create a normal windowed window.
+// window at the highest 16:9 resolution possible. If the platform does not
+// support fullscreen windows, then it creates a normal, windowed window.
 //
-// Some devices are fullscreen-only (most of the production targets for
-// Starboard). In those cases, only one SbWindow may be created, and it must be
-// fullscreen. Additionally, the requested size will actually be the requested
-// resolution, and must be a supported resolution, as specified by the
-// resolutions returned by SbWindowGetSupportedResolutionIterator().
+// Some devices are fullscreen-only, including many production targets for
+// Starboard. In those cases, only one SbWindow may be created, and it must be
+// fullscreen. Additionally, in those cases, the requested size will actually
+// be the requested resolution.
 //
-// A SbWindow must be created in order to receive window-based events, like
-// input events, even on fullscreen-only devices. These will be dispatched to
+// An SbWindow must be created to receive window-based events, like input
+// events, even on fullscreen-only devices. These events are dispatched to
 // the Starboard entry point.
+//
+// |options|: Options that specify parameters for the window being created.
 SB_EXPORT SbWindow SbWindowCreate(const SbWindowOptions* options);
 
-// Sets |options| to all the defaults. |options| must not be NULL.
+// Sets the default options for system windows.
+//
+// |options|: The option values to use as default values. This object must not
+// be |NULL|.
 SB_EXPORT void SbWindowSetDefaultOptions(SbWindowOptions* options);
 
 // Destroys |window|, reclaiming associated resources.
+//
+// |window|: The |SbWindow| to destroy.
 SB_EXPORT bool SbWindowDestroy(SbWindow window);
 
-// Sets |size| to the dimensions of |window|. Returns true on success. If false
-// is returned, |size| will not be modified.
+// Retrieves the dimensions of |window| and sets |size| accordingly. This
+// function returns |true| if it completes successfully. If the function
+// returns |false|, then |size| will not have been modified.
+//
+// |window|: The SbWindow to retrieve the size of.
+// |size|: The retrieved size.
 SB_EXPORT bool SbWindowGetSize(SbWindow window, SbWindowSize* size);
 
 // Gets the platform-specific handle for |window|, which can be passed as an
 // EGLNativeWindowType to initialize EGL/GLES. This return value is entirely
-// platform specific, so there are no constraints about expected ranges.
+// platform-specific, so there are no constraints about expected ranges.
+//
+// |window|: The SbWindow to retrieve the platform handle for.
 SB_EXPORT void* SbWindowGetPlatformHandle(SbWindow window);
 
 #ifdef __cplusplus