Merge "libaudiohal: Add optional "msd" devices factory"
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 629d75a..1793877 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -471,10 +471,6 @@
* Otherwise will always be present.</p>
* <p>The maximum number of regions supported by the device is determined by the value
* of android.control.maxRegionsAe.</p>
- * <p>The data representation is int[5 * area_count].
- * Every five elements represent a metering region of (xmin, ymin, xmax, ymax, weight).
- * The rectangle is defined to be inclusive on xmin and ymin, but exclusive on xmax and
- * ymax.</p>
* <p>The coordinate system is based on the active pixel array,
* with (0,0) being the top-left pixel in the active pixel array, and
* (ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE.width - 1,
@@ -495,6 +491,10 @@
* region and output only the intersection rectangle as the metering region in the result
* metadata. If the region is entirely outside the crop region, it will be ignored and
* not reported in the result metadata.</p>
+ * <p>The data representation is <code>int[5 * area_count]</code>.
+ * Every five elements represent a metering region of <code>(xmin, ymin, xmax, ymax, weight)</code>.
+ * The rectangle is defined to be inclusive on xmin and ymin, but exclusive on xmax and
+ * ymax.</p>
*
* @see ACAMERA_SCALER_CROP_REGION
* @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -633,10 +633,6 @@
* Otherwise will always be present.</p>
* <p>The maximum number of focus areas supported by the device is determined by the value
* of android.control.maxRegionsAf.</p>
- * <p>The data representation is int[5 * area_count].
- * Every five elements represent a metering region of (xmin, ymin, xmax, ymax, weight).
- * The rectangle is defined to be inclusive on xmin and ymin, but exclusive on xmax and
- * ymax.</p>
* <p>The coordinate system is based on the active pixel array,
* with (0,0) being the top-left pixel in the active pixel array, and
* (ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE.width - 1,
@@ -657,6 +653,10 @@
* region and output only the intersection rectangle as the metering region in the result
* metadata. If the region is entirely outside the crop region, it will be ignored and
* not reported in the result metadata.</p>
+ * <p>The data representation is <code>int[5 * area_count]</code>.
+ * Every five elements represent a metering region of <code>(xmin, ymin, xmax, ymax, weight)</code>.
+ * The rectangle is defined to be inclusive on xmin and ymin, but exclusive on xmax and
+ * ymax.</p>
*
* @see ACAMERA_SCALER_CROP_REGION
* @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -791,10 +791,6 @@
* Otherwise will always be present.</p>
* <p>The maximum number of regions supported by the device is determined by the value
* of android.control.maxRegionsAwb.</p>
- * <p>The data representation is int[5 * area_count].
- * Every five elements represent a metering region of (xmin, ymin, xmax, ymax, weight).
- * The rectangle is defined to be inclusive on xmin and ymin, but exclusive on xmax and
- * ymax.</p>
* <p>The coordinate system is based on the active pixel array,
* with (0,0) being the top-left pixel in the active pixel array, and
* (ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE.width - 1,
@@ -815,6 +811,10 @@
* region and output only the intersection rectangle as the metering region in the result
* metadata. If the region is entirely outside the crop region, it will be ignored and
* not reported in the result metadata.</p>
+ * <p>The data representation is <code>int[5 * area_count]</code>.
+ * Every five elements represent a metering region of <code>(xmin, ymin, xmax, ymax, weight)</code>.
+ * The rectangle is defined to be inclusive on xmin and ymin, but exclusive on xmax and
+ * ymax.</p>
*
* @see ACAMERA_SCALER_CROP_REGION
* @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -885,11 +885,10 @@
* <p>When set to AUTO, the individual algorithm controls in
* ACAMERA_CONTROL_* are in effect, such as ACAMERA_CONTROL_AF_MODE.</p>
* <p>When set to USE_SCENE_MODE, the individual controls in
- * ACAMERA_CONTROL_* are mostly disabled, and the camera device implements
- * one of the scene mode settings (such as ACTION, SUNSET, or PARTY)
- * as it wishes. The camera device scene mode 3A settings are provided by
- * capture results {@link ACameraMetadata} from
- * {@link ACameraCaptureSession_captureCallback_result}.</p>
+ * ACAMERA_CONTROL_* are mostly disabled, and the camera device
+ * implements one of the scene mode settings (such as ACTION,
+ * SUNSET, or PARTY) as it wishes. The camera device scene mode
+ * 3A settings are provided by {@link ACameraCaptureSession_captureCallback_result capture results}.</p>
* <p>When set to OFF_KEEP_STATE, it is similar to OFF mode, the only difference
* is that this frame will not be used by camera device background 3A statistics
* update, as if this frame is never captured. This mode can be used in the scenario
@@ -1043,20 +1042,18 @@
* <p>For constant-framerate recording, for each normal
* <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a>, that is, a
* <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a> that has
- * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#quality">quality</a>
- * in the range [
- * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#QUALITY_LOW">QUALITY_LOW</a>,
- * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#QUALITY_2160P">QUALITY_2160P</a>],
- * if the profile is supported by the device and has
- * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#videoFrameRate">videoFrameRate</a>
- * <code>x</code>, this list will always include (<code>x</code>,<code>x</code>).</p>
+ * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#quality">quality</a> in
+ * the range [<a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#QUALITY_LOW">QUALITY_LOW</a>,
+ * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#QUALITY_2160P">QUALITY_2160P</a>], if the profile is
+ * supported by the device and has
+ * <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#videoFrameRate">videoFrameRate</a> <code>x</code>, this list will
+ * always include (<code>x</code>,<code>x</code>).</p>
* </li>
* <li>
* <p>Also, a camera device must either not support any
* <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a>,
* or support at least one
- * normal <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a>
- * that has
+ * normal <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a> that has
* <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#videoFrameRate">videoFrameRate</a> <code>x</code> >= 24.</p>
* </li>
* </ul>
@@ -1619,13 +1616,13 @@
* compared to previous regular requests. enableZsl does not affect requests with other
* capture intents.</p>
* <p>For example, when requests are submitted in the following order:
- * Request A: enableZsl is <code>true</code>, ACAMERA_CONTROL_CAPTURE_INTENT is PREVIEW
- * Request B: enableZsl is <code>true</code>, ACAMERA_CONTROL_CAPTURE_INTENT is STILL_CAPTURE</p>
+ * Request A: enableZsl is ON, ACAMERA_CONTROL_CAPTURE_INTENT is PREVIEW
+ * Request B: enableZsl is ON, ACAMERA_CONTROL_CAPTURE_INTENT is STILL_CAPTURE</p>
* <p>The output images for request B may have contents captured before the output images for
* request A, and the result metadata for request B may be older than the result metadata for
* request A.</p>
- * <p>Note that when enableZsl is <code>true</code>, it is not guaranteed to get output images captured in the
- * past for requests with STILL_CAPTURE capture intent.</p>
+ * <p>Note that when enableZsl is <code>true</code>, it is not guaranteed to get output images captured in
+ * the past for requests with STILL_CAPTURE capture intent.</p>
* <p>For applications targeting SDK versions O and newer, the value of enableZsl in
* TEMPLATE_STILL_CAPTURE template may be <code>true</code>. The value in other templates is always
* <code>false</code> if present.</p>
@@ -1959,14 +1956,14 @@
* <p>When an ACAMERA_JPEG_ORIENTATION of non-zero degree is requested,
* the camera device will handle thumbnail rotation in one of the following ways:</p>
* <ul>
- * <li>Set the
- * <a href="https://developer.android.com/reference/android/media/ExifInterface.html#TAG_ORIENTATION">EXIF orientation flag</a>
+ * <li>Set the <a href="https://developer.android.com/reference/android/media/ExifInterface.html#TAG_ORIENTATION">EXIF orientation flag</a>
* and keep jpeg and thumbnail image data unrotated.</li>
* <li>Rotate the jpeg and thumbnail image data and not set
- * <a href="https://developer.android.com/reference/android/media/ExifInterface.html#TAG_ORIENTATION">EXIF orientation flag</a>.
- * In this case, LIMITED or FULL hardware level devices will report rotated thumnail size
- * in capture result, so the width and height will be interchanged if 90 or 270 degree
- * orientation is requested. LEGACY device will always report unrotated thumbnail size.</li>
+ * <a href="https://developer.android.com/reference/android/media/ExifInterface.html#TAG_ORIENTATION">EXIF orientation flag</a>. In this
+ * case, LIMITED or FULL hardware level devices will report rotated thumnail size in
+ * capture result, so the width and height will be interchanged if 90 or 270 degree
+ * orientation is requested. LEGACY device will always report unrotated thumbnail
+ * size.</li>
* </ul>
*
* @see ACAMERA_JPEG_ORIENTATION
@@ -2218,9 +2215,8 @@
* <p>The position of the camera device's lens optical center,
* as a three-dimensional vector <code>(x,y,z)</code>, relative to the
* optical center of the largest camera device facing in the
- * same direction as this camera, in the
- * <a href="https://developer.android.com/reference/android/hardware/SensorEvent.html">Android sensor coordinate axes</a>.
- * Note that only the axis definitions are shared with
+ * same direction as this camera, in the <a href="https://developer.android.com/reference/android/hardware/SensorEvent.html">Android sensor coordinate
+ * axes</a>. Note that only the axis definitions are shared with
* the sensor coordinate system, but not the origin.</p>
* <p>If this device is the largest or only camera device with a
* given facing, then this position will be <code>(0, 0, 0)</code>; a
@@ -2662,11 +2658,12 @@
* into the 3 stream types as below:</p>
* <ul>
* <li>Processed (but stalling): any non-RAW format with a stallDurations > 0.
- * Typically {@link AIMAGE_FORMAT_JPEG} format.</li>
- * <li>Raw formats: {@link AIMAGE_FORMAT_RAW16}, {@link AIMAGE_FORMAT_RAW10}, or
- * {@link AIMAGE_FORMAT_RAW12}.</li>
- * <li>Processed (but not-stalling): any non-RAW format without a stall duration.
- * Typically {@link AIMAGE_FORMAT_YUV_420_888}.</li>
+ * Typically {@link AIMAGE_FORMAT_JPEG JPEG format}.</li>
+ * <li>Raw formats: {@link AIMAGE_FORMAT_RAW16 RAW_SENSOR}, {@link AIMAGE_FORMAT_RAW10 RAW10}, or
+ * {@link AIMAGE_FORMAT_RAW12 RAW12}.</li>
+ * <li>Processed (but not-stalling): any non-RAW format without a stall duration. Typically
+ * {@link AIMAGE_FORMAT_YUV_420_888 YUV_420_888},
+ * <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#NV21">NV21</a>, or <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#YV12">YV12</a>.</li>
* </ul>
*
* @see ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS
@@ -2787,7 +2784,7 @@
ACAMERA_REQUEST_START + 12,
/**
* <p>A list of all keys that the camera device has available
- * to use with {@link ACaptureRequest}.</p>
+ * to use with {@link ACaptureRequest }.</p>
*
* <p>Type: int32[n]</p>
*
@@ -2809,9 +2806,7 @@
ACAMERA_REQUEST_AVAILABLE_REQUEST_KEYS = // int32[n]
ACAMERA_REQUEST_START + 13,
/**
- * <p>A list of all keys that the camera device has available
- * to query with {@link ACameraMetadata} from
- * {@link ACameraCaptureSession_captureCallback_result}.</p>
+ * <p>A list of all keys that the camera device has available to use with {@link ACameraCaptureSession_captureCallback_result }.</p>
*
* <p>Type: int32[n]</p>
*
@@ -2842,9 +2837,7 @@
ACAMERA_REQUEST_AVAILABLE_RESULT_KEYS = // int32[n]
ACAMERA_REQUEST_START + 14,
/**
- * <p>A list of all keys that the camera device has available
- * to query with {@link ACameraMetadata} from
- * {@link ACameraManager_getCameraCharacteristics}.</p>
+ * <p>A list of all keys that the camera device has available to use with {@link ACameraManager_getCameraCharacteristics }.</p>
*
* <p>Type: int32[n]</p>
*
@@ -2876,7 +2869,6 @@
* </ul></p>
*
* <p>This control can be used to implement digital zoom.</p>
- * <p>The data representation is int[4], which maps to (left, top, width, height).</p>
* <p>The crop region coordinate system is based off
* ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE, with <code>(0, 0)</code> being the
* top-left corner of the sensor active array.</p>
@@ -2906,6 +2898,7 @@
* for rounding and other hardware requirements; the final
* crop region used will be included in the output capture
* result.</p>
+ * <p>The data representation is int[4], which maps to (left, top, width, height).</p>
*
* @see ACAMERA_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM
* @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -3061,13 +3054,14 @@
* ignored).</p>
* <p>The following formats may always have a stall duration:</p>
* <ul>
- * <li>{@link AIMAGE_FORMAT_JPEG}</li>
- * <li>{@link AIMAGE_FORMAT_RAW16}</li>
+ * <li>{@link AIMAGE_FORMAT_JPEG }</li>
+ * <li>{@link AIMAGE_FORMAT_RAW16 }</li>
* </ul>
* <p>The following formats will never have a stall duration:</p>
* <ul>
- * <li>{@link AIMAGE_FORMAT_YUV_420_888}</li>
- * <li>{@link AIMAGE_FORMAT_RAW10}</li>
+ * <li>{@link AIMAGE_FORMAT_YUV_420_888 }</li>
+ * <li>{@link AIMAGE_FORMAT_RAW10 }</li>
+ * <li>{@link AIMAGE_FORMAT_RAW12 }</li>
* </ul>
* <p>All other formats may or may not have an allowed stall duration on
* a per-capability basis; refer to ACAMERA_REQUEST_AVAILABLE_CAPABILITIES
@@ -3177,39 +3171,29 @@
* can run concurrently to the rest of the camera pipeline, but
* cannot process more than 1 capture at a time.</li>
* </ul>
- * <p>The necessary information for the application, given the model above,
- * is provided via
- * {@link ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS}.
- * These are used to determine the maximum frame rate / minimum frame
- * duration that is possible for a given stream configuration.</p>
+ * <p>The necessary information for the application, given the model above, is provided via
+ * {@link ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS }.
+ * These are used to determine the maximum frame rate / minimum frame duration that is
+ * possible for a given stream configuration.</p>
* <p>Specifically, the application can use the following rules to
* determine the minimum frame duration it can request from the camera
* device:</p>
* <ol>
- * <li>Let the set of currently configured input/output streams
- * be called <code>S</code>.</li>
- * <li>Find the minimum frame durations for each stream in <code>S</code>, by looking
- * it up in {@link ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS}
- * (with its respective size/format). Let this set of frame durations be
- * called <code>F</code>.</li>
- * <li>For any given request <code>R</code>, the minimum frame duration allowed
- * for <code>R</code> is the maximum out of all values in <code>F</code>. Let the streams
- * used in <code>R</code> be called <code>S_r</code>.</li>
+ * <li>Let the set of currently configured input/output streams be called <code>S</code>.</li>
+ * <li>Find the minimum frame durations for each stream in <code>S</code>, by looking it up in {@link ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS }
+ * (with its respective size/format). Let this set of frame durations be called <code>F</code>.</li>
+ * <li>For any given request <code>R</code>, the minimum frame duration allowed for <code>R</code> is the maximum
+ * out of all values in <code>F</code>. Let the streams used in <code>R</code> be called <code>S_r</code>.</li>
* </ol>
- * <p>If none of the streams in <code>S_r</code> have a stall time (listed in {@link
- * ACAMERA_SCALER_AVAILABLE_STALL_DURATIONS}
- * using its respective size/format), then the frame duration in <code>F</code>
- * determines the steady state frame rate that the application will get
- * if it uses <code>R</code> as a repeating request. Let this special kind of
- * request be called <code>Rsimple</code>.</p>
- * <p>A repeating request <code>Rsimple</code> can be <em>occasionally</em> interleaved
- * by a single capture of a new request <code>Rstall</code> (which has at least
- * one in-use stream with a non-0 stall time) and if <code>Rstall</code> has the
- * same minimum frame duration this will not cause a frame rate loss
- * if all buffers from the previous <code>Rstall</code> have already been
- * delivered.</p>
- * <p>For more details about stalling, see
- * {@link ACAMERA_SCALER_AVAILABLE_STALL_DURATIONS}.</p>
+ * <p>If none of the streams in <code>S_r</code> have a stall time (listed in {@link ACAMERA_SCALER_AVAILABLE_STALL_DURATIONS }
+ * using its respective size/format), then the frame duration in <code>F</code> determines the steady
+ * state frame rate that the application will get if it uses <code>R</code> as a repeating request. Let
+ * this special kind of request be called <code>Rsimple</code>.</p>
+ * <p>A repeating request <code>Rsimple</code> can be <em>occasionally</em> interleaved by a single capture of a
+ * new request <code>Rstall</code> (which has at least one in-use stream with a non-0 stall time) and if
+ * <code>Rstall</code> has the same minimum frame duration this will not cause a frame rate loss if all
+ * buffers from the previous <code>Rstall</code> have already been delivered.</p>
+ * <p>For more details about stalling, see {@link ACAMERA_SCALER_AVAILABLE_STALL_DURATIONS }.</p>
* <p>This control is only effective if ACAMERA_CONTROL_AE_MODE or ACAMERA_CONTROL_MODE is set to
* OFF; otherwise the auto-exposure algorithm will override this value.</p>
*
@@ -3567,14 +3551,12 @@
* timestamps for other captures from the same camera device, but are
* not guaranteed to be comparable to any other time source.</p>
* <p>When ACAMERA_SENSOR_INFO_TIMESTAMP_SOURCE <code>==</code> REALTIME, the
- * timestamps measure time in the same timebase as
- * <a href="https://developer.android.com/reference/android/os/SystemClock.html#elapsedRealtimeNanos">elapsedRealtimeNanos</a>
- * (or CLOCK_BOOTTIME), and they can
+ * timestamps measure time in the same timebase as <a href="https://developer.android.com/reference/android/os/SystemClock.html#elapsedRealtimeNanos">SystemClock#elapsedRealtimeNanos</a>, and they can
* be compared to other timestamps from other subsystems that
* are using that base.</p>
* <p>For reprocessing, the timestamp will match the start of exposure of
- * the input image, i.e. {@link CaptureResult#SENSOR_TIMESTAMP the
- * timestamp} in the TotalCaptureResult that was used to create the
+ * the input image, i.e. <a href="https://developer.android.com/reference/CaptureResult.html#SENSOR_TIMESTAMP">the
+ * timestamp</a> in the TotalCaptureResult that was used to create the
* reprocess capture request.</p>
*
* @see ACAMERA_SENSOR_INFO_TIMESTAMP_SOURCE
@@ -3775,7 +3757,6 @@
* optically shielded pixel areas. By blocking light, these pixels
* provides a reliable black reference for black level compensation
* in active array region.</p>
- * <p>The data representation is int[4], which maps to (left, top, width, height).</p>
* <p>This key provides a list of disjoint rectangles specifying the
* regions of optically shielded (with metal shield) black pixel
* regions if the camera device is capable of reading out these black
@@ -3785,6 +3766,7 @@
* black level of each captured raw images.</p>
* <p>When this key is reported, the ACAMERA_SENSOR_DYNAMIC_BLACK_LEVEL and
* ACAMERA_SENSOR_DYNAMIC_WHITE_LEVEL will also be reported.</p>
+ * <p>The data representation is <code>int[4]</code>, which maps to <code>(left, top, width, height)</code>.</p>
*
* @see ACAMERA_SENSOR_BLACK_LEVEL_PATTERN
* @see ACAMERA_SENSOR_DYNAMIC_BLACK_LEVEL
@@ -3825,9 +3807,8 @@
* layout key (see ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT), i.e. the
* nth value given corresponds to the black level offset for the nth
* color channel listed in the CFA.</p>
- * <p>This key will be available if ACAMERA_SENSOR_OPTICAL_BLACK_REGIONS is
- * available or the camera device advertises this key via
- * {@link ACAMERA_REQUEST_AVAILABLE_RESULT_KEYS}.</p>
+ * <p>This key will be available if ACAMERA_SENSOR_OPTICAL_BLACK_REGIONS is available or the
+ * camera device advertises this key via {@link ACAMERA_REQUEST_AVAILABLE_RESULT_KEYS }.</p>
*
* @see ACAMERA_SENSOR_BLACK_LEVEL_PATTERN
* @see ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
@@ -3853,7 +3834,7 @@
* estimated white level for each frame.</p>
* <p>This key will be available if ACAMERA_SENSOR_OPTICAL_BLACK_REGIONS is
* available or the camera device advertises this key via
- * {@link ACAMERA_REQUEST_AVAILABLE_RESULT_KEYS}.</p>
+ * {@link ACAMERA_REQUEST_AVAILABLE_RESULT_KEYS }.</p>
*
* @see ACAMERA_SENSOR_BLACK_LEVEL_PATTERN
* @see ACAMERA_SENSOR_INFO_WHITE_LEVEL
@@ -3882,13 +3863,13 @@
* <p>This rectangle is defined relative to the full pixel array; (0,0) is the top-left of
* the full pixel array, and the size of the full pixel array is given by
* ACAMERA_SENSOR_INFO_PIXEL_ARRAY_SIZE.</p>
- * <p>The data representation is int[4], which maps to (left, top, width, height).</p>
* <p>The coordinate system for most other keys that list pixel coordinates, including
* ACAMERA_SCALER_CROP_REGION, is defined relative to the active array rectangle given in
* this field, with <code>(0, 0)</code> being the top-left of this rectangle.</p>
* <p>The active array may be smaller than the full pixel array, since the full array may
* include black calibration pixels or other inactive regions, and geometric correction
* resulting in scaling or cropping may have been applied.</p>
+ * <p>The data representation is <code>int[4]</code>, which maps to <code>(left, top, width, height)</code>.</p>
*
* @see ACAMERA_SCALER_CROP_REGION
* @see ACAMERA_SENSOR_INFO_PIXEL_ARRAY_SIZE
@@ -3960,8 +3941,7 @@
* <p>Attempting to use frame durations beyond the maximum will result in the frame
* duration being clipped to the maximum. See that control for a full definition of frame
* durations.</p>
- * <p>Refer to {@link
- * ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS}
+ * <p>Refer to {@link ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS }
* for the minimum frame duration values.</p>
*/
ACAMERA_SENSOR_INFO_MAX_FRAME_DURATION = // int64
@@ -4000,9 +3980,9 @@
* the raw buffers produced by this sensor.</p>
* <p>If a camera device supports raw sensor formats, either this or
* ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE is the maximum dimensions for the raw
- * output formats listed in ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS (this depends on
- * whether or not the image sensor returns buffers containing pixels that are not
- * part of the active array region for blacklevel calibration or other purposes).</p>
+ * output formats listed in {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS }
+ * (this depends on whether or not the image sensor returns buffers containing pixels that
+ * are not part of the active array region for blacklevel calibration or other purposes).</p>
* <p>Some parts of the full pixel array may not receive light from the scene,
* or be otherwise inactive. The ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE key
* defines the rectangle of active pixels that will be included in processed image
@@ -4092,7 +4072,6 @@
* <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
* </ul></p>
*
- * <p>The data representation is int[4], which maps to (left, top, width, height).</p>
* <p>This is the rectangle representing the size of the active region of the sensor (i.e.
* the region that actually receives light from the scene) before any geometric correction
* has been applied, and should be treated as the active region rectangle for any of the
@@ -4143,6 +4122,7 @@
* ACAMERA_SENSOR_INFO_PIXEL_ARRAY_SIZE.</p>
* <p>The pre-correction active array may be smaller than the full pixel array, since the
* full array may include black calibration pixels or other inactive regions.</p>
+ * <p>The data representation is <code>int[4]</code>, which maps to <code>(left, top, width, height)</code>.</p>
*
* @see ACAMERA_LENS_RADIAL_DISTORTION
* @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -4302,10 +4282,10 @@
* <li>ACameraMetadata from ACameraCaptureSession_captureCallback_result callbacks</li>
* </ul></p>
*
- * <p>The data representation is int[4], which maps to (left, top, width, height).</p>
* <p>The coordinate system is that of ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE, with
* <code>(0, 0)</code> being the top-left pixel of the active array.</p>
- * <p>Only available if ACAMERA_STATISTICS_FACE_DETECT_MODE != OFF</p>
+ * <p>Only available if ACAMERA_STATISTICS_FACE_DETECT_MODE != OFF
+ * The data representation is <code>int[4]</code>, which maps to <code>(left, top, width, height)</code>.</p>
*
* @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
* @see ACAMERA_STATISTICS_FACE_DETECT_MODE
@@ -4832,7 +4812,7 @@
* <p>See the individual level enums for full descriptions of the supported capabilities. The
* ACAMERA_REQUEST_AVAILABLE_CAPABILITIES entry describes the device's capabilities at a
* finer-grain level, if needed. In addition, many controls have their available settings or
- * ranges defined in individual metadata tag entries in this document.</p>
+ * ranges defined in individual entries from {@link ACameraManager_getCameraCharacteristics }.</p>
* <p>Some features are not part of any particular hardware level or capability and must be
* queried separately. These include:</p>
* <ul>
@@ -6157,13 +6137,13 @@
ACAMERA_EDGE_MODE_HIGH_QUALITY = 2,
/**
- * <p>Edge enhancement is applied at different levels for different output streams,
- * based on resolution. Streams at maximum recording resolution (see {@link
- * ACameraDevice_createCaptureSession}) or below have
- * edge enhancement applied, while higher-resolution streams have no edge enhancement
- * applied. The level of edge enhancement for low-resolution streams is tuned so that
- * frame rate is not impacted, and the quality is equal to or better than FAST (since it
- * is only applied to lower-resolution outputs, quality may improve from FAST).</p>
+ * <p>Edge enhancement is applied at different
+ * levels for different output streams, based on resolution. Streams at maximum recording
+ * resolution (see {@link ACameraDevice_createCaptureSession })
+ * or below have edge enhancement applied, while higher-resolution streams have no edge
+ * enhancement applied. The level of edge enhancement for low-resolution streams is tuned
+ * so that frame rate is not impacted, and the quality is equal to or better than FAST
+ * (since it is only applied to lower-resolution outputs, quality may improve from FAST).</p>
* <p>This mode is intended to be used by applications operating in a zero-shutter-lag mode
* with YUV or PRIVATE reprocessing, where the application continuously captures
* high-resolution intermediate buffers into a circular buffer, from which a final image is
@@ -6412,13 +6392,12 @@
/**
* <p>Noise reduction is applied at different levels for different output streams,
- * based on resolution. Streams at maximum recording resolution (see {@link
- * ACameraDevice_createCaptureSession}) or below have noise
- * reduction applied, while higher-resolution streams have MINIMAL (if supported) or no
- * noise reduction applied (if MINIMAL is not supported.) The degree of noise reduction
- * for low-resolution streams is tuned so that frame rate is not impacted, and the quality
- * is equal to or better than FAST (since it is only applied to lower-resolution outputs,
- * quality may improve from FAST).</p>
+ * based on resolution. Streams at maximum recording resolution (see {@link ACameraDevice_createCaptureSession })
+ * or below have noise reduction applied, while higher-resolution streams have MINIMAL (if
+ * supported) or no noise reduction applied (if MINIMAL is not supported.) The degree of
+ * noise reduction for low-resolution streams is tuned so that frame rate is not impacted,
+ * and the quality is equal to or better than FAST (since it is only applied to
+ * lower-resolution outputs, quality may improve from FAST).</p>
* <p>This mode is intended to be used by applications operating in a zero-shutter-lag mode
* with YUV or PRIVATE reprocessing, where the application continuously captures
* high-resolution intermediate buffers into a circular buffer, from which a final image is
@@ -6635,18 +6614,16 @@
* to FAST. Additionally, maximum-resolution images can be captured at >= 10 frames
* per second. Here, 'high resolution' means at least 8 megapixels, or the maximum
* resolution of the device, whichever is smaller.</p>
- * <p>More specifically, this means that at least one output {@link
- * AIMAGE_FORMAT_YUV_420_888} size listed in
- * {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS} is larger or equal to the
- * 'high resolution' defined above, and can be captured at at least 20 fps.
- * For the largest {@link AIMAGE_FORMAT_YUV_420_888} size listed in
- * {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS}, camera device can capture this
- * size for at least 10 frames per second.
- * Also the ACAMERA_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES entry lists at least one FPS range
- * where the minimum FPS is >= 1 / minimumFrameDuration for the largest YUV_420_888 size.</p>
- * <p>If the device supports the {@link AIMAGE_FORMAT_RAW10}, {@link
- * AIMAGE_FORMAT_RAW12}, then those can also be captured at the same rate
- * as the maximum-size YUV_420_888 resolution is.</p>
+ * <p>More specifically, this means that at least one output {@link AIMAGE_FORMAT_YUV_420_888 } size listed in
+ * {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS }
+ * is larger or equal to the 'high resolution' defined above, and can be captured at at
+ * least 20 fps. For the largest {@link AIMAGE_FORMAT_YUV_420_888 } size listed in
+ * {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS },
+ * camera device can capture this size for at least 10 frames per second. Also the
+ * ACAMERA_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES entry lists at least one FPS range where
+ * the minimum FPS is >= 1 / minimumFrameDuration for the largest YUV_420_888 size.</p>
+ * <p>If the device supports the {@link AIMAGE_FORMAT_RAW10 }, {@link AIMAGE_FORMAT_RAW12 }, then those can also be
+ * captured at the same rate as the maximum-size YUV_420_888 resolution is.</p>
* <p>In addition, the ACAMERA_SYNC_MAX_LATENCY field is guaranted to have a value between 0
* and 4, inclusive. ACAMERA_CONTROL_AE_LOCK_AVAILABLE and ACAMERA_CONTROL_AWB_LOCK_AVAILABLE
* are also guaranteed to be <code>true</code> so burst capture with these two locks ON yields
@@ -6663,13 +6640,13 @@
* <p>The camera device can produce depth measurements from its field of view.</p>
* <p>This capability requires the camera device to support the following:</p>
* <ul>
- * <li>{@link AIMAGE_FORMAT_DEPTH16} is supported as an output format.</li>
- * <li>{@link AIMAGE_FORMAT_DEPTH_POINT_CLOUD} is optionally supported as an
- * output format.</li>
- * <li>This camera device, and all camera devices with the same ACAMERA_LENS_FACING,
- * will list the following calibration entries in {@link ACameraMetadata} from both
- * {@link ACameraManager_getCameraCharacteristics} and
- * {@link ACameraCaptureSession_captureCallback_result}:<ul>
+ * <li>{@link AIMAGE_FORMAT_DEPTH16 } is supported as
+ * an output format.</li>
+ * <li>{@link AIMAGE_FORMAT_DEPTH_POINT_CLOUD } is
+ * optionally supported as an output format.</li>
+ * <li>This camera device, and all camera devices with the same ACAMERA_LENS_FACING, will
+ * list the following calibration metadata entries in both {@link ACameraManager_getCameraCharacteristics }
+ * and {@link ACameraCaptureSession_captureCallback_result }:<ul>
* <li>ACAMERA_LENS_POSE_TRANSLATION</li>
* <li>ACAMERA_LENS_POSE_ROTATION</li>
* <li>ACAMERA_LENS_INTRINSIC_CALIBRATION</li>
@@ -6683,8 +6660,7 @@
* </ul>
* <p>Generally, depth output operates at a slower frame rate than standard color capture,
* so the DEPTH16 and DEPTH_POINT_CLOUD formats will commonly have a stall duration that
- * should be accounted for (see
- * {@link ACAMERA_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS}).
+ * should be accounted for (see {@link ACAMERA_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS }).
* On a device that supports both depth and color-based output, to enable smooth preview,
* using a repeating burst is recommended, where a depth-output target is only included
* once every N frames, where N is the ratio between preview output rate and depth output
@@ -6918,8 +6894,8 @@
/**
* <p>Timestamps from ACAMERA_SENSOR_TIMESTAMP are in the same timebase as
- * <a href="https://developer.android.com/reference/android/os/SystemClock.html#elapsedRealtimeNanos">elapsedRealtimeNanos</a>
- * (or CLOCK_BOOTTIME), and they can be compared to other timestamps using that base.</p>
+ * <a href="https://developer.android.com/reference/android/os/SystemClock.html#elapsedRealtimeNanos">SystemClock#elapsedRealtimeNanos</a>,
+ * and they can be compared to other timestamps using that base.</p>
*
* @see ACAMERA_SENSOR_TIMESTAMP
*/
@@ -7104,7 +7080,7 @@
* <p>This camera device does not have enough capabilities to qualify as a <code>FULL</code> device or
* better.</p>
* <p>Only the stream configurations listed in the <code>LEGACY</code> and <code>LIMITED</code> tables in the
- * {@link ACameraDevice_createCaptureSession} documentation are guaranteed to be supported.</p>
+ * {@link ACameraDevice_createCaptureSession createCaptureSession} documentation are guaranteed to be supported.</p>
* <p>All <code>LIMITED</code> devices support the <code>BACKWARDS_COMPATIBLE</code> capability, indicating basic
* support for color image capture. The only exception is that the device may
* alternatively support only the <code>DEPTH_OUTPUT</code> capability, if it can only output depth
@@ -7130,7 +7106,7 @@
/**
* <p>This camera device is capable of supporting advanced imaging applications.</p>
* <p>The stream configurations listed in the <code>FULL</code>, <code>LEGACY</code> and <code>LIMITED</code> tables in the
- * {@link ACameraDevice_createCaptureSession} documentation are guaranteed to be supported.</p>
+ * {@link ACameraDevice_createCaptureSession createCaptureSession} documentation are guaranteed to be supported.</p>
* <p>A <code>FULL</code> device will support below capabilities:</p>
* <ul>
* <li><code>BURST_CAPTURE</code> capability (ACAMERA_REQUEST_AVAILABLE_CAPABILITIES contains
@@ -7157,8 +7133,7 @@
/**
* <p>This camera device is running in backward compatibility mode.</p>
- * <p>Only the stream configurations listed in the <code>LEGACY</code> table in the {@link
- * ACameraDevice_createCaptureSession} documentation are supported.</p>
+ * <p>Only the stream configurations listed in the <code>LEGACY</code> table in the {@link ACameraDevice_createCaptureSession createCaptureSession} documentation are supported.</p>
* <p>A <code>LEGACY</code> device does not support per-frame control, manual sensor control, manual
* post-processing, arbitrary cropping regions, and has relaxed performance constraints.
* No additional capabilities beyond <code>BACKWARD_COMPATIBLE</code> will ever be listed by a
@@ -7179,9 +7154,7 @@
* <p>This camera device is capable of YUV reprocessing and RAW data capture, in addition to
* FULL-level capabilities.</p>
* <p>The stream configurations listed in the <code>LEVEL_3</code>, <code>RAW</code>, <code>FULL</code>, <code>LEGACY</code> and
- * <code>LIMITED</code> tables in the {@link
- * ACameraDevice_createCaptureSession}
- * documentation are guaranteed to be supported.</p>
+ * <code>LIMITED</code> tables in the {@link ACameraDevice_createCaptureSession createCaptureSession} documentation are guaranteed to be supported.</p>
* <p>The following additional capabilities are guaranteed to be supported:</p>
* <ul>
* <li><code>YUV_REPROCESSING</code> capability (ACAMERA_REQUEST_AVAILABLE_CAPABILITIES contains
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 283bcb4..7623d6d 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -7,16 +7,16 @@
jpeg.cpp \
SineSource.cpp
-LOCAL_HEADER_LIBRARIES := \
- media_plugin_headers \
-
LOCAL_SHARED_LIBRARIES := \
libstagefright libmedia libmedia_omx libmediaextractor libutils libbinder \
libstagefright_foundation libjpeg libui libgui libcutils liblog \
- libhidlbase \
+ libhidlmemory \
android.hardware.media.omx@1.0 \
LOCAL_C_INCLUDES:= \
+ frameworks/av/media/libstagefright \
+ frameworks/av/media/libstagefright/include \
+ frameworks/native/include/media/openmax \
external/jpeg \
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
@@ -35,13 +35,15 @@
SineSource.cpp \
record.cpp
-LOCAL_HEADER_LIBRARIES := \
- media_plugin_headers \
-
LOCAL_SHARED_LIBRARIES := \
libstagefright libmedia libmediaextractor liblog libutils libbinder \
libstagefright_foundation
+LOCAL_C_INCLUDES:= \
+ frameworks/av/media/libstagefright \
+ frameworks/native/include/media/openmax \
+ frameworks/native/include/media/hardware
+
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
LOCAL_MODULE_TAGS := optional
@@ -58,13 +60,15 @@
SineSource.cpp \
recordvideo.cpp
-LOCAL_HEADER_LIBRARIES := \
- media_plugin_headers \
-
LOCAL_SHARED_LIBRARIES := \
libstagefright libmedia libmediaextractor liblog libutils libbinder \
libstagefright_foundation
+LOCAL_C_INCLUDES:= \
+ frameworks/av/media/libstagefright \
+ frameworks/native/include/media/openmax \
+ frameworks/native/include/media/hardware
+
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
LOCAL_MODULE_TAGS := optional
@@ -82,13 +86,14 @@
SineSource.cpp \
audioloop.cpp
-LOCAL_HEADER_LIBRARIES := \
- media_plugin_headers \
-
LOCAL_SHARED_LIBRARIES := \
libstagefright libmedia libmediaextractor liblog libutils libbinder \
libstagefright_foundation
+LOCAL_C_INCLUDES:= \
+ frameworks/av/media/libstagefright \
+ frameworks/native/include/media/openmax
+
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
LOCAL_MODULE_TAGS := optional
@@ -104,13 +109,14 @@
LOCAL_SRC_FILES:= \
stream.cpp \
-LOCAL_HEADER_LIBRARIES := \
- media_plugin_headers \
-
LOCAL_SHARED_LIBRARIES := \
libstagefright liblog libutils libbinder libui libgui \
libstagefright_foundation libmedia libcutils
+LOCAL_C_INCLUDES:= \
+ frameworks/av/media/libstagefright \
+ frameworks/native/include/media/openmax
+
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
LOCAL_MODULE_TAGS := optional
@@ -127,13 +133,14 @@
codec.cpp \
SimplePlayer.cpp \
-LOCAL_HEADER_LIBRARIES := \
- media_plugin_headers \
-
LOCAL_SHARED_LIBRARIES := \
libstagefright liblog libutils libbinder libstagefright_foundation \
libmedia libmedia_omx libaudioclient libui libgui libcutils
+LOCAL_C_INCLUDES:= \
+ frameworks/av/media/libstagefright \
+ frameworks/native/include/media/openmax
+
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
LOCAL_MODULE_TAGS := optional
@@ -152,9 +159,6 @@
filters/saturation.rs \
mediafilter.cpp \
-LOCAL_HEADER_LIBRARIES := \
- media_plugin_headers \
-
LOCAL_SHARED_LIBRARIES := \
libstagefright \
liblog \
@@ -168,9 +172,14 @@
libcutils \
libRScpp \
+LOCAL_C_INCLUDES:= \
+ frameworks/av/media/libstagefright \
+ frameworks/native/include/media/openmax \
+ frameworks/rs/cpp \
+ frameworks/rs \
+
intermediates := $(call intermediates-dir-for,STATIC_LIBRARIES,libRS,TARGET,)
LOCAL_C_INCLUDES += $(intermediates)
-LOCAL_C_INCLUDES += frameworks/av/media/libstagefright/filters
LOCAL_STATIC_LIBRARIES:= \
libstagefright_mediafilter
@@ -193,13 +202,14 @@
LOCAL_SRC_FILES:= \
muxer.cpp \
-LOCAL_HEADER_LIBRARIES := \
- media_plugin_headers \
-
LOCAL_SHARED_LIBRARIES := \
libstagefright liblog libutils libbinder libstagefright_foundation \
libcutils libc
+LOCAL_C_INCLUDES:= \
+ frameworks/av/media/libstagefright \
+ frameworks/native/include/media/openmax
+
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
LOCAL_MODULE_TAGS := optional
diff --git a/cmds/stagefright/mediafilter.cpp b/cmds/stagefright/mediafilter.cpp
index c90a2e4..f24d2dd 100644
--- a/cmds/stagefright/mediafilter.cpp
+++ b/cmds/stagefright/mediafilter.cpp
@@ -20,7 +20,7 @@
#include <inttypes.h>
#include <binder/ProcessState.h>
-#include <ColorConvert.h>
+#include <filters/ColorConvert.h>
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/Surface.h>
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index f873ba5..50b034a 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -36,12 +36,13 @@
#include <media/MediaSource.h>
#include <media/ICrypto.h>
#include <media/IMediaHTTPService.h>
+#include <media/IMediaCodecService.h>
#include <media/IMediaPlayerService.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AUtils.h>
-#include <NuCachedSource2.h>
+#include "include/NuCachedSource2.h"
#include <media/stagefright/AudioPlayer.h>
#include <media/stagefright/DataSourceFactory.h>
#include <media/stagefright/JPEGSource.h>
@@ -67,6 +68,7 @@
#include <gui/SurfaceComposerClient.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
+#include <media/omx/1.0/WOmx.h>
using namespace android;
@@ -910,24 +912,37 @@
}
if (listComponents) {
- using ::android::hardware::hidl_vec;
- using ::android::hardware::hidl_string;
- using namespace ::android::hardware::media::omx::V1_0;
- sp<IOmx> omx = IOmx::getService();
- CHECK(omx.get() != nullptr);
+ sp<IOMX> omx;
+ if (property_get_bool("persist.media.treble_omx", true)) {
+ using namespace ::android::hardware::media::omx::V1_0;
+ sp<IOmx> tOmx = IOmx::getService();
- hidl_vec<IOmx::ComponentInfo> nodeList;
- auto transStatus = omx->listNodes([](
- const auto& status, const auto& nodeList) {
- CHECK(status == Status::OK);
- for (const auto& info : nodeList) {
- printf("%s\t Roles: ", info.mName.c_str());
- for (const auto& role : info.mRoles) {
- printf("%s\t", role.c_str());
- }
- }
- });
- CHECK(transStatus.isOk());
+ CHECK(tOmx.get() != NULL);
+
+ omx = new utils::LWOmx(tOmx);
+ } else {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16("media.codec"));
+ sp<IMediaCodecService> service = interface_cast<IMediaCodecService>(binder);
+
+ CHECK(service.get() != NULL);
+
+ omx = service->getOMX();
+ }
+ CHECK(omx.get() != NULL);
+
+ List<IOMX::ComponentInfo> list;
+ omx->listNodes(&list);
+
+ for (List<IOMX::ComponentInfo>::iterator it = list.begin();
+ it != list.end(); ++it) {
+ printf("%s\t Roles: ", (*it).mName.string());
+ for (List<String8>::iterator itRoles = (*it).mRoles.begin() ;
+ itRoles != (*it).mRoles.end() ; ++itRoles) {
+ printf("%s\t", (*itRoles).string());
+ }
+ printf("\n");
+ }
}
sp<SurfaceComposerClient> composerClient;
diff --git a/media/audioserver/Android.mk b/media/audioserver/Android.mk
index 0777890..ee87751 100644
--- a/media/audioserver/Android.mk
+++ b/media/audioserver/Android.mk
@@ -13,11 +13,12 @@
libbinder \
libcutils \
liblog \
+ libhidltransport \
+ libhwbinder \
libmedialogservice \
libnbaio \
libsoundtriggerservice \
- libutils \
- libhwbinder
+ libutils
# TODO oboeservice is the old folder name for aaudioservice. It will be changed.
LOCAL_C_INCLUDES := \
diff --git a/media/audioserver/main_audioserver.cpp b/media/audioserver/main_audioserver.cpp
index 474ef97..5a9d1bb 100644
--- a/media/audioserver/main_audioserver.cpp
+++ b/media/audioserver/main_audioserver.cpp
@@ -25,12 +25,9 @@
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
+#include <hidl/HidlTransportSupport.h>
#include <utils/Log.h>
-// FIXME: remove when BUG 31748996 is fixed
-#include <hwbinder/IPCThreadState.h>
-#include <hwbinder/ProcessState.h>
-
// from LOCAL_C_INCLUDES
#include "aaudio/AAudioTesting.h"
#include "AudioFlinger.h"
@@ -128,6 +125,7 @@
prctl(PR_SET_PDEATHSIG, SIGKILL); // if parent media.log dies before me, kill me also
setpgid(0, 0); // but if I die first, don't kill my parent
}
+ android::hardware::configureRpcThreadpool(4, false /*callerWillJoin*/);
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
ALOGI("ServiceManager: %p", sm.get());
@@ -145,10 +143,6 @@
SoundTriggerHwService::instantiate();
ProcessState::self()->startThreadPool();
-
-// FIXME: remove when BUG 31748996 is fixed
- android::hardware::ProcessState::self()->startThreadPool();
-
IPCThreadState::self()->joinThreadPool();
}
}
diff --git a/media/libaudioclient/ToneGenerator.cpp b/media/libaudioclient/ToneGenerator.cpp
index fa1d253..cfb5be6 100644
--- a/media/libaudioclient/ToneGenerator.cpp
+++ b/media/libaudioclient/ToneGenerator.cpp
@@ -811,6 +811,20 @@
{ .duration = 0 , .waveFreq = { 0 }, 0, 0}},
.repeatCnt = ToneGenerator::TONEGEN_INF,
.repeatSegment = 0 }, // TONE_HK_RINGTONE
+ { .segments = { { .duration = 400, .waveFreq = { 400, 450, 0 }, 0, 0 },
+ { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+ { .duration = 400, .waveFreq = { 400, 450, 0 }, 0, 0 },
+ { .duration = 2000, .waveFreq = { 0 }, 0, 0},
+ { .duration = 0, .waveFreq = { 0 }, 0, 0}},
+ .repeatCnt = ToneGenerator::TONEGEN_INF,
+ .repeatSegment = 0 }, // TONE_IE_RINGTONE
+ { .segments = { { .duration = 180, .waveFreq = { 425, 0 }, 0, 0 },
+ { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+ { .duration = 200, .waveFreq = { 425, 0 }, 0, 0 },
+ { .duration = 4500, .waveFreq = { 0 }, 0, 0 },
+ { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+ .repeatCnt = ToneGenerator::TONEGEN_INF,
+ .repeatSegment = 0 }, // TONE_IE_CALL_WAITING
};
// Used by ToneGenerator::getToneForRegion() to convert user specified supervisory tone type
@@ -875,6 +889,16 @@
TONE_SUP_ERROR, // TONE_SUP_ERROR
TONE_SUP_CALL_WAITING, // TONE_SUP_CALL_WAITING
TONE_HK_RINGTONE // TONE_SUP_RINGTONE
+ },
+ { // IRELAND
+ TONE_SUP_DIAL, // TONE_SUP_DIAL
+ TONE_SUP_BUSY, // TONE_SUP_BUSY
+ TONE_SUP_CONGESTION, // TONE_SUP_CONGESTION
+ TONE_SUP_RADIO_ACK, // TONE_SUP_RADIO_ACK
+ TONE_SUP_RADIO_NOTAVAIL, // TONE_SUP_RADIO_NOTAVAIL
+ TONE_SUP_ERROR, // TONE_SUP_ERROR
+ TONE_IE_CALL_WAITING, // TONE_SUP_CALL_WAITING
+ TONE_IE_RINGTONE // TONE_SUP_RINGTONE
}
};
@@ -944,6 +968,8 @@
mRegion = SINGAPORE;
} else if (strstr(value, "hk") != NULL) {
mRegion = HONGKONG;
+ } else if (strstr(value, "ie") != NULL) {
+ mRegion = IRELAND;
} else {
mRegion = CEPT;
}
diff --git a/media/libaudioclient/include/media/ToneGenerator.h b/media/libaudioclient/include/media/ToneGenerator.h
index 97bc825..247703f 100644
--- a/media/libaudioclient/include/media/ToneGenerator.h
+++ b/media/libaudioclient/include/media/ToneGenerator.h
@@ -209,6 +209,9 @@
// HONG KONG Supervisory tones
TONE_HK_BUSY, // Busy tone: 480 Hz + 620 Hz, 500ms ON, 500ms OFF...
TONE_HK_RINGTONE, // Ring Tone: 440 Hz + 480 Hz repeated with pattern 0,4s on, 0,2s off, 0,4s on and 3s off.
+ // IRELAND Supervisory tones
+ TONE_IE_RINGTONE, // Ring Tone: A 400Hz + 450Hz tone repeated in a 0.4s on, 0.2s off, 0.4s on, 2.0s off pattern.
+ TONE_IE_CALL_WAITING, // Call waiting tone: 425Hz tone repeated in a 0.18s on, 0.2s off, 0.2s on, 4.5s off pattern.
NUM_ALTERNATE_TONES
};
@@ -219,6 +222,7 @@
AUSTRALIA,
SINGAPORE,
HONGKONG,
+ IRELAND,
CEPT,
NUM_REGIONS
};
diff --git a/media/libaudiohal/HalDeathHandlerHidl.cpp b/media/libaudiohal/HalDeathHandlerHidl.cpp
index a742671..1e3ab58 100644
--- a/media/libaudiohal/HalDeathHandlerHidl.cpp
+++ b/media/libaudiohal/HalDeathHandlerHidl.cpp
@@ -48,12 +48,13 @@
void HalDeathHandler::serviceDied(uint64_t /*cookie*/, const wp<IBase>& /*who*/) {
// No matter which of the service objects has died,
- // we need to run all the registered handlers and crash our process.
+ // we need to run all the registered handlers and exit.
std::lock_guard<std::mutex> guard(mHandlersLock);
for (const auto& handler : mHandlers) {
handler.second();
}
- LOG_ALWAYS_FATAL("HAL server crashed, need to restart");
+ ALOGE("HAL server crashed, audio server is restarting");
+ exit(1);
}
} // namespace android
diff --git a/media/libaudioprocessing/AudioMixer.cpp b/media/libaudioprocessing/AudioMixer.cpp
index 238925d..3e72c89 100644
--- a/media/libaudioprocessing/AudioMixer.cpp
+++ b/media/libaudioprocessing/AudioMixer.cpp
@@ -813,7 +813,7 @@
mMixerInFormat, sampleRate, playbackRate);
reconfigureBufferProviders();
} else {
- reinterpret_cast<TimestretchBufferProvider*>(mTimestretchBufferProvider)
+ static_cast<TimestretchBufferProvider*>(mTimestretchBufferProvider)
->setPlaybackRate(playbackRate);
}
return true;
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 1f4bd0a..1381d27 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -45,7 +45,9 @@
"aidl/android/IOMXBufferSource.aidl",
"IMediaCodecList.cpp",
+ "IMediaCodecService.cpp",
"IOMX.cpp",
+ "IOMXStore.cpp",
"MediaCodecBuffer.cpp",
"MediaCodecInfo.cpp",
"OMXBuffer.cpp",
diff --git a/media/libmedia/IMediaCodecService.cpp b/media/libmedia/IMediaCodecService.cpp
new file mode 100644
index 0000000..adfa93d
--- /dev/null
+++ b/media/libmedia/IMediaCodecService.cpp
@@ -0,0 +1,86 @@
+/*
+**
+** Copyright 2015, The Android Open Source Project
+**
+** 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.
+*/
+
+#define LOG_TAG "IMediaCodecService"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/Parcel.h>
+#include <media/IMediaCodecService.h>
+
+namespace android {
+
+enum {
+ GET_OMX = IBinder::FIRST_CALL_TRANSACTION,
+ GET_OMX_STORE
+};
+
+class BpMediaCodecService : public BpInterface<IMediaCodecService>
+{
+public:
+ explicit BpMediaCodecService(const sp<IBinder>& impl)
+ : BpInterface<IMediaCodecService>(impl)
+ {
+ }
+
+ virtual sp<IOMX> getOMX() {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaCodecService::getInterfaceDescriptor());
+ remote()->transact(GET_OMX, data, &reply);
+ return interface_cast<IOMX>(reply.readStrongBinder());
+ }
+
+ virtual sp<IOMXStore> getOMXStore() {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaCodecService::getInterfaceDescriptor());
+ remote()->transact(GET_OMX_STORE, data, &reply);
+ return interface_cast<IOMXStore>(reply.readStrongBinder());
+ }
+
+};
+
+IMPLEMENT_META_INTERFACE(MediaCodecService, "android.media.IMediaCodecService");
+
+// ----------------------------------------------------------------------
+
+status_t BnMediaCodecService::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch (code) {
+
+ case GET_OMX: {
+ CHECK_INTERFACE(IMediaCodecService, data, reply);
+ sp<IOMX> omx = getOMX();
+ reply->writeStrongBinder(IInterface::asBinder(omx));
+ return NO_ERROR;
+ }
+ case GET_OMX_STORE: {
+ CHECK_INTERFACE(IMediaCodecService, data, reply);
+ sp<IOMXStore> omxStore = getOMXStore();
+ reply->writeStrongBinder(IInterface::asBinder(omxStore));
+ return NO_ERROR;
+ }
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+} // namespace android
diff --git a/media/libmedia/IOMXStore.cpp b/media/libmedia/IOMXStore.cpp
new file mode 100644
index 0000000..4948f1a
--- /dev/null
+++ b/media/libmedia/IOMXStore.cpp
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2009 The Android Open Source Project
+ *
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "IOMXStore"
+
+#include <utils/Log.h>
+
+#include <media/IOMX.h>
+#include <media/IOMXStore.h>
+#include <android/hardware/media/omx/1.0/IOmxStore.h>
+
+#include <binder/IInterface.h>
+#include <binder/IBinder.h>
+#include <binder/Parcel.h>
+
+#include <vector>
+#include <string>
+
+namespace android {
+
+namespace {
+
+enum {
+ CONNECT = IBinder::FIRST_CALL_TRANSACTION,
+ LIST_SERVICE_ATTRIBUTES,
+ GET_NODE_PREFIX,
+ LIST_ROLES,
+ GET_OMX,
+};
+
+// Forward declarations of std::vector<T> <-> Parcel conversion funcitons that
+// depend on writeToParcel() and readToParcel() for T <-> Parcel.
+
+template <typename T>
+status_t writeToParcel(const std::vector<T>& v, Parcel* p);
+
+template <typename T>
+status_t readFromParcel(std::vector<T>* v, const Parcel& p);
+
+// std::string <-> Parcel
+
+status_t writeToParcel(const std::string& s, Parcel* p) {
+ if (s.size() > INT32_MAX) {
+ return BAD_VALUE;
+ }
+ return p->writeByteArray(
+ s.size(), reinterpret_cast<const uint8_t*>(s.c_str()));
+}
+
+status_t readFromParcel(std::string* s, const Parcel& p) {
+ int32_t len;
+ status_t status = p.readInt32(&len);
+ if (status != NO_ERROR) {
+ return status;
+ } else if ((len < 0) || (static_cast<uint64_t>(len) > SIZE_MAX)) {
+ return BAD_VALUE;
+ }
+ s->resize(len);
+ if (len == 0) {
+ return NO_ERROR;
+ }
+ return p.read(static_cast<void*>(&s->front()), static_cast<size_t>(len));
+}
+
+// IOMXStore::Attribute <-> Parcel
+
+status_t writeToParcel(const IOMXStore::Attribute& a, Parcel* p) {
+ status_t status = writeToParcel(a.key, p);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return writeToParcel(a.value, p);
+}
+
+status_t readFromParcel(IOMXStore::Attribute* a, const Parcel& p) {
+ status_t status = readFromParcel(&(a->key), p);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return readFromParcel(&(a->value), p);
+}
+
+// IOMXStore::NodeInfo <-> Parcel
+
+status_t writeToParcel(const IOMXStore::NodeInfo& n, Parcel* p) {
+ status_t status = writeToParcel(n.name, p);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = writeToParcel(n.owner, p);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return writeToParcel(n.attributes, p);
+}
+
+status_t readFromParcel(IOMXStore::NodeInfo* n, const Parcel& p) {
+ status_t status = readFromParcel(&(n->name), p);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = readFromParcel(&(n->owner), p);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return readFromParcel(&(n->attributes), p);
+}
+
+// IOMXStore::RoleInfo <-> Parcel
+
+status_t writeToParcel(const IOMXStore::RoleInfo& r, Parcel* p) {
+ status_t status = writeToParcel(r.role, p);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = writeToParcel(r.type, p);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = p->writeBool(r.isEncoder);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = p->writeBool(r.preferPlatformNodes);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return writeToParcel(r.nodes, p);
+}
+
+status_t readFromParcel(IOMXStore::RoleInfo* r, const Parcel& p) {
+ status_t status = readFromParcel(&(r->role), p);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = readFromParcel(&(r->type), p);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = p.readBool(&(r->isEncoder));
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = p.readBool(&(r->preferPlatformNodes));
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return readFromParcel(&(r->nodes), p);
+}
+
+// std::vector<NodeInfo> <-> Parcel
+// std::vector<RoleInfo> <-> Parcel
+
+template <typename T>
+status_t writeToParcel(const std::vector<T>& v, Parcel* p) {
+ status_t status = p->writeVectorSize(v);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ for (const T& x : v) {
+ status = writeToParcel(x, p);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ }
+ return NO_ERROR;
+}
+
+template <typename T>
+status_t readFromParcel(std::vector<T>* v, const Parcel& p) {
+ status_t status = p.resizeOutVector(v);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ for (T& x : *v) {
+ status = readFromParcel(&x, p);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ }
+ return NO_ERROR;
+}
+
+} // unnamed namespace
+
+////////////////////////////////////////////////////////////////////////////////
+
+class BpOMXStore : public BpInterface<IOMXStore> {
+public:
+ explicit BpOMXStore(const sp<IBinder> &impl)
+ : BpInterface<IOMXStore>(impl) {
+ }
+
+ status_t listServiceAttributes(
+ std::vector<Attribute>* attributes) override {
+ Parcel data, reply;
+ status_t status;
+ status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = remote()->transact(LIST_SERVICE_ATTRIBUTES, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return readFromParcel(attributes, reply);
+ }
+
+ status_t getNodePrefix(std::string* prefix) override {
+ Parcel data, reply;
+ status_t status;
+ status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = remote()->transact(GET_NODE_PREFIX, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return readFromParcel(prefix, reply);
+ }
+
+ status_t listRoles(std::vector<RoleInfo>* roleList) override {
+ Parcel data, reply;
+ status_t status;
+ status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = remote()->transact(LIST_ROLES, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return readFromParcel(roleList, reply);
+ }
+
+ status_t getOmx(const std::string& name, sp<IOMX>* omx) override {
+ Parcel data, reply;
+ status_t status;
+ status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = writeToParcel(name, &data);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = remote()->transact(GET_OMX, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return reply.readStrongBinder(omx);
+ }
+
+};
+
+IMPLEMENT_META_INTERFACE(OMXStore, "android.hardware.IOMXStore");
+
+////////////////////////////////////////////////////////////////////////////////
+
+#define CHECK_OMX_INTERFACE(interface, data, reply) \
+ do { if (!(data).enforceInterface(interface::getInterfaceDescriptor())) { \
+ ALOGW("Call incorrectly routed to " #interface); \
+ return PERMISSION_DENIED; \
+ } } while (0)
+
+status_t BnOMXStore::onTransact(
+ uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
+ switch (code) {
+ case LIST_SERVICE_ATTRIBUTES: {
+ CHECK_OMX_INTERFACE(IOMXStore, data, reply);
+ status_t status;
+ std::vector<Attribute> attributes;
+
+ status = listServiceAttributes(&attributes);
+ if (status != NO_ERROR) {
+ ALOGE("listServiceAttributes() fails with status %d",
+ static_cast<int>(status));
+ return NO_ERROR;
+ }
+ status = writeToParcel(attributes, reply);
+ if (status != NO_ERROR) {
+ ALOGE("listServiceAttributes() fails to send reply");
+ return NO_ERROR;
+ }
+ return NO_ERROR;
+ }
+ case GET_NODE_PREFIX: {
+ CHECK_OMX_INTERFACE(IOMXStore, data, reply);
+ status_t status;
+ std::string prefix;
+
+ status = getNodePrefix(&prefix);
+ if (status != NO_ERROR) {
+ ALOGE("getNodePrefix() fails with status %d",
+ static_cast<int>(status));
+ return NO_ERROR;
+ }
+ status = writeToParcel(prefix, reply);
+ if (status != NO_ERROR) {
+ ALOGE("getNodePrefix() fails to send reply");
+ return NO_ERROR;
+ }
+ return NO_ERROR;
+ }
+ case LIST_ROLES: {
+ CHECK_OMX_INTERFACE(IOMXStore, data, reply);
+ status_t status;
+ std::vector<RoleInfo> roleList;
+
+ status = listRoles(&roleList);
+ if (status != NO_ERROR) {
+ ALOGE("listRoles() fails with status %d",
+ static_cast<int>(status));
+ return NO_ERROR;
+ }
+ status = writeToParcel(roleList, reply);
+ if (status != NO_ERROR) {
+ ALOGE("listRoles() fails to send reply");
+ return NO_ERROR;
+ }
+ return NO_ERROR;
+ }
+ case GET_OMX: {
+ CHECK_OMX_INTERFACE(IOMXStore, data, reply);
+ status_t status;
+ std::string name;
+ sp<IOMX> omx;
+
+ status = readFromParcel(&name, data);
+ if (status != NO_ERROR) {
+ ALOGE("getOmx() fails to retrieve name");
+ return NO_ERROR;
+ }
+ status = getOmx(name, &omx);
+ if (status != NO_ERROR) {
+ ALOGE("getOmx() fails with status %d",
+ static_cast<int>(status));
+ return NO_ERROR;
+ }
+ status = reply->writeStrongBinder(IInterface::asBinder(omx));
+ if (status != NO_ERROR) {
+ ALOGE("getOmx() fails to send reply");
+ return NO_ERROR;
+ }
+ return NO_ERROR;
+ }
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+} // namespace android
diff --git a/media/libmedia/include/media/IMediaCodecService.h b/media/libmedia/include/media/IMediaCodecService.h
new file mode 100644
index 0000000..59fb1c0
--- /dev/null
+++ b/media/libmedia/include/media/IMediaCodecService.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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 ANDROID_IMEDIACODECSERVICE_H
+#define ANDROID_IMEDIACODECSERVICE_H
+
+#include <binder/IInterface.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <media/IDataSource.h>
+#include <media/IOMX.h>
+#include <media/IOMXStore.h>
+
+namespace android {
+
+class IMediaCodecService: public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(MediaCodecService);
+
+ virtual sp<IOMX> getOMX() = 0;
+ virtual sp<IOMXStore> getOMXStore() = 0;
+};
+
+class BnMediaCodecService: public BnInterface<IMediaCodecService>
+{
+public:
+ virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags = 0);
+};
+
+} // namespace android
+
+#endif // ANDROID_IMEDIACODECSERVICE_H
diff --git a/media/libmedia/include/media/IOMXStore.h b/media/libmedia/include/media/IOMXStore.h
new file mode 100644
index 0000000..628db70
--- /dev/null
+++ b/media/libmedia/include/media/IOMXStore.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 ANDROID_IOMXSTORE_H_
+
+#define ANDROID_IOMXSTORE_H_
+
+#include <media/IOMX.h>
+#include <android/hardware/media/omx/1.0/IOmxStore.h>
+
+#include <binder/IInterface.h>
+#include <binder/IBinder.h>
+
+#include <vector>
+#include <string>
+
+namespace android {
+
+using hardware::media::omx::V1_0::IOmxStore;
+
+class IOMXStore : public IInterface {
+public:
+ DECLARE_META_INTERFACE(OMXStore);
+
+ struct Attribute {
+ std::string key;
+ std::string value;
+ };
+
+ struct NodeInfo {
+ std::string name;
+ std::string owner;
+ std::vector<Attribute> attributes;
+ };
+
+ struct RoleInfo {
+ std::string role;
+ std::string type;
+ bool isEncoder;
+ bool preferPlatformNodes;
+ std::vector<NodeInfo> nodes;
+ };
+
+ virtual status_t listServiceAttributes(
+ std::vector<Attribute>* attributes) = 0;
+
+ virtual status_t getNodePrefix(std::string* prefix) = 0;
+
+ virtual status_t listRoles(std::vector<RoleInfo>* roleList) = 0;
+
+ virtual status_t getOmx(const std::string& name, sp<IOMX>* omx) = 0;
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+class BnOMXStore : public BnInterface<IOMXStore> {
+public:
+ virtual status_t onTransact(
+ uint32_t code, const Parcel &data, Parcel *reply,
+ uint32_t flags = 0);
+};
+
+} // namespace android
+
+#endif // ANDROID_IOMX_H_
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 98a47c4..6b2c81d 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -741,14 +741,26 @@
new ServiceDeathNotifier(binder, p, MEDIAEXTRACTOR_PROCESS_DEATH);
binder->linkToDeath(extractorDeathListener);
- sp<IOmx> omx = IOmx::getService();
- if (omx == nullptr) {
- ALOGE("IOmx service is not available");
- return NULL;
+ sp<ServiceDeathNotifier> codecDeathListener;
+ if (property_get_bool("persist.media.treble_omx", true)) {
+ // Treble IOmx
+ sp<IOmx> omx = IOmx::getService();
+ if (omx == nullptr) {
+ ALOGE("Treble IOmx not available");
+ return NULL;
+ }
+ codecDeathListener = new ServiceDeathNotifier(omx, p, MEDIACODEC_PROCESS_DEATH);
+ omx->linkToDeath(codecDeathListener, 0);
+ } else {
+ // Legacy IOMX
+ binder = sm->getService(String16("media.codec"));
+ if (binder == NULL) {
+ ALOGE("codec service not available");
+ return NULL;
+ }
+ codecDeathListener = new ServiceDeathNotifier(binder, p, MEDIACODEC_PROCESS_DEATH);
+ binder->linkToDeath(codecDeathListener);
}
- sp<ServiceDeathNotifier> codecDeathListener =
- new ServiceDeathNotifier(omx, p, MEDIACODEC_PROCESS_DEATH);
- omx->linkToDeath(codecDeathListener, 0);
Mutex::Autolock lock(mLock);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index a423fee..9b9b3bb 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -450,14 +450,27 @@
}
sCameraChecked = true;
- sp<IOmx> omx = IOmx::getService();
- if (omx == nullptr) {
- ALOGE("IOmx service is not available");
- return NO_INIT;
+ if (property_get_bool("persist.media.treble_omx", true)) {
+ // Treble IOmx
+ sp<IOmx> omx = IOmx::getService();
+ if (omx == nullptr) {
+ ALOGE("Treble IOmx not available");
+ return NO_INIT;
+ }
+ mCodecDeathListener = new ServiceDeathNotifier(omx, listener,
+ MediaPlayerService::MEDIACODEC_PROCESS_DEATH);
+ omx->linkToDeath(mCodecDeathListener, 0);
+ } else {
+ // Legacy IOMX
+ binder = sm->getService(String16("media.codec"));
+ if (binder == NULL) {
+ ALOGE("Unable to connect to media codec service");
+ return NO_INIT;
+ }
+ mCodecDeathListener = new ServiceDeathNotifier(binder, listener,
+ MediaPlayerService::MEDIACODEC_PROCESS_DEATH);
+ binder->linkToDeath(mCodecDeathListener);
}
- mCodecDeathListener = new ServiceDeathNotifier(omx, listener,
- MediaPlayerService::MEDIACODEC_PROCESS_DEATH);
- omx->linkToDeath(mCodecDeathListener, 0);
return OK;
}
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index c3127ae..a3f4efb 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -677,6 +677,12 @@
break;
}
+ case kWhatSeek:
+ {
+ onSeek(msg);
+ break;
+ }
+
case kWhatReadBuffer:
{
onReadBuffer(msg);
@@ -1097,8 +1103,39 @@
}
status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
- Mutex::Autolock _l(mLock);
ALOGV("seekTo: %lld, %d", (long long)seekTimeUs, mode);
+ sp<AMessage> msg = new AMessage(kWhatSeek, this);
+ msg->setInt64("seekTimeUs", seekTimeUs);
+ msg->setInt32("mode", mode);
+
+ // Need to call readBuffer on |mLooper| to ensure the calls to
+ // IMediaSource::read* are serialized. Note that IMediaSource::read*
+ // is called without |mLock| acquired and MediaSource is not thread safe.
+ sp<AMessage> response;
+ status_t err = msg->postAndAwaitResponse(&response);
+ if (err == OK && response != NULL) {
+ CHECK(response->findInt32("err", &err));
+ }
+
+ return err;
+}
+
+void NuPlayer::GenericSource::onSeek(const sp<AMessage>& msg) {
+ int64_t seekTimeUs;
+ int32_t mode;
+ CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
+ CHECK(msg->findInt32("mode", &mode));
+
+ sp<AMessage> response = new AMessage;
+ status_t err = doSeek(seekTimeUs, (MediaPlayerSeekMode)mode);
+ response->setInt32("err", err);
+
+ sp<AReplyToken> replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+ response->postReply(replyID);
+}
+
+status_t NuPlayer::GenericSource::doSeek(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
if (mVideoTrack.mSource != NULL) {
++mVideoDataGeneration;
@@ -1321,13 +1358,14 @@
Vector<MediaBuffer *> mediaBuffers;
status_t err = NO_ERROR;
+ sp<IMediaSource> source = track->mSource;
mLock.unlock();
if (couldReadMultiple) {
- err = track->mSource->readMultiple(
+ err = source->readMultiple(
&mediaBuffers, maxBuffers - numBuffers, &options);
} else {
MediaBuffer *mbuf = NULL;
- err = track->mSource->read(&mbuf, &options);
+ err = source->read(&mbuf, &options);
if (err == OK && mbuf != NULL) {
mediaBuffers.push_back(mbuf);
}
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
index 16c0224..cb9c27f 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.h
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -112,6 +112,7 @@
kWhatSendTimedTextData,
kWhatChangeAVSource,
kWhatPollBuffering,
+ kWhatSeek,
kWhatReadBuffer,
kWhatStart,
kWhatResume,
@@ -183,6 +184,9 @@
void finishPrepareAsync();
status_t startSources();
+ void onSeek(const sp<AMessage>& msg);
+ status_t doSeek(int64_t seekTimeUs, MediaPlayerSeekMode mode);
+
void onPrepareAsync();
void fetchTextData(
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index a26d525..6c4b823 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -182,6 +182,7 @@
mAudioDecoderGeneration(0),
mVideoDecoderGeneration(0),
mRendererGeneration(0),
+ mLastStartedPlayingTimeNs(0),
mPreviousSeekTimeUs(0),
mAudioEOS(false),
mVideoEOS(false),
@@ -1309,6 +1310,7 @@
ALOGV("kWhatReset");
mResetting = true;
+ stopPlaybackTimer("kWhatReset");
mDeferredActions.push_back(
new FlushDecoderAction(
@@ -1449,7 +1451,7 @@
ALOGW("resume called when renderer is gone or not set");
}
- mLastStartedPlayingTimeNs = systemTime();
+ startPlaybackTimer("onresume");
}
status_t NuPlayer::onInstantiateSecureDecoders() {
@@ -1569,12 +1571,43 @@
mAudioDecoder->setRenderer(mRenderer);
}
- mLastStartedPlayingTimeNs = systemTime();
+ startPlaybackTimer("onstart");
postScanSources();
}
+void NuPlayer::startPlaybackTimer(const char *where) {
+ Mutex::Autolock autoLock(mPlayingTimeLock);
+ if (mLastStartedPlayingTimeNs == 0) {
+ mLastStartedPlayingTimeNs = systemTime();
+ ALOGV("startPlaybackTimer() time %20" PRId64 " (%s)", mLastStartedPlayingTimeNs, where);
+ }
+}
+
+void NuPlayer::stopPlaybackTimer(const char *where) {
+ Mutex::Autolock autoLock(mPlayingTimeLock);
+
+ ALOGV("stopPlaybackTimer() time %20" PRId64 " (%s)", mLastStartedPlayingTimeNs, where);
+
+ if (mLastStartedPlayingTimeNs != 0) {
+ sp<NuPlayerDriver> driver = mDriver.promote();
+ if (driver != NULL) {
+ int64_t now = systemTime();
+ int64_t played = now - mLastStartedPlayingTimeNs;
+ ALOGV("stopPlaybackTimer() log %20" PRId64 "", played);
+
+ if (played > 0) {
+ driver->notifyMorePlayingTimeUs((played+500)/1000);
+ }
+ }
+ mLastStartedPlayingTimeNs = 0;
+ }
+}
+
void NuPlayer::onPause() {
+
+ stopPlaybackTimer("onPause");
+
if (mPaused) {
return;
}
@@ -1590,13 +1623,6 @@
ALOGW("pause called when renderer is gone or not set");
}
- sp<NuPlayerDriver> driver = mDriver.promote();
- if (driver != NULL) {
- int64_t now = systemTime();
- int64_t played = now - mLastStartedPlayingTimeNs;
-
- driver->notifyMorePlayingTimeUs((played+500)/1000);
- }
}
bool NuPlayer::audioDecoderStillNeeded() {
@@ -2223,6 +2249,8 @@
CHECK(mAudioDecoder == NULL);
CHECK(mVideoDecoder == NULL);
+ stopPlaybackTimer("performReset");
+
cancelPollDuration();
++mScanSourcesGeneration;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 747dc47..492b8d4 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -178,7 +178,10 @@
int32_t mVideoDecoderGeneration;
int32_t mRendererGeneration;
+ Mutex mPlayingTimeLock;
int64_t mLastStartedPlayingTimeNs;
+ void stopPlaybackTimer(const char *where);
+ void startPlaybackTimer(const char *where);
int64_t mPreviousSeekTimeUs;
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index d9fdfe3..a7a1b05 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -28,6 +28,8 @@
#include <media/stagefright/ACodec.h>
+#include <binder/MemoryDealer.h>
+
#include <media/stagefright/foundation/avc_utils.h>
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/foundation/ABuffer.h>
@@ -573,6 +575,8 @@
memset(&mLastNativeWindowCrop, 0, sizeof(mLastNativeWindowCrop));
changeState(mUninitializedState);
+
+ mTrebleFlag = false;
}
ACodec::~ACodec() {
@@ -824,7 +828,11 @@
status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
- CHECK(mAllocator[portIndex] == NULL);
+ if (getTrebleFlag()) {
+ CHECK(mAllocator[portIndex] == NULL);
+ } else {
+ CHECK(mDealer[portIndex] == NULL);
+ }
CHECK(mBuffers[portIndex].isEmpty());
status_t err;
@@ -866,10 +874,7 @@
}
}
- size_t alignment = 32; // This is the value currently returned by
- // MemoryDealer::getAllocationAlignment().
- // TODO: Fix this when Treble has
- // MemoryHeap/MemoryDealer.
+ size_t alignment = MemoryDealer::getAllocationAlignment();
ALOGV("[%s] Allocating %u buffers of size %zu (from %u using %s) on %s port",
mComponentName.c_str(),
@@ -891,15 +896,18 @@
}
if (mode != IOMX::kPortModePresetSecureBuffer) {
- mAllocator[portIndex] = TAllocator::getService("ashmem");
- if (mAllocator[portIndex] == nullptr) {
- ALOGE("hidl allocator on port %d is null",
- (int)portIndex);
- return NO_MEMORY;
+ if (getTrebleFlag()) {
+ mAllocator[portIndex] = TAllocator::getService("ashmem");
+ if (mAllocator[portIndex] == nullptr) {
+ ALOGE("hidl allocator on port %d is null",
+ (int)portIndex);
+ return NO_MEMORY;
+ }
+ } else {
+ size_t totalSize = def.nBufferCountActual *
+ (alignedSize + alignedConvSize);
+ mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
}
- // TODO: When Treble has MemoryHeap/MemoryDealer, we should
- // specify the heap size to be
- // def.nBufferCountActual * (alignedSize + alignedConvSize).
}
const sp<AMessage> &format =
@@ -928,55 +936,23 @@
: new SecureBuffer(format, native_handle, bufSize);
info.mCodecData = info.mData;
} else {
- bool success;
- auto transStatus = mAllocator[portIndex]->allocate(
- bufSize,
- [&success, &hidlMemToken](
- bool s,
- hidl_memory const& m) {
- success = s;
- hidlMemToken = m;
- });
-
- if (!transStatus.isOk()) {
- ALOGE("hidl's AshmemAllocator failed at the "
- "transport: %s",
- transStatus.description().c_str());
- return NO_MEMORY;
- }
- if (!success) {
- return NO_MEMORY;
- }
- hidlMem = mapMemory(hidlMemToken);
- if (hidlMem == nullptr) {
- return NO_MEMORY;
- }
- err = mOMXNode->useBuffer(
- portIndex, hidlMemToken, &info.mBufferID);
-
- if (mode == IOMX::kPortModeDynamicANWBuffer) {
- VideoNativeMetadata* metaData = (VideoNativeMetadata*)(
- (void*)hidlMem->getPointer());
- metaData->nFenceFd = -1;
- }
-
- info.mCodecData = new SharedMemoryBuffer(
- format, hidlMem);
- info.mCodecRef = hidlMem;
-
- // if we require conversion, allocate conversion buffer for client use;
- // otherwise, reuse codec buffer
- if (mConverter[portIndex] != NULL) {
- CHECK_GT(conversionBufferSize, (size_t)0);
+ if (getTrebleFlag()) {
bool success;
- mAllocator[portIndex]->allocate(
- conversionBufferSize,
+ auto transStatus = mAllocator[portIndex]->allocate(
+ bufSize,
[&success, &hidlMemToken](
bool s,
hidl_memory const& m) {
success = s;
hidlMemToken = m;
});
+
+ if (!transStatus.isOk()) {
+ ALOGE("hidl's AshmemAllocator failed at the "
+ "transport: %s",
+ transStatus.description().c_str());
+ return NO_MEMORY;
+ }
if (!success) {
return NO_MEMORY;
}
@@ -984,8 +960,67 @@
if (hidlMem == nullptr) {
return NO_MEMORY;
}
- info.mData = new SharedMemoryBuffer(format, hidlMem);
- info.mMemRef = hidlMem;
+ err = mOMXNode->useBuffer(
+ portIndex, hidlMemToken, &info.mBufferID);
+ } else {
+ mem = mDealer[portIndex]->allocate(bufSize);
+ if (mem == NULL || mem->pointer() == NULL) {
+ return NO_MEMORY;
+ }
+
+ err = mOMXNode->useBuffer(
+ portIndex, mem, &info.mBufferID);
+ }
+
+ if (mode == IOMX::kPortModeDynamicANWBuffer) {
+ VideoNativeMetadata* metaData = (VideoNativeMetadata*)(
+ getTrebleFlag() ?
+ (void*)hidlMem->getPointer() : mem->pointer());
+ metaData->nFenceFd = -1;
+ }
+
+ if (getTrebleFlag()) {
+ info.mCodecData = new SharedMemoryBuffer(
+ format, hidlMem);
+ info.mCodecRef = hidlMem;
+ } else {
+ info.mCodecData = new SharedMemoryBuffer(
+ format, mem);
+ info.mCodecRef = mem;
+ }
+
+ // if we require conversion, allocate conversion buffer for client use;
+ // otherwise, reuse codec buffer
+ if (mConverter[portIndex] != NULL) {
+ CHECK_GT(conversionBufferSize, (size_t)0);
+ if (getTrebleFlag()) {
+ bool success;
+ mAllocator[portIndex]->allocate(
+ conversionBufferSize,
+ [&success, &hidlMemToken](
+ bool s,
+ hidl_memory const& m) {
+ success = s;
+ hidlMemToken = m;
+ });
+ if (!success) {
+ return NO_MEMORY;
+ }
+ hidlMem = mapMemory(hidlMemToken);
+ if (hidlMem == nullptr) {
+ return NO_MEMORY;
+ }
+ info.mData = new SharedMemoryBuffer(format, hidlMem);
+ info.mMemRef = hidlMem;
+ } else {
+ mem = mDealer[portIndex]->allocate(
+ conversionBufferSize);
+ if (mem == NULL|| mem->pointer() == NULL) {
+ return NO_MEMORY;
+ }
+ info.mData = new SharedMemoryBuffer(format, mem);
+ info.mMemRef = mem;
+ }
} else {
info.mData = info.mCodecData;
info.mMemRef = info.mCodecRef;
@@ -1546,7 +1581,11 @@
}
}
- mAllocator[portIndex].clear();
+ if (getTrebleFlag()) {
+ mAllocator[portIndex].clear();
+ } else {
+ mDealer[portIndex].clear();
+ }
return err;
}
@@ -6212,8 +6251,13 @@
if (mDeathNotifier != NULL) {
if (mCodec->mOMXNode != NULL) {
- auto tOmxNode = mCodec->mOMXNode->getHalInterface();
- tOmxNode->unlinkToDeath(mDeathNotifier);
+ if (mCodec->getTrebleFlag()) {
+ auto tOmxNode = mCodec->mOMXNode->getHalInterface();
+ tOmxNode->unlinkToDeath(mDeathNotifier);
+ } else {
+ sp<IBinder> binder = IInterface::asBinder(mCodec->mOMXNode);
+ binder->unlinkToDeath(mDeathNotifier);
+ }
}
mDeathNotifier.clear();
}
@@ -6361,7 +6405,8 @@
componentName = matchingCodecs[matchIndex];
OMXClient client;
- if (client.connect(owners[matchIndex].c_str()) != OK) {
+ bool trebleFlag;
+ if (client.connect(owners[matchIndex].c_str(), &trebleFlag) != OK) {
mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
return false;
}
@@ -6374,6 +6419,7 @@
androidSetThreadPriority(tid, prevPriority);
if (err == OK) {
+ mCodec->setTrebleFlag(trebleFlag);
break;
} else {
ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
@@ -6395,9 +6441,17 @@
}
mDeathNotifier = new DeathNotifier(notify);
- auto tOmxNode = omxNode->getHalInterface();
- if (!tOmxNode->linkToDeath(mDeathNotifier, 0)) {
- mDeathNotifier.clear();
+ if (mCodec->getTrebleFlag()) {
+ auto tOmxNode = omxNode->getHalInterface();
+ if (!tOmxNode->linkToDeath(mDeathNotifier, 0)) {
+ mDeathNotifier.clear();
+ }
+ } else {
+ if (IInterface::asBinder(omxNode)->linkToDeath(mDeathNotifier) != OK) {
+ // This was a local binder, if it dies so do we, we won't care
+ // about any notifications in the afterlife.
+ mDeathNotifier.clear();
+ }
}
notify = new AMessage(kWhatOMXMessageList, mCodec);
@@ -7804,7 +7858,11 @@
mCodec->mBuffers[kPortIndexOutput].size());
err = FAILED_TRANSACTION;
} else {
- mCodec->mAllocator[kPortIndexOutput].clear();
+ if (mCodec->getTrebleFlag()) {
+ mCodec->mAllocator[kPortIndexOutput].clear();
+ } else {
+ mCodec->mDealer[kPortIndexOutput].clear();
+ }
}
if (err == OK) {
@@ -8406,4 +8464,12 @@
return OK;
}
+void ACodec::setTrebleFlag(bool trebleFlag) {
+ mTrebleFlag = trebleFlag;
+}
+
+bool ACodec::getTrebleFlag() const {
+ return mTrebleFlag;
+}
+
} // namespace android
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 54265a4..4feba37 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -24,6 +24,7 @@
#include <media/IMediaCodecList.h>
#include <media/IMediaPlayerService.h>
+#include <media/IMediaCodecService.h>
#include <media/MediaCodecInfo.h>
#include <media/stagefright/foundation/ADebug.h>
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index cd07262..5f50e46 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -25,6 +25,7 @@
#include <cutils/properties.h>
#include <binder/IServiceManager.h>
+#include <media/IMediaCodecService.h>
#include <media/stagefright/OMXClient.h>
#include <media/IOMX.h>
@@ -36,22 +37,71 @@
OMXClient::OMXClient() {
}
-status_t OMXClient::connect(const char* name) {
+status_t OMXClient::connect() {
+ return connect("default", nullptr);
+}
+
+status_t OMXClient::connect(bool* trebleFlag) {
+ if (property_get_bool("persist.media.treble_omx", true)) {
+ if (trebleFlag != nullptr) {
+ *trebleFlag = true;
+ }
+ return connectTreble();
+ }
+ if (trebleFlag != nullptr) {
+ *trebleFlag = false;
+ }
+ return connectLegacy();
+}
+
+status_t OMXClient::connect(const char* name, bool* trebleFlag) {
+ if (property_get_bool("persist.media.treble_omx", true)) {
+ if (trebleFlag != nullptr) {
+ *trebleFlag = true;
+ }
+ return connectTreble(name);
+ }
+ if (trebleFlag != nullptr) {
+ *trebleFlag = false;
+ }
+ return connectLegacy();
+}
+
+status_t OMXClient::connectLegacy() {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> codecbinder = sm->getService(String16("media.codec"));
+ sp<IMediaCodecService> codecservice = interface_cast<IMediaCodecService>(codecbinder);
+
+ if (codecservice.get() == NULL) {
+ ALOGE("Cannot obtain IMediaCodecService");
+ return NO_INIT;
+ }
+
+ mOMX = codecservice->getOMX();
+ if (mOMX.get() == NULL) {
+ ALOGE("Cannot obtain mediacodec IOMX");
+ return NO_INIT;
+ }
+
+ return OK;
+}
+
+status_t OMXClient::connectTreble(const char* name) {
using namespace ::android::hardware::media::omx::V1_0;
if (name == nullptr) {
name = "default";
}
sp<IOmx> tOmx = IOmx::getService(name);
if (tOmx.get() == nullptr) {
- ALOGE("Cannot obtain IOmx service.");
+ ALOGE("Cannot obtain Treble IOmx.");
return NO_INIT;
}
if (!tOmx->isRemote()) {
- ALOGE("IOmx service running in passthrough mode.");
+ ALOGE("Treble IOmx is in passthrough mode.");
return NO_INIT;
}
mOMX = new utils::LWOmx(tOmx);
- ALOGI("IOmx service obtained");
+ ALOGI("Treble IOmx obtained");
return OK;
}
@@ -59,8 +109,4 @@
mOMX.clear();
}
-sp<IOMX> OMXClient::interface() {
- return mOMX;
-}
-
} // namespace android
diff --git a/media/libstagefright/OmxInfoBuilder.cpp b/media/libstagefright/OmxInfoBuilder.cpp
index c174371..063d13e 100644
--- a/media/libstagefright/OmxInfoBuilder.cpp
+++ b/media/libstagefright/OmxInfoBuilder.cpp
@@ -24,6 +24,8 @@
#include <utils/Log.h>
#include <cutils/properties.h>
+#include <binder/IServiceManager.h>
+#include <media/IMediaCodecService.h>
#include <media/stagefright/foundation/MediaDefs.h>
#include <media/stagefright/OmxInfoBuilder.h>
#include <media/stagefright/ACodec.h>
@@ -33,6 +35,7 @@
#include <android/hardware/media/omx/1.0/IOmxNode.h>
#include <media/stagefright/omx/OMXUtils.h>
+#include <media/IOMXStore.h>
#include <media/IOMX.h>
#include <media/omx/1.0/WOmx.h>
@@ -45,18 +48,10 @@
namespace android {
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using namespace ::android::hardware::media::omx::V1_0;
-
namespace /* unnamed */ {
-bool hasPrefix(const hidl_string& s, const char* prefix) {
- return strncmp(s.c_str(), prefix, strlen(prefix)) == 0;
-}
-
status_t queryCapabilities(
- const IOmxStore::NodeInfo& node, const char* mime, bool isEncoder,
+ const IOMXStore::NodeInfo& node, const char* mime, bool isEncoder,
MediaCodecInfo::CapabilitiesWriter* caps) {
sp<ACodec> codec = new ACodec();
status_t err = codec->queryCapabilities(
@@ -67,13 +62,14 @@
for (const auto& attribute : node.attributes) {
// All features have an int32 value except
// "feature-bitrate-modes", which has a string value.
- if (hasPrefix(attribute.key, "feature-") &&
- !hasPrefix(attribute.key, "feature-bitrate-modes")) {
- // If this attribute.key is a feature that is not bitrate modes,
- // add an int32 value.
+ if ((attribute.key.compare(0, 8, "feature-") == 0) &&
+ (attribute.key.compare(8, 15, "bitrate-modes")
+ != 0)) {
+ // If this attribute.key is a feature that is not a bitrate
+ // control, add an int32 value.
caps->addDetail(
attribute.key.c_str(),
- hasPrefix(attribute.value, "1") ? 1 : 0);
+ attribute.value == "1" ? 1 : 0);
} else {
// Non-feature attributes
caps->addDetail(
@@ -89,53 +85,138 @@
}
status_t OmxInfoBuilder::buildMediaCodecList(MediaCodecListWriter* writer) {
- hidl_vec<IOmxStore::RoleInfo> roles;
+ bool treble;
+ sp<IOMX> omx;
+ std::vector<IOMXStore::RoleInfo> roles;
- // Obtain IOmxStore
- sp<IOmxStore> omxStore = IOmxStore::getService();
- if (omxStore == nullptr) {
- ALOGE("Cannot find an IOmxStore service.");
- return NO_INIT;
- }
+ treble = property_get_bool("persist.media.treble_omx", true);
+ if (treble) {
+ using namespace ::android::hardware::media::omx::V1_0;
+ using ::android::hardware::hidl_vec;
+ using ::android::hardware::hidl_string;
- // List service attributes (global settings)
- Status status;
- hidl_vec<IOmxStore::ServiceAttribute> serviceAttributes;
- auto transStatus = omxStore->listServiceAttributes(
- [&status, &serviceAttributes] (
- Status inStatus,
- const hidl_vec<IOmxStore::ServiceAttribute>& inAttributes) {
- status = inStatus;
- serviceAttributes = inAttributes;
- });
- if (!transStatus.isOk()) {
- ALOGE("Fail to obtain global settings from IOmxStore.");
- return NO_INIT;
- }
- if (status != Status::OK) {
- ALOGE("IOmxStore reports parsing error.");
- return NO_INIT;
- }
- for (const auto& p : serviceAttributes) {
- writer->addGlobalSetting(
- p.key.c_str(), p.value.c_str());
- }
+ // Obtain IOmxStore
+ sp<IOmxStore> omxStore = IOmxStore::getService();
+ if (omxStore == nullptr) {
+ ALOGE("Cannot connect to an IOmxStore instance.");
+ return NO_INIT;
+ }
- transStatus = omxStore->listRoles(
- [&roles] (
- const hidl_vec<IOmxStore::RoleInfo>& inRoleList) {
- roles = inRoleList;
- });
- if (!transStatus.isOk()) {
- ALOGE("Fail to obtain codec roles from IOmxStore.");
- return NO_INIT;
+ // List service attributes (global settings)
+ Status status;
+ hidl_vec<IOmxStore::ServiceAttribute> serviceAttributes;
+ auto transStatus = omxStore->listServiceAttributes(
+ [&status, &serviceAttributes]
+ (Status inStatus, const hidl_vec<IOmxStore::ServiceAttribute>&
+ inAttributes) {
+ status = inStatus;
+ serviceAttributes = inAttributes;
+ });
+ if (!transStatus.isOk()) {
+ ALOGE("Fail to obtain global settings from IOmxStore.");
+ return NO_INIT;
+ }
+ if (status != Status::OK) {
+ ALOGE("IOmxStore reports parsing error.");
+ return NO_INIT;
+ }
+ for (const auto& p : serviceAttributes) {
+ writer->addGlobalSetting(
+ p.key.c_str(), p.value.c_str());
+ }
+
+ // List roles and convert to IOMXStore's format
+ transStatus = omxStore->listRoles(
+ [&roles]
+ (const hidl_vec<IOmxStore::RoleInfo>& inRoleList) {
+ roles.reserve(inRoleList.size());
+ for (const auto& inRole : inRoleList) {
+ IOMXStore::RoleInfo role;
+ role.role = inRole.role;
+ role.type = inRole.type;
+ role.isEncoder = inRole.isEncoder;
+ role.preferPlatformNodes = inRole.preferPlatformNodes;
+ std::vector<IOMXStore::NodeInfo>& nodes =
+ role.nodes;
+ nodes.reserve(inRole.nodes.size());
+ for (const auto& inNode : inRole.nodes) {
+ IOMXStore::NodeInfo node;
+ node.name = inNode.name;
+ node.owner = inNode.owner;
+ std::vector<IOMXStore::Attribute>& attributes =
+ node.attributes;
+ attributes.reserve(inNode.attributes.size());
+ for (const auto& inAttr : inNode.attributes) {
+ IOMXStore::Attribute attr;
+ attr.key = inAttr.key;
+ attr.value = inAttr.value;
+ attributes.push_back(std::move(attr));
+ }
+ nodes.push_back(std::move(node));
+ }
+ roles.push_back(std::move(role));
+ }
+ });
+ if (!transStatus.isOk()) {
+ ALOGE("Fail to obtain codec roles from IOmxStore.");
+ return NO_INIT;
+ }
+ } else {
+ // Obtain IOMXStore
+ sp<IServiceManager> sm = defaultServiceManager();
+ if (sm == nullptr) {
+ ALOGE("Cannot obtain the default service manager.");
+ return NO_INIT;
+ }
+ sp<IBinder> codecBinder = sm->getService(String16("media.codec"));
+ if (codecBinder == nullptr) {
+ ALOGE("Cannot obtain the media codec service.");
+ return NO_INIT;
+ }
+ sp<IMediaCodecService> codecService =
+ interface_cast<IMediaCodecService>(codecBinder);
+ if (codecService == nullptr) {
+ ALOGE("Wrong type of media codec service obtained.");
+ return NO_INIT;
+ }
+ omx = codecService->getOMX();
+ if (omx == nullptr) {
+ ALOGE("Cannot connect to an IOMX instance.");
+ }
+ sp<IOMXStore> omxStore = codecService->getOMXStore();
+ if (omxStore == nullptr) {
+ ALOGE("Cannot connect to an IOMXStore instance.");
+ return NO_INIT;
+ }
+
+ // List service attributes (global settings)
+ std::vector<IOMXStore::Attribute> serviceAttributes;
+ status_t status = omxStore->listServiceAttributes(&serviceAttributes);
+ if (status != OK) {
+ ALOGE("Fail to obtain global settings from IOMXStore.");
+ return NO_INIT;
+ }
+ for (const auto& p : serviceAttributes) {
+ writer->addGlobalSetting(
+ p.key.c_str(), p.value.c_str());
+ }
+
+ // List roles
+ status = omxStore->listRoles(&roles);
+ if (status != OK) {
+ ALOGE("Fail to obtain codec roles from IOMXStore.");
+ return NO_INIT;
+ }
}
// Convert roles to lists of codecs
- // codec name -> index into swCodecs/hwCodecs
- std::map<hidl_string, std::unique_ptr<MediaCodecInfoWriter>>
- swCodecName2Info, hwCodecName2Info;
+ // codec name -> index into swCodecs
+ std::map<std::string, std::unique_ptr<MediaCodecInfoWriter> >
+ swCodecName2Info;
+ // codec name -> index into hwCodecs
+ std::map<std::string, std::unique_ptr<MediaCodecInfoWriter> >
+ hwCodecName2Info;
// owner name -> MediaCodecInfo
// This map will be used to obtain the correct IOmx service(s) needed for
// creating IOmxNode instances and querying capabilities.
@@ -149,10 +230,10 @@
// If preferPlatformNodes is true, hardware nodes must be added after
// platform (software) nodes. hwCodecs is used to hold hardware nodes
// that need to be added after software nodes for the same role.
- std::vector<const IOmxStore::NodeInfo*> hwCodecs;
+ std::vector<const IOMXStore::NodeInfo*> hwCodecs;
for (const auto& node : role.nodes) {
const auto& nodeName = node.name;
- bool isSoftware = hasPrefix(nodeName, "OMX.google");
+ bool isSoftware = nodeName.compare(0, 10, "OMX.google") == 0;
MediaCodecInfoWriter* info;
if (isSoftware) {
auto c2i = swCodecName2Info.find(nodeName);
diff --git a/media/libstagefright/codec2/include/C2.h b/media/libstagefright/codec2/include/C2.h
index 7d00a03..bd563ff 100644
--- a/media/libstagefright/codec2/include/C2.h
+++ b/media/libstagefright/codec2/include/C2.h
@@ -66,8 +66,8 @@
* mitigate binary breaks by adhering to the following conventions:
*
* - at most one vtable with placeholder virtual methods
- * - all optional/placeholder virtual methods returning a status_t, with C2_NOT_IMPLEMENTED not
- * requiring any update to input/output arguments.
+ * - all optional/placeholder virtual methods returning a C2Status, with C2_OMITTED not requiring
+ * any update to input/output arguments.
* - limiting symbol export of inline methods
* - use of pimpl (or shared-pimpl)
*
@@ -98,49 +98,62 @@
* C2String: basic string implementation
*/
typedef std::string C2String;
+
+/**
+ * C2StringLiteral: basic string literal implementation.
+ * \note these are never owned by any object, and can only refer to C string literals.
+ */
typedef const char *C2StringLiteral;
/**
- * C2Error: status codes used.
+ * C2Status: status codes used.
*/
-typedef int32_t C2Error;
-enum {
+enum C2Status : int32_t {
+
+/*
+ * Use android status constants if available. Otherwise, define the android status constants as
+ * additional enum values using POSIX errno constants.
+ */
#ifndef __ANDROID__
- OK = 0,
+ ALREADY_EXISTS = -EEXIST,
BAD_VALUE = -EINVAL,
BAD_INDEX = -EOVERFLOW,
- UNKNOWN_TRANSACTION = -EBADMSG,
- ALREADY_EXISTS = -EEXIST,
- NAME_NOT_FOUND = -ENOENT,
+ FAILED_TRANSACTION = -ENOTSUP,
INVALID_OPERATION = -ENOSYS,
+ NAME_NOT_FOUND = -ENOENT,
NO_MEMORY = -ENOMEM,
+ NO_INIT = -ENODEV,
+ OK = 0,
PERMISSION_DENIED = -EPERM,
TIMED_OUT = -ETIMEDOUT,
- UNKNOWN_ERROR = -EINVAL,
+ UNKNOWN_ERROR = -EFAULT,
+ UNKNOWN_TRANSACTION = -EBADMSG,
#endif
- C2_OK = OK, ///< operation completed successfully
+ C2_OK = OK, ///< operation completed successfully
// bad input
- C2_BAD_VALUE = BAD_VALUE, ///< argument has invalid value (user error)
- C2_BAD_INDEX = BAD_INDEX, ///< argument uses invalid index (user error)
- C2_UNSUPPORTED = UNKNOWN_TRANSACTION, ///< argument/index is value but not supported \todo is this really BAD_INDEX/VALUE?
+ C2_BAD_VALUE = BAD_VALUE, ///< argument has invalid value (user error)
+ C2_BAD_INDEX = BAD_INDEX, ///< argument uses invalid index (user error)
+ C2_CANNOT_DO = FAILED_TRANSACTION, ///< argument/index is valid but not possible
// bad sequencing of events
- C2_DUPLICATE = ALREADY_EXISTS, ///< object already exists
- C2_NOT_FOUND = NAME_NOT_FOUND, ///< object not found
- C2_BAD_STATE = INVALID_OPERATION, ///< operation is not permitted in the current state
+ C2_DUPLICATE = ALREADY_EXISTS, ///< object already exists
+ C2_NOT_FOUND = NAME_NOT_FOUND, ///< object not found
+ C2_BAD_STATE = INVALID_OPERATION, ///< operation is not permitted in the current state
// bad environment
- C2_NO_MEMORY = NO_MEMORY, ///< not enough memory to complete operation
- C2_NO_PERMISSION = PERMISSION_DENIED, ///< missing permission to complete operation
- C2_TIMED_OUT = TIMED_OUT, ///< operation did not complete within timeout
+ C2_NO_MEMORY = NO_MEMORY, ///< not enough memory to complete operation
+ C2_REFUSED = PERMISSION_DENIED, ///< missing permission to complete operation
+
+ C2_TIMED_OUT = TIMED_OUT, ///< operation did not complete within timeout
// bad versioning
- C2_NOT_IMPLEMENTED = UNKNOWN_TRANSACTION, ///< operation is not implemented (optional only) \todo for now reuse error code
+ C2_OMITTED = UNKNOWN_TRANSACTION, ///< operation is not implemented/supported (optional only)
// unknown fatal
- C2_CORRUPTED = UNKNOWN_ERROR, ///< some unexpected error prevented the operation
+ C2_CORRUPTED = UNKNOWN_ERROR, ///< some unexpected error prevented the operation
+ C2_NO_INIT = NO_INIT, ///< status has not been initialized
};
/// @}
diff --git a/media/libstagefright/codec2/include/C2Buffer.h b/media/libstagefright/codec2/include/C2Buffer.h
index 9580449..cb8c2d2 100644
--- a/media/libstagefright/codec2/include/C2Buffer.h
+++ b/media/libstagefright/codec2/include/C2Buffer.h
@@ -88,10 +88,10 @@
* \retval C2_TIMED_OUT the fence has not been signaled within the timeout
* \retval C2_BAD_STATE the fence has been abandoned without being signaled (it will never
* be signaled)
- * \retval C2_NO_PERMISSION no permission to wait for the fence (unexpected - system)
+ * \retval C2_REFUSED no permission to wait for the fence (unexpected - system)
* \retval C2_CORRUPTED some unknown error prevented waiting for the fence (unexpected)
*/
- C2Error wait(nsecs_t timeoutNs);
+ C2Status wait(nsecs_t timeoutNs);
/**
* Used to check if this fence is valid (if there is a chance for it to be signaled.)
@@ -155,10 +155,10 @@
* \retval C2_OK the fence(s) were successfully signaled
* \retval C2_BAD_STATE the fence(s) have already been abandoned or merged (caller error)
* \retval C2_DUPLICATE the fence(s) have already been signaled (caller error)
- * \retval C2_NO_PERMISSION no permission to signal the fence (unexpected - system)
+ * \retval C2_REFUSED no permission to signal the fence (unexpected - system)
* \retval C2_CORRUPTED some unknown error prevented signaling the fence(s) (unexpected)
*/
- C2Error fire();
+ C2Status fire();
/**
* Trigger this event from the merging of the supplied fences. This means that it will be
@@ -169,10 +169,10 @@
* \retval C2_NO_MEMORY not enough memory to perform the merging
* \retval C2_DUPLICATE the fence have already been merged (caller error)
* \retval C2_BAD_STATE the fence have already been signaled or abandoned (caller error)
- * \retval C2_NO_PERMISSION no permission to merge the fence (unexpected - system)
+ * \retval C2_REFUSED no permission to merge the fence (unexpected - system)
* \retval C2_CORRUPTED some unknown error prevented merging the fence(s) (unexpected)
*/
- C2Error merge(std::vector<C2Fence> fences);
+ C2Status merge(std::vector<C2Fence> fences);
/**
* Abandons the event and any associated fence(s).
@@ -183,10 +183,10 @@
* \retval C2_OK the fence(s) were successfully signaled
* \retval C2_BAD_STATE the fence(s) have already been signaled or merged (caller error)
* \retval C2_DUPLICATE the fence(s) have already been abandoned (caller error)
- * \retval C2_NO_PERMISSION no permission to abandon the fence (unexpected - system)
+ * \retval C2_REFUSED no permission to abandon the fence (unexpected - system)
* \retval C2_CORRUPTED some unknown error prevented signaling the fence(s) (unexpected)
*/
- C2Error abandon();
+ C2Status abandon();
private:
class Impl;
@@ -197,15 +197,15 @@
/// @{
/**
- * Interface for objects that encapsulate an updatable error value.
+ * Interface for objects that encapsulate an updatable status value.
*/
-struct _C2InnateError {
- inline C2Error error() const { return mError; }
+struct _C2InnateStatus {
+ inline C2Status status() const { return mStatus; }
protected:
- _C2InnateError(C2Error error) : mError(error) { }
+ _C2InnateStatus(C2Status status) : mStatus(status) { }
- C2Error mError; // this error is updatable by the object
+ C2Status mStatus; // this status is updatable by the object
};
/// @}
@@ -230,10 +230,10 @@
}
protected:
- C2Acquirable(C2Error error, C2Fence fence, T t) : C2Fence(fence), mInitialError(error), mT(t) { }
+ C2Acquirable(C2Status error, C2Fence fence, T t) : C2Fence(fence), mInitialError(error), mT(t) { }
private:
- C2Error mInitialError;
+ C2Status mInitialError;
T mT; // TODO: move instead of copy
};
@@ -449,11 +449,11 @@
/**
* \return error during the creation/mapping of this view.
*/
- C2Error error();
+ C2Status error() const;
protected:
C2ReadView(const _C2LinearCapacityAspect *parent, const uint8_t *data);
- explicit C2ReadView(C2Error error);
+ explicit C2ReadView(C2Status error);
private:
class Impl;
@@ -482,11 +482,11 @@
/**
* \return error during the creation/mapping of this view.
*/
- C2Error error();
+ C2Status error() const;
protected:
C2WriteView(const _C2LinearRangeAspect *parent, uint8_t *base);
- explicit C2WriteView(C2Error error);
+ explicit C2WriteView(C2Status error);
private:
class Impl;
@@ -631,7 +631,7 @@
* \retval C2_TIMED_OUT the reservation timed out \todo when?
* \retval C2_CORRUPTED some unknown error prevented reserving space. (unexpected)
*/
- C2Error reserve(size_t size, C2Fence *fence /* nullable */);
+ C2Status reserve(size_t size, C2Fence *fence /* nullable */);
/**
* Abandons a portion of this segment. This will move to the beginning of this segment.
@@ -644,7 +644,7 @@
* \retval C2_TIMED_OUT the operation timed out (unexpected)
* \retval C2_CORRUPTED some unknown error prevented abandoning the data (unexpected)
*/
- C2Error abandon(size_t size);
+ C2Status abandon(size_t size);
/**
* Share a portion as block(s) with consumers (these are moved to the used section).
@@ -661,7 +661,7 @@
* \retval C2_TIMED_OUT the operation timed out (unexpected)
* \retval C2_CORRUPTED some unknown error prevented sharing the data (unexpected)
*/
- C2Error share(size_t size, C2Fence fence, std::list<C2ConstLinearBlock> &blocks);
+ C2Status share(size_t size, C2Fence fence, std::list<C2ConstLinearBlock> &blocks);
/**
* Returns the beginning offset of this segment from the start of this circular block.
@@ -695,7 +695,7 @@
/**
* \return error during the creation/mapping of this view.
*/
- C2Error error();
+ C2Status error() const;
};
/**
@@ -716,7 +716,7 @@
* \param size number of bytes to commit to the next segment
* \param fence fence used for the commit (the fence must signal before the data is committed)
*/
- C2Error commit(size_t size, C2Fence fence);
+ C2Status commit(size_t size, C2Fence fence);
/**
* Maps this block into memory and returns a write view for it.
@@ -1016,14 +1016,14 @@
/**
* \return error during the creation/mapping of this view.
*/
- C2Error error() const;
+ C2Status error() const;
protected:
C2GraphicView(
const _C2PlanarCapacityAspect *parent,
uint8_t *const *data,
const C2PlaneLayout& layout);
- explicit C2GraphicView(C2Error error);
+ explicit C2GraphicView(C2Status error);
private:
class Impl;
@@ -1224,7 +1224,7 @@
* \retval C2_NO_MEMORY not enough memory to register for this callback
* \retval C2_CORRUPTED an unknown error prevented the registration (unexpected)
*/
- C2Error registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr);
+ C2Status registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr);
/**
* Unregisters a previously registered pre-destroy notification.
@@ -1236,7 +1236,7 @@
* \retval C2_NOT_FOUND the notification was not found
* \retval C2_CORRUPTED an unknown error prevented the registration (unexpected)
*/
- C2Error unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr);
+ C2Status unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr);
///@}
@@ -1262,7 +1262,7 @@
* \retval C2_NO_MEMORY not enough memory to attach the metadata (this return value is not
* used if the same kind of metadata is already attached to the buffer).
*/
- C2Error setInfo(const std::shared_ptr<C2Info> &info);
+ C2Status setInfo(const std::shared_ptr<C2Info> &info);
/**
* Checks if there is a certain type of metadata attached to this buffer.
@@ -1377,7 +1377,7 @@
* \todo Do we need to support sync operation as we could just wait for the fence?
*
* \retval C2_OK the operation was successful
- * \retval C2_NO_PERMISSION no permission to map the portion
+ * \retval C2_REFUSED no permission to map the portion
* \retval C2_TIMED_OUT the operation timed out
* \retval C2_DUPLICATE if the allocation is already mapped.
* \retval C2_NO_MEMORY not enough memory to complete the operation
@@ -1385,7 +1385,7 @@
* the usage flags are invalid (caller error)
* \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
*/
- virtual C2Error map(
+ virtual C2Status map(
size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd /* nullable */,
void **addr /* nonnull */) = 0;
@@ -1407,9 +1407,9 @@
* \retval C2_BAD_VALUE the parameters (addr/size) do not correspond to previously mapped
* regions (caller error)
* \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
- * \retval C2_NO_PERMISSION no permission to unmap the portion (unexpected - system)
+ * \retval C2_REFUSED no permission to unmap the portion (unexpected - system)
*/
- virtual C2Error unmap(void *addr, size_t size, int *fenceFd /* nullable */) = 0;
+ virtual C2Status unmap(void *addr, size_t size, int *fenceFd /* nullable */) = 0;
/**
* Returns true if this is a valid allocation.
@@ -1463,7 +1463,7 @@
* \todo Do we need to support sync operation as we could just wait for the fence?
*
* \retval C2_OK the operation was successful
- * \retval C2_NO_PERMISSION no permission to map the section
+ * \retval C2_REFUSED no permission to map the section
* \retval C2_DUPLICATE there is already a mapped region (caller error)
* \retval C2_TIMED_OUT the operation timed out
* \retval C2_NO_MEMORY not enough memory to complete the operation
@@ -1472,7 +1472,7 @@
* \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
*/
- virtual C2Error map(
+ virtual C2Status map(
C2Rect rect, C2MemoryUsage usage, int *fenceFd,
// TODO: return <addr, size> buffers with plane sizes
C2PlaneLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) = 0;
@@ -1490,9 +1490,9 @@
* \retval C2_TIMED_OUT the operation timed out
* \retval C2_NOT_FOUND there is no mapped region (caller error)
* \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
- * \retval C2_NO_PERMISSION no permission to unmap the section (unexpected - system)
+ * \retval C2_REFUSED no permission to unmap the section (unexpected - system)
*/
- virtual C2Error unmap(C2Fence *fenceFd /* nullable */) = 0;
+ virtual C2Status unmap(C2Fence *fenceFd /* nullable */) = 0;
/**
* Returns true if this is a valid allocation.
@@ -1545,16 +1545,16 @@
* \retval C2_OK the allocation was successful
* \retval C2_NO_MEMORY not enough memory to complete the allocation
* \retval C2_TIMED_OUT the allocation timed out
- * \retval C2_NO_PERMISSION no permission to complete the allocation
+ * \retval C2_REFUSED no permission to complete the allocation
* \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
- * \retval C2_UNSUPPORTED this allocator does not support 1D allocations
+ * \retval C2_OMITTED this allocator does not support 1D allocations
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
*/
- virtual C2Error allocateLinearBuffer(
+ virtual C2Status allocateLinearBuffer(
uint32_t capacity __unused, C2MemoryUsage usage __unused,
std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) {
*allocation = nullptr;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
/**
@@ -1568,16 +1568,16 @@
* \retval C2_OK the allocation was recreated successfully
* \retval C2_NO_MEMORY not enough memory to recreate the allocation
* \retval C2_TIMED_OUT the recreation timed out (unexpected)
- * \retval C2_NO_PERMISSION no permission to recreate the allocation
+ * \retval C2_REFUSED no permission to recreate the allocation
* \retval C2_BAD_VALUE invalid handle (caller error)
- * \retval C2_UNSUPPORTED this allocator does not support 1D allocations
+ * \retval C2_OMITTED this allocator does not support 1D allocations
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
*/
- virtual C2Error recreateLinearBuffer(
+ virtual C2Status recreateLinearBuffer(
const C2Handle *handle __unused,
std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) {
*allocation = nullptr;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
/**
@@ -1601,17 +1601,17 @@
* \retval C2_OK the allocation was successful
* \retval C2_NO_MEMORY not enough memory to complete the allocation
* \retval C2_TIMED_OUT the allocation timed out
- * \retval C2_NO_PERMISSION no permission to complete the allocation
+ * \retval C2_REFUSED no permission to complete the allocation
* \retval C2_BAD_VALUE width, height, format or usage are not supported (invalid) (caller error)
- * \retval C2_UNSUPPORTED this allocator does not support 2D allocations
+ * \retval C2_OMITTED this allocator does not support 2D allocations
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
*/
- virtual C2Error allocateGraphicBuffer(
+ virtual C2Status allocateGraphicBuffer(
uint32_t width __unused, uint32_t height __unused, uint32_t format __unused,
C2MemoryUsage usage __unused,
std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) {
*allocation = nullptr;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
/**
@@ -1625,16 +1625,16 @@
* \retval C2_OK the allocation was recreated successfully
* \retval C2_NO_MEMORY not enough memory to recreate the allocation
* \retval C2_TIMED_OUT the recreation timed out (unexpected)
- * \retval C2_NO_PERMISSION no permission to recreate the allocation
+ * \retval C2_REFUSED no permission to recreate the allocation
* \retval C2_BAD_VALUE invalid handle (caller error)
- * \retval C2_UNSUPPORTED this allocator does not support 2D allocations
+ * \retval C2_OMITTED this allocator does not support 2D allocations
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during recreation (unexpected)
*/
- virtual C2Error recreateGraphicBuffer(
+ virtual C2Status recreateGraphicBuffer(
const C2Handle *handle __unused,
std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) {
*allocation = nullptr;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
protected:
@@ -1669,16 +1669,16 @@
* \retval C2_OK the allocation was successful
* \retval C2_NO_MEMORY not enough memory to complete the allocation
* \retval C2_TIMED_OUT the allocation timed out
- * \retval C2_NO_PERMISSION no permission to complete the allocation
+ * \retval C2_REFUSED no permission to complete the allocation
* \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
- * \retval C2_UNSUPPORTED this allocator does not support linear allocations
+ * \retval C2_OMITTED this allocator does not support linear allocations
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
*/
- virtual C2Error allocateLinearBlock(
+ virtual C2Status allocateLinearBlock(
uint32_t capacity __unused, C2MemoryUsage usage __unused,
std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
*block = nullptr;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
/**
@@ -1698,16 +1698,16 @@
* \retval C2_OK the allocation was successful
* \retval C2_NO_MEMORY not enough memory to complete the allocation
* \retval C2_TIMED_OUT the allocation timed out
- * \retval C2_NO_PERMISSION no permission to complete the allocation
+ * \retval C2_REFUSED no permission to complete the allocation
* \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
- * \retval C2_UNSUPPORTED this allocator does not support circular allocations
+ * \retval C2_OMITTED this allocator does not support circular allocations
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
*/
- virtual C2Error allocateCircularBlock(
+ virtual C2Status allocateCircularBlock(
uint32_t capacity __unused, C2MemoryUsage usage __unused,
std::shared_ptr<C2CircularBlock> *block /* nonnull */) {
*block = nullptr;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
/**
@@ -1731,17 +1731,17 @@
* \retval C2_OK the allocation was successful
* \retval C2_NO_MEMORY not enough memory to complete the allocation
* \retval C2_TIMED_OUT the allocation timed out
- * \retval C2_NO_PERMISSION no permission to complete the allocation
+ * \retval C2_REFUSED no permission to complete the allocation
* \retval C2_BAD_VALUE width, height, format or usage are not supported (invalid) (caller error)
- * \retval C2_UNSUPPORTED this allocator does not support 2D allocations
+ * \retval C2_OMITTED this allocator does not support 2D allocations
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
*/
- virtual C2Error allocateGraphicBlock(
+ virtual C2Status allocateGraphicBlock(
uint32_t width __unused, uint32_t height __unused, uint32_t format __unused,
C2MemoryUsage usage __unused,
std::shared_ptr<C2GraphicBlock> *block /* nonnull */) {
*block = nullptr;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
protected:
diff --git a/media/libstagefright/codec2/include/C2Component.h b/media/libstagefright/codec2/include/C2Component.h
index a9b1702..2ac9c72 100644
--- a/media/libstagefright/codec2/include/C2Component.h
+++ b/media/libstagefright/codec2/include/C2Component.h
@@ -55,6 +55,31 @@
virtual ~C2ComponentListener() = default;
};
+struct C2FieldSupportedValuesQuery {
+ enum Type : uint32_t {
+ POSSIBLE, ///< query all possible values regardless of other settings
+ CURRENT, ///< query currently possible values given dependent settings
+ };
+
+ const C2ParamField field;
+ const Type type;
+ C2Status status;
+ C2FieldSupportedValues values;
+
+ C2FieldSupportedValuesQuery(const C2ParamField &field_, Type type_)
+ : field(field_), type(type_), status(C2_NO_INIT) { }
+
+ static C2FieldSupportedValuesQuery&&
+ Current(const C2ParamField &field_) {
+ return std::move(C2FieldSupportedValuesQuery(field_, CURRENT));
+ }
+
+ static C2FieldSupportedValuesQuery&&
+ Possible(const C2ParamField &field_) {
+ return std::move(C2FieldSupportedValuesQuery(field_, POSSIBLE));
+ }
+};
+
/**
* Component interface object. This object contains all of the configuration of a potential or
* actual component. It can be created and used independently of an actual C2Component instance to
@@ -129,7 +154,7 @@
* \retval C2_CORRUPTED some unknown error prevented the querying of the parameters
* (unexpected)
*/
- virtual status_t query_nb(
+ virtual C2Status query_nb(
const std::vector<C2Param* const> &stackParams,
const std::vector<C2Param::Index> &heapParamIndices,
std::vector<std::unique_ptr<C2Param>>* const heapParams) const = 0;
@@ -166,7 +191,7 @@
* \retval C2_CORRUPTED some unknown error prevented the update of the parameters
* (unexpected)
*/
- virtual status_t config_nb(
+ virtual C2Status config_nb(
const std::vector<C2Param* const> ¶ms,
std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
@@ -205,7 +230,7 @@
* \retval C2_CORRUPTED some unknown error prevented the update of the parameters
* (unexpected)
*/
- virtual status_t commit_sm(
+ virtual C2Status commit_sm(
const std::vector<C2Param* const> ¶ms,
std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
@@ -225,12 +250,13 @@
* \retval C2_OK the tunnel was successfully created
* \retval C2_BAD_INDEX the target component does not exist
* \retval C2_DUPLICATE the tunnel already exists
- * \retval C2_UNSUPPORTED the tunnel is not supported
+ * \retval C2_OMITTED tunneling is not supported by this component
+ * \retval C2_CANNOT_DO the specific tunnel is not supported
*
* \retval C2_TIMED_OUT could not create the tunnel within the time limit (unexpected)
* \retval C2_CORRUPTED some unknown error prevented the creation of the tunnel (unexpected)
*/
- virtual status_t createTunnel_sm(node_id targetComponent) = 0;
+ virtual C2Status createTunnel_sm(node_id targetComponent) = 0;
/**
* Releases a tunnel from this component to the target component.
@@ -246,11 +272,12 @@
* \retval C2_OK the tunnel was marked for release successfully
* \retval C2_BAD_INDEX the target component does not exist
* \retval C2_NOT_FOUND the tunnel does not exist
+ * \retval C2_OMITTED tunneling is not supported by this component
*
* \retval C2_TIMED_OUT could not mark the tunnel for release within the time limit (unexpected)
* \retval C2_CORRUPTED some unknown error prevented the release of the tunnel (unexpected)
*/
- virtual status_t releaseTunnel_sm(node_id targetComponent) = 0;
+ virtual C2Status releaseTunnel_sm(node_id targetComponent) = 0;
// REFLECTION MECHANISM (USED FOR EXTENSION)
@@ -273,7 +300,7 @@
* \retval C2_OK the operation completed successfully.
* \retval C2_NO_MEMORY not enough memory to complete this method.
*/
- virtual status_t getSupportedParams(
+ virtual C2Status getSupportedParams(
std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const = 0;
/**
@@ -281,9 +308,8 @@
* \todo should this take a list considering that setting some fields may further limit other
* fields in the same list?
*/
- virtual status_t getSupportedValues(
- const std::vector<const C2ParamField> &fields,
- std::vector<C2FieldSupportedValues>* const values) const = 0;
+ virtual C2Status getSupportedValues(
+ std::vector<C2FieldSupportedValuesQuery> &fields) const = 0;
virtual ~C2ComponentInterface() = default;
};
@@ -305,12 +331,12 @@
*
* \retval C2_OK the work was successfully queued
* \retval C2_BAD_INDEX some component(s) in the work do(es) not exist
- * \retval C2_UNSUPPORTED the components are not tunneled
+ * \retval C2_CANNOT_DO the components are not tunneled
*
* \retval C2_NO_MEMORY not enough memory to queue the work
* \retval C2_CORRUPTED some unknown error prevented queuing the work (unexpected)
*/
- virtual status_t queue_nb(std::list<std::unique_ptr<C2Work>>* const items) = 0;
+ virtual C2Status queue_nb(std::list<std::unique_ptr<C2Work>>* const items) = 0;
/**
* Announces a work to be queued later for the component. This reserves a slot for the queue
@@ -322,14 +348,14 @@
*
* \retval C2_OK the work announcement has been successfully recorded
* \retval C2_BAD_INDEX some component(s) in the work outline do(es) not exist
- * \retval C2_UNSUPPORTED the componentes are not tunneled
+ * \retval C2_CANNOT_DO the componentes are not tunneled
*
* \retval C2_NO_MEMORY not enough memory to record the work announcement
* \retval C2_CORRUPTED some unknown error prevented recording the announcement (unexpected)
*
* \todo Can this be rolled into queue_nb?
*/
- virtual status_t announce_nb(const std::vector<C2WorkOutline> &items) = 0;
+ virtual C2Status announce_nb(const std::vector<C2WorkOutline> &items) = 0;
/**
* Discards and abandons any pending work for the component, and optionally any component
@@ -361,7 +387,7 @@
* \retval C2_TIMED_OUT the flush could not be completed within the time limit (unexpected)
* \retval C2_CORRUPTED some unknown error prevented flushing from completion (unexpected)
*/
- virtual status_t flush_sm(bool flushThrough, std::list<std::unique_ptr<C2Work>>* const flushedWork) = 0;
+ virtual C2Status flush_sm(bool flushThrough, std::list<std::unique_ptr<C2Work>>* const flushedWork) = 0;
/**
* Drains the component, and optionally downstream components
@@ -390,7 +416,7 @@
* \retval C2_TIMED_OUT the flush could not be completed within the time limit (unexpected)
* \retval C2_CORRUPTED some unknown error prevented flushing from completion (unexpected)
*/
- virtual status_t drain_nb(bool drainThrough) = 0;
+ virtual C2Status drain_nb(bool drainThrough) = 0;
// STATE CHANGE METHODS
// =============================================================================================
@@ -411,7 +437,7 @@
* \retval C2_TIMED_OUT the component could not be started within the time limit (unexpected)
* \retval C2_CORRUPTED some unknown error prevented starting the component (unexpected)
*/
- virtual status_t start() = 0;
+ virtual C2Status start() = 0;
/**
* Stops the component.
@@ -428,7 +454,7 @@
* This does not alter any settings and tunings that may have resulted in a tripped state.
* (Is this material given the definition? Perhaps in case we want to start again.)
*/
- virtual status_t stop() = 0;
+ virtual C2Status stop() = 0;
/**
* Resets the component.
@@ -502,9 +528,9 @@
* \retval C2_TIMED_OUT could not reset the parser within the time limit (unexpected)
* \retval C2_CORRUPTED some unknown error prevented the resetting of the parser (unexpected)
*/
- virtual status_t reset() { return C2_OK; }
+ virtual C2Status reset() { return C2_OK; }
- virtual status_t parseFrame(C2BufferPack &frame);
+ virtual C2Status parseFrame(C2BufferPack &frame);
virtual ~C2FrameInfoParser() = default;
};
@@ -542,7 +568,7 @@
* \retval C2_NOT_FOUND no such allocator
* \retval C2_NO_MEMORY not enough memory to create the allocator
*/
- virtual status_t createAllocator(ID id, std::shared_ptr<C2Allocator>* const allocator) = 0;
+ virtual C2Status createAllocator(ID id, std::shared_ptr<C2Allocator>* const allocator) = 0;
virtual ~C2AllocatorStore() = default;
};
@@ -565,7 +591,7 @@
* \retval C2_NOT_FOUND no such component
* \retval C2_NO_MEMORY not enough memory to create the component
*/
- virtual status_t createComponent(C2String name, std::shared_ptr<C2Component>* const component);
+ virtual C2Status createComponent(C2String name, std::shared_ptr<C2Component>* const component);
/**
* Creates a component interface.
@@ -586,7 +612,7 @@
*
* \todo Do we need an interface, or could this just be a component that is never started?
*/
- virtual status_t createInterface(C2String name, std::shared_ptr<C2ComponentInterface>* const interface);
+ virtual C2Status createInterface(C2String name, std::shared_ptr<C2ComponentInterface>* const interface);
/**
* Returns the list of components supported by this component store.
@@ -600,9 +626,9 @@
// -------------------------------------- UTILITY METHODS --------------------------------------
// on-demand buffer layout conversion (swizzling)
- virtual status_t copyBuffer(std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst);
+ virtual C2Status copyBuffer(std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst);
- // status_t selectPreferredColor(formats<A>, formats<B>);
+ // C2Status selectPreferredColor(formats<A>, formats<B>);
// GLOBAL SETTINGS
// system-wide stride & slice-height (???)
@@ -636,7 +662,7 @@
* \retval C2_CORRUPTED some unknown error prevented the querying of the parameters
* (unexpected)
*/
- virtual status_t query_sm(
+ virtual C2Status query_sm(
const std::vector<C2Param* const> &stackParams,
const std::vector<C2Param::Index> &heapParamIndices,
std::vector<std::unique_ptr<C2Param>>* const heapParams) const = 0;
@@ -675,7 +701,7 @@
* \retval C2_CORRUPTED some unknown error prevented the update of the parameters
* (unexpected)
*/
- virtual status_t config_nb(
+ virtual C2Status config_nb(
const std::vector<C2Param* const> ¶ms,
std::list<std::unique_ptr<C2SettingResult>>* const failures) = 0;
diff --git a/media/libstagefright/codec2/include/C2Param.h b/media/libstagefright/codec2/include/C2Param.h
index 02403c5..f0b92a3 100644
--- a/media/libstagefright/codec2/include/C2Param.h
+++ b/media/libstagefright/codec2/include/C2Param.h
@@ -344,6 +344,10 @@
/// returns the parameter type: the parameter index without the stream ID
inline uint32_t type() const { return _mIndex.type(); }
+ /// returns the index of this parameter
+ /// \todo: should we restrict this to C2ParamField?
+ inline uint32_t index() const { return (uint32_t)_mIndex; }
+
/// returns the kind of this parameter
inline Kind kind() const { return _mIndex.kind(); }
@@ -562,7 +566,6 @@
/**
* Constructor used to identify a field in an object.
*
- * \param U[type] pointer to the object that contains this field
* \param pm[im] member pointer to the field
*/
template<typename R, typename T, typename B=typename std::remove_extent<R>::type>
@@ -597,23 +600,93 @@
};
/**
- * Structure uniquely specifying a field in a configuration
+ * Structure uniquely specifying a 'field' in a configuration. The field
+ * can be a field of a configuration, a subfield of a field of a configuration,
+ * and even the whole configuration. Moreover, if the field can point to an
+ * element in a array field, or to the entire array field.
+ *
+ * This structure is used for querying supported values for a field, as well
+ * as communicating configuration failures and conflicts when trying to change
+ * a configuration for a component/interface or a store.
*/
struct C2ParamField {
//public:
- // TODO: fix what this is for T[] (for now size becomes T[1])
+ /**
+ * Create a field identifier using a configuration parameter (variable),
+ * and a pointer to member.
+ *
+ * ~~~~~~~~~~~~~ (.cpp)
+ *
+ * struct C2SomeParam {
+ * uint32_t mField;
+ * uint32_t mArray[2];
+ * C2OtherStruct mStruct;
+ * uint32_t mFlexArray[];
+ * } *mParam;
+ *
+ * C2ParamField(mParam, &mParam->mField);
+ * C2ParamField(mParam, &mParam->mArray);
+ * C2ParamField(mParam, &mParam->mArray[0]);
+ * C2ParamField(mParam, &mParam->mStruct.mSubField);
+ * C2ParamField(mParam, &mParam->mFlexArray);
+ * C2ParamField(mParam, &mParam->mFlexArray[2]);
+ *
+ * ~~~~~~~~~~~~~
+ *
+ * \todo fix what this is for T[] (for now size becomes T[1])
+ *
+ * \param param pointer to parameter
+ * \param offset member pointer
+ */
template<typename S, typename T>
inline C2ParamField(S* param, T* offset)
: _mIndex(param->index()),
_mFieldId(offset) {}
+ /**
+ * Create a field identifier using a configuration parameter (variable),
+ * and a member pointer. This method cannot be used to refer to an
+ * array element or a subfield.
+ *
+ * ~~~~~~~~~~~~~ (.cpp)
+ *
+ * C2SomeParam mParam;
+ * C2ParamField(&mParam, &C2SomeParam::mMemberField);
+ *
+ * ~~~~~~~~~~~~~
+ *
+ * \param p pointer to parameter
+ * \param T member pointer to the field member
+ */
template<typename R, typename T, typename U>
- inline C2ParamField(U *p, R T::* pm) : _mIndex(p->type()), _mFieldId(p, pm) { }
+ inline C2ParamField(U *p, R T::* pm) : _mIndex(p->index()), _mFieldId(p, pm) { }
+ /**
+ * Create a field identifier to a configuration parameter (variable).
+ *
+ * ~~~~~~~~~~~~~ (.cpp)
+ *
+ * C2SomeParam mParam;
+ * C2ParamField(&mParam);
+ *
+ * ~~~~~~~~~~~~~
+ *
+ * \param param pointer to parameter
+ */
+ template<typename S>
+ inline C2ParamField(S* param)
+ : _mIndex(param->index()), _mFieldId(0u, param->size()) {}
+
+ /**
+ * Equality operator.
+ */
inline bool operator==(const C2ParamField &other) const {
return _mIndex == other._mIndex && _mFieldId == other._mFieldId;
}
+ /**
+ * Ordering operator.
+ */
inline bool operator<(const C2ParamField &other) const {
return _mIndex < other._mIndex ||
(_mIndex == other._mIndex && _mFieldId < other._mFieldId);
@@ -622,8 +695,8 @@
DEFINE_OTHER_COMPARISON_OPERATORS(C2ParamField)
private:
- C2Param::Index _mIndex;
- _C2FieldId _mFieldId;
+ C2Param::Index _mIndex; ///< parameter index
+ _C2FieldId _mFieldId; ///< field identifier
};
/**
@@ -1153,6 +1226,7 @@
struct C2FieldSupportedValues {
//public:
enum Type {
+ EMPTY, ///< no supported values
RANGE, ///< a numeric range that can be continuous or discrete
VALUES, ///< a list of values
FLAGS ///< a list of flags that can be OR-ed
@@ -1171,6 +1245,10 @@
} range;
std::vector<Primitive> values;
+ C2FieldSupportedValues()
+ : type(EMPTY) {
+ }
+
template<typename T>
C2FieldSupportedValues(T min, T max, T step = T(std::is_floating_point<T>::value ? 0 : 1))
: type(RANGE),
@@ -1199,6 +1277,9 @@
}
}
+ /// \internal
+ /// \todo: create separate values vs. flags initializer as for flags we want
+ /// to list both allowed and disallowed flags
template<typename T, typename E=decltype(C2FieldDescriptor::namedValuesFor(*(T*)0))>
C2FieldSupportedValues(bool flags, const T*)
: type(flags ? FLAGS : VALUES),
@@ -1210,6 +1291,21 @@
}
};
+/**
+ * Spported values for a specific field.
+ *
+ * This is a pair of the field specifier together with an optional supported values object.
+ * This structure is used when reporting parameter configuration failures and conflicts.
+ */
+struct C2ParamFieldValues {
+ C2ParamField paramOrField; ///< the field or parameter
+ /// optional supported values for the field if paramOrField specifies an actual field that is
+ /// numeric (non struct, blob or string). Supported values for arrays (including string and
+ /// blobs) describe the supported values for each element (character for string, and bytes for
+ /// blobs). It is optional for read-only strings and blobs.
+ std::unique_ptr<C2FieldSupportedValues> values;
+};
+
/// @}
} // namespace android
diff --git a/media/libstagefright/codec2/include/C2Work.h b/media/libstagefright/codec2/include/C2Work.h
index a378623..69c16ab 100644
--- a/media/libstagefright/codec2/include/C2Work.h
+++ b/media/libstagefright/codec2/include/C2Work.h
@@ -28,28 +28,47 @@
#include <list>
#include <vector>
-typedef int status_t;
-
namespace android {
/// \defgroup work Work and data processing
/// @{
+/**
+ * Information describing the reason a parameter settings may fail, or
+ * may be overriden.
+ */
struct C2SettingResult {
- enum Failure {
+ enum Failure : uint32_t {
READ_ONLY, ///< parameter is read-only and cannot be set
MISMATCH, ///< parameter mismatches input data
BAD_VALUE, ///< parameter does not accept value
BAD_TYPE, ///< parameter is not supported
BAD_PORT, ///< parameter is not supported on the specific port
BAD_INDEX, ///< parameter is not supported on the specific stream
- CONFLICT, ///< parameter is in conflict with another setting
+ CONFLICT, ///< parameter is in conflict with an/other setting(s)
+ /// parameter is out of range due to other settings (this failure mode
+ /// can only be used for strict parameters)
+ UNSUPPORTED,
+
+
+ /// requested parameter value is in conflict with an/other setting(s)
+ /// and has been corrected to the closest supported value. This failure
+ /// mode is given to provide suggestion to the client as to how to
+ /// enable the requested parameter value.
+ INFO_CONFLICT,
};
- C2ParamField field;
- Failure failure;
- std::unique_ptr<C2FieldSupportedValues> supportedValues; //< if different from normal (e.g. in conflict w/another param or input data)
- std::list<C2ParamField> conflictingFields;
+ Failure failure; ///< failure code
+
+ /// Failing (or corrected) field. Currently supported values for the field. This is set if
+ /// different from the globally supported values (e.g. due to restrictions by another param or
+ /// input data)
+ /// \todo need to define suggestions for masks to be set and unset.
+ C2ParamFieldValues field;
+
+ /// Conflicting parameters or fields with optional suggestions with (optional) suggested values
+ /// for any conflicting fields to avoid the conflict.
+ std::list<C2ParamFieldValues> conflicts;
};
// ================================================================================================
@@ -146,7 +165,7 @@
std::list<std::unique_ptr<C2Worklet>> worklets;
uint32_t worklets_processed;
- status_t result;
+ C2Status result;
};
struct C2WorkOutline {
diff --git a/media/libstagefright/codec2/tests/C2ComponentInterface_test.cpp b/media/libstagefright/codec2/tests/C2ComponentInterface_test.cpp
index 0c8ca3e..b725d76 100644
--- a/media/libstagefright/codec2/tests/C2ComponentInterface_test.cpp
+++ b/media/libstagefright/codec2/tests/C2ComponentInterface_test.cpp
@@ -112,11 +112,11 @@
// check if a component has a parameter whose type is |T|.
// If a component has, the value should be copied into an argument, that is
// |p| in queryOnStack() and |heapParams| in queryOnHeap().
- // The return value is status_t (e.g. C2_OK).
- template <typename T> status_t queryOnStack(T *const p);
+ // The return value is C2Status (e.g. C2_OK).
+ template <typename T> C2Status queryOnStack(T *const p);
template <typename T>
- status_t queryOnHeap(const T &p,
+ C2Status queryOnHeap(const T &p,
std::vector<std::unique_ptr<C2Param>> *const heapParams);
// Get a value whose type is |T| in a component. The value is copied to |param|.
@@ -139,7 +139,7 @@
// Execute an interface's config_nb(). |T| is a single parameter type, not std::vector.
// config() creates std::vector<C2Param *const> {p} and passes it to config_nb().
template <typename T>
- status_t
+ C2Status
config(T *const p,
std::vector<std::unique_ptr<C2SettingResult>> *const failures);
@@ -150,7 +150,7 @@
// Test if config works correctly for writable parameters.
// This changes the parameter's value to |newParam|.
// |stConfig| is a return value of config().
- template <typename T> void configWritableParamValidValue(const T &newParam, status_t *stConfig);
+ template <typename T> void configWritableParamValidValue(const T &newParam, C2Status *stConfig);
// Test if config works correctly in the case an invalid value |newParam| is tried to write
// to an writable parameter.
@@ -162,7 +162,7 @@
// config() should be failed if these values are used as new values.
// This function should be called only for writable and supported parameters.
template <typename TField>
- void getTestValues(const std::vector<C2FieldSupportedValues> &validValueInfos,
+ void getTestValues(const C2FieldSupportedValues &validValueInfos,
std::vector<TField> *const validValues,
std::vector<TField> *const invalidValues);
@@ -194,13 +194,13 @@
} \
} while (false)
-template <typename T> status_t C2CompIntfTest::queryOnStack(T *const p) {
+template <typename T> C2Status C2CompIntfTest::queryOnStack(T *const p) {
std::vector<C2Param *const> stackParams{p};
return mIntf->query_nb(stackParams, {}, nullptr);
}
template <typename T>
-status_t C2CompIntfTest::queryOnHeap(
+C2Status C2CompIntfTest::queryOnHeap(
const T &p, std::vector<std::unique_ptr<C2Param>> *const heapParams) {
uint32_t index = p.type();
if (p.forStream()) {
@@ -258,7 +258,7 @@
}
template <typename T>
-status_t C2CompIntfTest::config(
+C2Status C2CompIntfTest::config(
T *const p, std::vector<std::unique_ptr<C2SettingResult>> *const failures) {
std::vector<C2Param *const> params{p};
return mIntf->config_nb(params, failures);
@@ -286,7 +286,7 @@
}
template <typename T>
-void C2CompIntfTest::configWritableParamValidValue(const T &newParam, status_t *configResult) {
+void C2CompIntfTest::configWritableParamValidValue(const T &newParam, C2Status *configResult) {
std::unique_ptr<T> p = makeParamFrom(newParam);
std::vector<C2Param *const> params{p.get()};
@@ -297,7 +297,7 @@
// because there may be dependent limitations between fields or between parameters.
// TODO(hiroh): I have to fill the return value. Comments in C2Component.h doesn't mention
// about the return value when conflict happens. I set C2_BAD_VALUE to it temporarily now.
- status_t stConfig = mIntf->config_nb(params, &failures);
+ C2Status stConfig = mIntf->config_nb(params, &failures);
if (stConfig == C2_OK) {
EXPECT_EQ(0u, failures.size());
} else {
@@ -325,7 +325,7 @@
// If another field type is added, it is necessary to add function for that.
template <>
void C2CompIntfTest::getTestValues(
- const std::vector<C2FieldSupportedValues> &validValueInfos,
+ const C2FieldSupportedValues &validValueInfos,
std::vector<C2DomainKind> *const validValues,
std::vector<C2DomainKind> *const invalidValues) {
UNUSED(validValueInfos);
@@ -339,7 +339,7 @@
template <typename TField>
void C2CompIntfTest::getTestValues(
- const std::vector<C2FieldSupportedValues> &validValueInfos,
+ const C2FieldSupportedValues &validValueInfos,
std::vector<TField> *const validValues,
std::vector<TField> *const invalidValues) {
@@ -366,9 +366,14 @@
};
// The size of validValueInfos is one.
- const auto &c2FSV = validValueInfos[0];
+ const auto &c2FSV = validValueInfos;
switch (c2FSV.type) {
+ case C2FieldSupportedValues::Type::EMPTY: {
+ invalidValues->emplace_back(TField(0));
+ // TODO(hiroh) : Should other invalid values be tested?
+ break;
+ }
case C2FieldSupportedValues::Type::RANGE: {
const auto &range = c2FSV.range;
auto rmin = prim2Value(range.min);
@@ -476,7 +481,7 @@
TParam *const param, TRealField *const writableField,
const std::vector<TField> &validValues,
const std::vector<TField> &invalidValues) {
- status_t stConfig;
+ C2Status stConfig;
// Get the parameter's value in the beginning in order to reset the value at the end.
TRACED_FAILURE(getValue(param));
@@ -550,7 +555,7 @@
std::vector<std::unique_ptr<C2SettingResult>> failures;
// Config does not change the parameter, because param is the present param.
// This config is executed to find out if a parameter is read-only or writable.
- status_t stStack = config(param.get(), &failures);
+ C2Status stStack = config(param.get(), &failures);
if (stStack == C2_BAD_VALUE) {
// Read-only
std::unique_ptr<T> newParam = makeParam<T>();
@@ -584,15 +589,16 @@
#define TEST_GENERAL_WRITABLE_FIELD(TParam_, field_type_name_, field_name_) \
do { \
std::unique_ptr<TParam_> param = makeParam<TParam_>(); \
- std::vector<C2FieldSupportedValues> validValueInfos; \
+ std::vector<C2FieldSupportedValuesQuery> validValueInfos = { \
+ C2FieldSupportedValuesQuery::Current( \
+ C2ParamField(param.get(), &field_type_name_::field_name_)) \
+ }; \
ASSERT_EQ(C2_OK, \
- mIntf->getSupportedValues( \
- {C2ParamField(param.get(), &field_type_name_::field_name_)}, \
- &validValueInfos)); \
+ mIntf->getSupportedValues(validValueInfos)); \
ASSERT_EQ(1u, validValueInfos.size()); \
std::vector<decltype(param->field_name_)> validValues; \
std::vector<decltype(param->field_name_)> invalidValues; \
- getTestValues(validValueInfos, &validValues, &invalidValues); \
+ getTestValues(validValueInfos[0].values, &validValues, &invalidValues); \
testWritableParam(param.get(), ¶m->field_name_, validValues,\
invalidValues); \
} while (0)
diff --git a/media/libstagefright/codec2/tests/C2Param_test.cpp b/media/libstagefright/codec2/tests/C2Param_test.cpp
index 0e71b2a..97c5f91 100644
--- a/media/libstagefright/codec2/tests/C2Param_test.cpp
+++ b/media/libstagefright/codec2/tests/C2Param_test.cpp
@@ -2403,28 +2403,28 @@
return 0;
}
- virtual status_t commit_sm(
+ virtual C2Status commit_sm(
const std::vector<C2Param* const> ¶ms,
std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
(void)params;
(void)failures;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
- virtual status_t config_nb(
+ virtual C2Status config_nb(
const std::vector<C2Param* const> ¶ms,
std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
(void)params;
(void)failures;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
- virtual status_t createTunnel_sm(node_id targetComponent) {
+ virtual C2Status createTunnel_sm(node_id targetComponent) {
(void)targetComponent;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
- virtual status_t query_nb(
+ virtual C2Status query_nb(
const std::vector<C2Param* const> &stackParams,
const std::vector<C2Param::Index> &heapParamIndices,
std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
@@ -2466,9 +2466,9 @@
mMyParams.insert({mDomainInfo.type(), mDomainInfo});
}
- virtual status_t releaseTunnel_sm(node_id targetComponent) {
+ virtual C2Status releaseTunnel_sm(node_id targetComponent) {
(void)targetComponent;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
class MyParamReflector : public C2ParamReflector {
@@ -2490,17 +2490,19 @@
}
};
- virtual status_t getSupportedValues(
- const std::vector<const C2ParamField> &fields,
- std::vector<C2FieldSupportedValues>* const values) const {
- for (const C2ParamField &field : fields) {
- if (field == C2ParamField(&mDomainInfo, &C2ComponentDomainInfo::mValue)) {
- values->push_back(C2FieldSupportedValues(
+ virtual C2Status getSupportedValues(
+ std::vector<C2FieldSupportedValuesQuery> &fields) const {
+ for (C2FieldSupportedValuesQuery &query : fields) {
+ if (query.field == C2ParamField(&mDomainInfo, &C2ComponentDomainInfo::mValue)) {
+ query.values = C2FieldSupportedValues(
false /* flag */,
&mDomainInfo.mValue
//,
//{(int32_t)C2DomainVideo}
- ));
+ );
+ query.status = C2_OK;
+ } else {
+ query.status = C2_BAD_INDEX;
}
}
return C2_OK;
@@ -2510,13 +2512,13 @@
return std::shared_ptr<C2ParamReflector>(new MyParamReflector(this));
}
- virtual status_t getSupportedParams(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const {
+ virtual C2Status getSupportedParams(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const {
params->push_back(std::make_shared<C2ParamDescriptor>(
true /* required */, "_domain", &mDomainInfo));
return C2_OK;
}
- status_t getSupportedParams2(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) {
+ C2Status getSupportedParams2(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) {
params->push_back(std::shared_ptr<C2ParamDescriptor>(
new C2ParamDescriptor(true /* required */, "_domain", &mDomainInfo)));
return C2_OK;
@@ -2699,21 +2701,23 @@
TEST_F(C2ParamTest, ReflectorTest) {
C2ComponentDomainInfo domainInfo;
std::shared_ptr<C2ComponentInterface> comp(new MyComponentInstance);
- std::vector<C2FieldSupportedValues> values;
std::unique_ptr<C2StructDescriptor> desc{
comp->getParamReflector()->describe(C2ComponentDomainInfo::indexFlags)};
dumpStruct(*desc);
- EXPECT_EQ(
- C2_OK,
- comp->getSupportedValues(
- { C2ParamField(&domainInfo, &C2ComponentDomainInfo::mValue) },
- &values)
- );
+ std::vector<C2FieldSupportedValuesQuery> query = {
+ { C2ParamField(&domainInfo, &C2ComponentDomainInfo::mValue),
+ C2FieldSupportedValuesQuery::CURRENT },
+ C2FieldSupportedValuesQuery(C2ParamField(&domainInfo, &C2ComponentDomainInfo::mValue),
+ C2FieldSupportedValuesQuery::CURRENT),
+ C2FieldSupportedValuesQuery::Current(C2ParamField(&domainInfo, &C2ComponentDomainInfo::mValue)),
+ };
- for (const C2FieldSupportedValues &sv : values) {
- dumpFSV(sv, &domainInfo.mValue);
+ EXPECT_EQ(C2_OK, comp->getSupportedValues(query));
+
+ for (const C2FieldSupportedValuesQuery &q : query) {
+ dumpFSV(q.values, &domainInfo.mValue);
}
}
diff --git a/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp b/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
index a185880..8c78334 100644
--- a/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
+++ b/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
@@ -38,7 +38,7 @@
~C2BufferTest() = default;
void allocateLinear(size_t capacity) {
- C2Error err = mLinearAllocator->allocateLinearBuffer(
+ C2Status err = mLinearAllocator->allocateLinearBuffer(
capacity,
{ C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
&mLinearAllocation);
@@ -50,7 +50,7 @@
void mapLinear(size_t offset, size_t size, uint8_t **addr) {
ASSERT_TRUE(mLinearAllocation);
- C2Error err = mLinearAllocation->map(
+ C2Status err = mLinearAllocation->map(
offset,
size,
{ C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
@@ -82,7 +82,7 @@
}
void allocateGraphic(uint32_t width, uint32_t height) {
- C2Error err = mGraphicAllocator->allocateGraphicBuffer(
+ C2Status err = mGraphicAllocator->allocateGraphicBuffer(
width,
height,
HAL_PIXEL_FORMAT_YCBCR_420_888,
@@ -96,7 +96,7 @@
void mapGraphic(C2Rect rect, C2PlaneLayout *layout, uint8_t **addr) {
ASSERT_TRUE(mGraphicAllocation);
- C2Error err = mGraphicAllocation->map(
+ C2Status err = mGraphicAllocation->map(
rect,
{ C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
// TODO: fence
diff --git a/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp b/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
index baa6637..6530cc1 100644
--- a/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
@@ -38,14 +38,14 @@
using ::android::hardware::hidl_vec;
/* ===================================== GRALLOC ALLOCATION ==================================== */
-static C2Error maperr2error(Error maperr) {
+static C2Status maperr2error(Error maperr) {
switch (maperr) {
case Error::NONE: return C2_OK;
case Error::BAD_DESCRIPTOR: return C2_BAD_VALUE;
case Error::BAD_BUFFER: return C2_BAD_VALUE;
case Error::BAD_VALUE: return C2_BAD_VALUE;
case Error::NO_RESOURCES: return C2_NO_MEMORY;
- case Error::UNSUPPORTED: return C2_UNSUPPORTED;
+ case Error::UNSUPPORTED: return C2_CANNOT_DO;
}
return C2_CORRUPTED;
}
@@ -54,10 +54,10 @@
public:
virtual ~C2AllocationGralloc();
- virtual C2Error map(
+ virtual C2Status map(
C2Rect rect, C2MemoryUsage usage, int *fenceFd,
C2PlaneLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
- virtual C2Error unmap(C2Fence *fenceFd /* nullable */) override;
+ virtual C2Status unmap(C2Fence *fenceFd /* nullable */) override;
virtual bool isValid() const override { return true; }
virtual const C2Handle *handle() const override { return mHandle; }
virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override;
@@ -69,7 +69,7 @@
const sp<IMapper> &mapper,
hidl_handle &handle);
int dup() const;
- C2Error status() const;
+ C2Status status() const;
private:
const IMapper::BufferDescriptorInfo mInfo;
@@ -100,7 +100,7 @@
mMapper->freeBuffer(const_cast<native_handle_t *>(mBuffer));
}
-C2Error C2AllocationGralloc::map(
+C2Status C2AllocationGralloc::map(
C2Rect rect, C2MemoryUsage usage, int *fenceFd,
C2PlaneLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
// TODO
@@ -114,7 +114,7 @@
return C2_BAD_VALUE;
}
- C2Error err = C2_OK;
+ C2Status err = C2_OK;
if (!mBuffer) {
mMapper->importBuffer(
mHandle, [&err, this](const auto &maperr, const auto &buffer) {
@@ -195,16 +195,16 @@
return err;
}
// TODO
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
mLocked = true;
return C2_OK;
}
-C2Error C2AllocationGralloc::unmap(C2Fence *fenceFd /* nullable */) {
+C2Status C2AllocationGralloc::unmap(C2Fence *fenceFd /* nullable */) {
// TODO: fence
- C2Error err = C2_OK;
+ C2Status err = C2_OK;
mMapper->unlock(
const_cast<native_handle_t *>(mBuffer),
[&err, &fenceFd](const auto &maperr, const auto &releaseFence) {
@@ -231,18 +231,18 @@
public:
Impl();
- C2Error allocateGraphicBuffer(
+ C2Status allocateGraphicBuffer(
uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
std::shared_ptr<C2GraphicAllocation> *allocation);
- C2Error recreateGraphicBuffer(
+ C2Status recreateGraphicBuffer(
const C2Handle *handle,
std::shared_ptr<C2GraphicAllocation> *allocation);
- C2Error status() const { return mInit; }
+ C2Status status() const { return mInit; }
private:
- C2Error mInit;
+ C2Status mInit;
sp<IAllocator> mAllocator;
sp<IMapper> mMapper;
};
@@ -256,7 +256,7 @@
}
}
-C2Error C2AllocatorGralloc::Impl::allocateGraphicBuffer(
+C2Status C2AllocatorGralloc::Impl::allocateGraphicBuffer(
uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
std::shared_ptr<C2GraphicAllocation> *allocation) {
// TODO: buffer usage should be determined according to |usage|
@@ -269,7 +269,7 @@
(PixelFormat)format,
BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN,
};
- C2Error err = C2_OK;
+ C2Status err = C2_OK;
BufferDescriptor desc;
mMapper->createDescriptor(
info, [&err, &desc](const auto &maperr, const auto &descriptor) {
@@ -307,33 +307,33 @@
return C2_OK;
}
-C2Error C2AllocatorGralloc::Impl::recreateGraphicBuffer(
+C2Status C2AllocatorGralloc::Impl::recreateGraphicBuffer(
const C2Handle *handle,
std::shared_ptr<C2GraphicAllocation> *allocation) {
(void) handle;
// TODO: need to figure out BufferDescriptorInfo from the handle.
allocation->reset();
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
C2AllocatorGralloc::C2AllocatorGralloc() : mImpl(new Impl) {}
C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; }
-C2Error C2AllocatorGralloc::allocateGraphicBuffer(
+C2Status C2AllocatorGralloc::allocateGraphicBuffer(
uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
std::shared_ptr<C2GraphicAllocation> *allocation) {
return mImpl->allocateGraphicBuffer(width, height, format, usage, allocation);
}
-C2Error C2AllocatorGralloc::recreateGraphicBuffer(
+C2Status C2AllocatorGralloc::recreateGraphicBuffer(
const C2Handle *handle,
std::shared_ptr<C2GraphicAllocation> *allocation) {
return mImpl->recreateGraphicBuffer(handle, allocation);
}
-C2Error C2AllocatorGralloc::status() const {
+C2Status C2AllocatorGralloc::status() const {
return mImpl->status();
}
diff --git a/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp b/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
index 7aa7769..06b4874 100644
--- a/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
+++ b/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
@@ -82,10 +82,10 @@
/* ======================================= ION ALLOCATION ====================================== */
class C2AllocationIon : public C2LinearAllocation {
public:
- virtual C2Error map(
+ virtual C2Status map(
size_t offset, size_t size, C2MemoryUsage usage, int *fence,
void **addr /* nonnull */);
- virtual C2Error unmap(void *addr, size_t size, int *fenceFd);
+ virtual C2Status unmap(void *addr, size_t size, int *fenceFd);
virtual bool isValid() const;
virtual ~C2AllocationIon();
virtual const C2Handle *handle() const;
@@ -95,7 +95,7 @@
C2AllocationIon(int ionFd, size_t size, size_t align, unsigned heapMask, unsigned flags);
C2AllocationIon(int ionFd, size_t size, int shareFd);
int dup() const;
- C2Error status() const;
+ C2Status status() const;
protected:
class Impl;
@@ -121,18 +121,28 @@
}
Impl(int ionFd, size_t capacity, int shareFd)
- : mHandle(ionFd, -1),
+ : mInit(C2_OK),
+ mHandle(ionFd, -1),
mMapFd(-1),
mCapacity(capacity) {
ion_user_handle_t buffer;
- mInit = ion_import(mHandle.ionFd(), shareFd, &buffer);
- if (mInit == 0) {
+ int ret = ion_import(mHandle.ionFd(), shareFd, &buffer);
+ switch (-ret) {
+ case 0:
mHandle.setBuffer(buffer);
+ break;
+ case EBADF: // bad ion handle - should not happen
+ case ENOTTY: // bad ion driver
+ mInit = C2_CORRUPTED;
+ break;
+ default:
+ mInit = c2_map_errno<ENOMEM, EACCES, EINVAL>(-ret);
+ break;
}
(void)mCapacity; // TODO
}
- C2Error map(size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
+ C2Status map(size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
(void)fenceFd; // TODO: wait for fence
*addr = nullptr;
int prot = PROT_NONE;
@@ -149,7 +159,7 @@
size_t mapOffset = offset - alignmentBytes;
size_t mapSize = size + alignmentBytes;
- C2Error err = C2_OK;
+ C2Status err = C2_OK;
if (mMapFd == -1) {
int ret = ion_map(mHandle.ionFd(), mHandle.buffer(), mapSize, prot,
flags, mapOffset, (unsigned char**)&mMapAddr, &mMapFd);
@@ -176,7 +186,7 @@
return err;
}
- C2Error unmap(void *addr, size_t size, int *fenceFd) {
+ C2Status unmap(void *addr, size_t size, int *fenceFd) {
if (addr != (uint8_t *)mMapAddr + mMapAlignmentBytes ||
size + mMapAlignmentBytes != mMapSize) {
return C2_BAD_VALUE;
@@ -200,7 +210,7 @@
(void)ion_free(mHandle.ionFd(), mHandle.buffer());
}
- C2Error status() const {
+ C2Status status() const {
return mInit;
}
@@ -217,7 +227,7 @@
}
private:
- C2Error mInit;
+ C2Status mInit;
C2HandleIon mHandle;
int mMapFd; // only one for now
void *mMapAddr;
@@ -226,12 +236,12 @@
size_t mCapacity;
};
-C2Error C2AllocationIon::map(
+C2Status C2AllocationIon::map(
size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
return mImpl->map(offset, size, usage, fenceFd, addr);
}
-C2Error C2AllocationIon::unmap(void *addr, size_t size, int *fenceFd) {
+C2Status C2AllocationIon::unmap(void *addr, size_t size, int *fenceFd) {
return mImpl->unmap(addr, size, fenceFd);
}
@@ -239,7 +249,7 @@
return mImpl->status() == C2_OK;
}
-C2Error C2AllocationIon::status() const {
+C2Status C2AllocationIon::status() const {
return mImpl->status();
}
@@ -272,7 +282,7 @@
C2AllocatorIon::C2AllocatorIon() : mInit(C2_OK), mIonFd(ion_open()) {
if (mIonFd < 0) {
switch (errno) {
- case ENOENT: mInit = C2_UNSUPPORTED; break;
+ case ENOENT: mInit = C2_OMITTED; break;
default: mInit = c2_map_errno<EACCES>(errno); break;
}
}
@@ -284,7 +294,7 @@
}
}
-C2Error C2AllocatorIon::allocateLinearBuffer(
+C2Status C2AllocatorIon::allocateLinearBuffer(
uint32_t capacity, C2MemoryUsage usage, std::shared_ptr<C2LinearAllocation> *allocation) {
if (allocation == nullptr) {
return C2_BAD_VALUE;
@@ -292,7 +302,7 @@
allocation->reset();
if (mInit != C2_OK) {
- return C2_UNSUPPORTED;
+ return mInit;
}
// get align, heapMask and flags
@@ -311,18 +321,18 @@
std::shared_ptr<C2AllocationIon> alloc
= std::make_shared<C2AllocationIon>(mIonFd, capacity, align, heapMask, flags);
- C2Error ret = alloc->status();
+ C2Status ret = alloc->status();
if (ret == C2_OK) {
*allocation = alloc;
}
return ret;
}
-C2Error C2AllocatorIon::recreateLinearBuffer(
+C2Status C2AllocatorIon::recreateLinearBuffer(
const C2Handle *handle, std::shared_ptr<C2LinearAllocation> *allocation) {
*allocation = nullptr;
if (mInit != C2_OK) {
- return C2_UNSUPPORTED;
+ return mInit;
}
if (!C2HandleIon::isValid(handle)) {
@@ -333,7 +343,7 @@
const C2HandleIon *h = static_cast<const C2HandleIon*>(handle);
std::shared_ptr<C2AllocationIon> alloc
= std::make_shared<C2AllocationIon>(mIonFd, 0 /* capacity */, h->buffer());
- C2Error ret = alloc->status();
+ C2Status ret = alloc->status();
if (ret == C2_OK) {
*allocation = alloc;
}
diff --git a/media/libstagefright/codec2/vndk/C2Buffer.cpp b/media/libstagefright/codec2/vndk/C2Buffer.cpp
index 1ffbf49..d3f0d70 100644
--- a/media/libstagefright/codec2/vndk/C2Buffer.cpp
+++ b/media/libstagefright/codec2/vndk/C2Buffer.cpp
@@ -129,26 +129,26 @@
explicit Impl(const uint8_t *data)
: mData(data), mError(C2_OK) {}
- explicit Impl(C2Error error)
+ explicit Impl(C2Status error)
: mData(nullptr), mError(error) {}
const uint8_t *data() const {
return mData;
}
- C2Error error() const {
+ C2Status error() const {
return mError;
}
private:
const uint8_t *mData;
- C2Error mError;
+ C2Status mError;
};
C2ReadView::C2ReadView(const _C2LinearCapacityAspect *parent, const uint8_t *data)
: _C2LinearCapacityAspect(parent), mImpl(std::make_shared<Impl>(data)) {}
-C2ReadView::C2ReadView(C2Error error)
+C2ReadView::C2ReadView(C2Status error)
: _C2LinearCapacityAspect(0u), mImpl(std::make_shared<Impl>(error)) {}
const uint8_t *C2ReadView::data() const {
@@ -167,7 +167,7 @@
return C2ReadView(&newCapacity, data() + offset);
}
-C2Error C2ReadView::error() {
+C2Status C2ReadView::error() const {
return mImpl->error();
}
@@ -176,33 +176,33 @@
explicit Impl(uint8_t *base)
: mBase(base), mError(C2_OK) {}
- explicit Impl(C2Error error)
+ explicit Impl(C2Status error)
: mBase(nullptr), mError(error) {}
uint8_t *base() const {
return mBase;
}
- C2Error error() const {
+ C2Status error() const {
return mError;
}
private:
uint8_t *mBase;
- C2Error mError;
+ C2Status mError;
};
C2WriteView::C2WriteView(const _C2LinearRangeAspect *parent, uint8_t *base)
: _C2EditableLinearRange(parent), mImpl(std::make_shared<Impl>(base)) {}
-C2WriteView::C2WriteView(C2Error error)
+C2WriteView::C2WriteView(C2Status error)
: _C2EditableLinearRange(nullptr), mImpl(std::make_shared<Impl>(error)) {}
uint8_t *C2WriteView::base() { return mImpl->base(); }
uint8_t *C2WriteView::data() { return mImpl->base() + offset(); }
-C2Error C2WriteView::error() { return mImpl->error(); }
+C2Status C2WriteView::error() const { return mImpl->error(); }
class C2ConstLinearBlock::Impl {
public:
@@ -212,7 +212,7 @@
~Impl() {
if (mBase != nullptr) {
// TODO: fence
- C2Error err = mAllocation->unmap(mBase, mSize, nullptr);
+ C2Status err = mAllocation->unmap(mBase, mSize, nullptr);
if (err != C2_OK) {
// TODO: Log?
}
@@ -238,13 +238,13 @@
const uint8_t *base() const { return mBase; }
- C2Error error() const { return mError; }
+ C2Status error() const { return mError; }
private:
std::shared_ptr<C2LinearAllocation> mAllocation;
uint8_t *mBase;
size_t mSize;
- C2Error mError;
+ C2Status mError;
};
C2ConstLinearBlock::C2ConstLinearBlock(std::shared_ptr<C2LinearAllocation> alloc)
@@ -277,7 +277,7 @@
~Impl() {
if (mBase != nullptr) {
// TODO: fence
- C2Error err = mAllocation->unmap(mBase, mSize, nullptr);
+ C2Status err = mAllocation->unmap(mBase, mSize, nullptr);
if (err != C2_OK) {
// TODO: Log?
}
@@ -309,7 +309,7 @@
uint8_t *base() const { return mBase; }
- C2Error error() const { return mError; }
+ C2Status error() const { return mError; }
C2Fence fence() const { return mFence; }
@@ -317,7 +317,7 @@
std::shared_ptr<C2LinearAllocation> mAllocation;
uint8_t *mBase;
size_t mSize;
- C2Error mError;
+ C2Status mError;
C2Fence mFence;
};
@@ -349,14 +349,14 @@
const std::shared_ptr<C2Allocator> &allocator)
: mAllocator(allocator) {}
-C2Error C2DefaultBlockAllocator::allocateLinearBlock(
+C2Status C2DefaultBlockAllocator::allocateLinearBlock(
uint32_t capacity,
C2MemoryUsage usage,
std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
block->reset();
std::shared_ptr<C2LinearAllocation> alloc;
- C2Error err = mAllocator->allocateLinearBuffer(capacity, usage, &alloc);
+ C2Status err = mAllocator->allocateLinearBuffer(capacity, usage, &alloc);
if (err != C2_OK) {
return err;
}
@@ -392,16 +392,16 @@
public:
Impl(uint8_t *const *data, const C2PlaneLayout &layout)
: mData(data), mLayout(layout), mError(C2_OK) {}
- explicit Impl(C2Error error) : mData(nullptr), mError(error) {}
+ explicit Impl(C2Status error) : mData(nullptr), mError(error) {}
uint8_t *const *data() const { return mData; }
const C2PlaneLayout &layout() const { return mLayout; }
- C2Error error() const { return mError; }
+ C2Status error() const { return mError; }
private:
uint8_t *const *mData;
C2PlaneLayout mLayout;
- C2Error mError;
+ C2Status mError;
};
C2GraphicView::C2GraphicView(
@@ -410,7 +410,7 @@
const C2PlaneLayout& layout)
: _C2PlanarSection(parent), mImpl(new Impl(data, layout)) {}
-C2GraphicView::C2GraphicView(C2Error error)
+C2GraphicView::C2GraphicView(C2Status error)
: _C2PlanarSection(nullptr), mImpl(new Impl(error)) {}
const uint8_t *const *C2GraphicView::data() const {
@@ -437,7 +437,7 @@
return view;
}
-C2Error C2GraphicView::error() const {
+C2Status C2GraphicView::error() const {
return mImpl->error();
}
@@ -453,12 +453,12 @@
}
}
- C2Error map(C2Rect rect) {
+ C2Status map(C2Rect rect) {
if (mData[0] != nullptr) {
// Already mapped.
return C2_OK;
}
- C2Error err = mAllocation->map(
+ C2Status err = mAllocation->map(
rect,
{ C2MemoryUsage::kSoftwareRead, 0 },
nullptr,
@@ -493,7 +493,7 @@
: C2Block2D(alloc), mImpl(new Impl(alloc)), mFence(fence) {}
C2Acquirable<const C2GraphicView> C2ConstGraphicBlock::map() const {
- C2Error err = mImpl->map(crop());
+ C2Status err = mImpl->map(crop());
if (err != C2_OK) {
C2DefaultGraphicView view(err);
return C2AcquirableConstGraphicView(err, mFence, view);
@@ -518,13 +518,13 @@
}
}
- C2Error map(C2Rect rect) {
+ C2Status map(C2Rect rect) {
if (mData[0] != nullptr) {
// Already mapped.
return C2_OK;
}
uint8_t *data[C2PlaneLayout::MAX_NUM_PLANES];
- C2Error err = mAllocation->map(
+ C2Status err = mAllocation->map(
rect,
{ C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
nullptr,
@@ -560,7 +560,7 @@
: C2Block2D(alloc), mImpl(new Impl(alloc)) {}
C2Acquirable<C2GraphicView> C2GraphicBlock::map() {
- C2Error err = mImpl->map(crop());
+ C2Status err = mImpl->map(crop());
if (err != C2_OK) {
C2DefaultGraphicView view(err);
// TODO: fence
@@ -579,7 +579,7 @@
const std::shared_ptr<C2Allocator> &allocator)
: mAllocator(allocator) {}
-C2Error C2DefaultGraphicBlockAllocator::allocateGraphicBlock(
+C2Status C2DefaultGraphicBlockAllocator::allocateGraphicBlock(
uint32_t width,
uint32_t height,
uint32_t format,
@@ -588,7 +588,7 @@
block->reset();
std::shared_ptr<C2GraphicAllocation> alloc;
- C2Error err = mAllocator->allocateGraphicBuffer(width, height, format, usage, &alloc);
+ C2Status err = mAllocator->allocateGraphicBuffer(width, height, format, usage, &alloc);
if (err != C2_OK) {
return err;
}
@@ -650,7 +650,7 @@
const C2BufferData &data() const { return mData; }
- C2Error registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
+ C2Status registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
auto it = std::find_if(
mNotify.begin(), mNotify.end(),
[onDestroyNotify, arg] (const auto &pair) {
@@ -663,7 +663,7 @@
return C2_OK;
}
- C2Error unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
+ C2Status unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
auto it = std::find_if(
mNotify.begin(), mNotify.end(),
[onDestroyNotify, arg] (const auto &pair) {
@@ -684,7 +684,7 @@
return result;
}
- C2Error setInfo(const std::shared_ptr<C2Info> &info) {
+ C2Status setInfo(const std::shared_ptr<C2Info> &info) {
// To "update" you need to erase the existing one if any, and then insert.
(void) mInfos.erase(info->type());
(void) mInfos.insert({ info->type(), info });
@@ -720,11 +720,11 @@
const C2BufferData C2Buffer::data() const { return mImpl->data(); }
-C2Error C2Buffer::registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
+C2Status C2Buffer::registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
return mImpl->registerOnDestroyNotify(onDestroyNotify, arg);
}
-C2Error C2Buffer::unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
+C2Status C2Buffer::unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg) {
return mImpl->unregisterOnDestroyNotify(onDestroyNotify, arg);
}
@@ -732,7 +732,7 @@
return mImpl->infos();
}
-C2Error C2Buffer::setInfo(const std::shared_ptr<C2Info> &info) {
+C2Status C2Buffer::setInfo(const std::shared_ptr<C2Info> &info) {
return mImpl->setInfo(info);
}
diff --git a/media/libstagefright/codec2/vndk/C2Store.cpp b/media/libstagefright/codec2/vndk/C2Store.cpp
index f21a3f0..42bdf0e 100644
--- a/media/libstagefright/codec2/vndk/C2Store.cpp
+++ b/media/libstagefright/codec2/vndk/C2Store.cpp
@@ -35,7 +35,7 @@
C2PlatformAllocatorStore(
/* ionmapper */
);
- virtual status_t createAllocator(ID id, std::shared_ptr<C2Allocator> *const allocator);
+ virtual C2Status createAllocator(ID id, std::shared_ptr<C2Allocator> *const allocator);
private:
// returns a shared-singleton ion allocator
@@ -48,7 +48,7 @@
C2PlatformAllocatorStore::C2PlatformAllocatorStore() {
}
-status_t C2PlatformAllocatorStore::createAllocator(
+C2Status C2PlatformAllocatorStore::createAllocator(
ID id, std::shared_ptr<C2Allocator> *const allocator) {
allocator->reset();
switch (id) {
diff --git a/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h b/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
index 94f74c8..9bfd987 100644
--- a/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
+++ b/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
@@ -30,17 +30,17 @@
typedef std::function<int (C2MemoryUsage, size_t,
/* => */ size_t*, unsigned*, unsigned*)> usage_mapper_fn;
- virtual C2Error allocateGraphicBuffer(
+ virtual C2Status allocateGraphicBuffer(
uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
std::shared_ptr<C2GraphicAllocation> *allocation) override;
- virtual C2Error recreateGraphicBuffer(
+ virtual C2Status recreateGraphicBuffer(
const C2Handle *handle,
std::shared_ptr<C2GraphicAllocation> *allocation) override;
C2AllocatorGralloc();
- C2Error status() const;
+ C2Status status() const;
virtual ~C2AllocatorGralloc();
diff --git a/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h b/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
index a453a7d..00c33fe 100644
--- a/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
+++ b/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
@@ -29,22 +29,22 @@
typedef std::function<int (C2MemoryUsage, size_t,
/* => */ size_t*, unsigned*, unsigned*)> usage_mapper_fn;
- virtual C2Error allocateLinearBuffer(
+ virtual C2Status allocateLinearBuffer(
uint32_t capacity, C2MemoryUsage usage,
std::shared_ptr<C2LinearAllocation> *allocation) override;
- virtual C2Error recreateLinearBuffer(
+ virtual C2Status recreateLinearBuffer(
const C2Handle *handle,
std::shared_ptr<C2LinearAllocation> *allocation) override;
C2AllocatorIon();
- C2Error status() const { return mInit; }
+ C2Status status() const { return mInit; }
virtual ~C2AllocatorIon();
private:
- C2Error mInit;
+ C2Status mInit;
int mIonFd;
usage_mapper_fn mUsageMapper;
};
diff --git a/media/libstagefright/codec2/vndk/include/C2BufferPriv.h b/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
index 6a8f94e..f1e8acb 100644
--- a/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
+++ b/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
@@ -29,7 +29,7 @@
virtual ~C2DefaultBlockAllocator() = default;
- virtual C2Error allocateLinearBlock(
+ virtual C2Status allocateLinearBlock(
uint32_t capacity,
C2MemoryUsage usage,
std::shared_ptr<C2LinearBlock> *block /* nonnull */) override;
@@ -45,7 +45,7 @@
virtual ~C2DefaultGraphicBlockAllocator() = default;
- virtual C2Error allocateGraphicBlock(
+ virtual C2Status allocateGraphicBlock(
uint32_t width,
uint32_t height,
uint32_t format,
diff --git a/media/libstagefright/codec2/vndk/include/C2ErrnoUtils.h b/media/libstagefright/codec2/vndk/include/C2ErrnoUtils.h
index f834cdb..aea3a6f 100644
--- a/media/libstagefright/codec2/vndk/include/C2ErrnoUtils.h
+++ b/media/libstagefright/codec2/vndk/include/C2ErrnoUtils.h
@@ -23,32 +23,32 @@
namespace android {
// standard ERRNO mappings
-template<int N> constexpr C2Error _c2_errno2error_impl();
-template<> constexpr C2Error _c2_errno2error_impl<0>() { return C2_OK; }
-template<> constexpr C2Error _c2_errno2error_impl<EINVAL>() { return C2_BAD_VALUE; }
-template<> constexpr C2Error _c2_errno2error_impl<EACCES>() { return C2_NO_PERMISSION; }
-template<> constexpr C2Error _c2_errno2error_impl<EPERM>() { return C2_NO_PERMISSION; }
-template<> constexpr C2Error _c2_errno2error_impl<ENOMEM>() { return C2_NO_MEMORY; }
+template<int N> constexpr C2Status _c2_errno2status_impl();
+template<> constexpr C2Status _c2_errno2status_impl<0>() { return C2_OK; }
+template<> constexpr C2Status _c2_errno2status_impl<EINVAL>() { return C2_BAD_VALUE; }
+template<> constexpr C2Status _c2_errno2status_impl<EACCES>() { return C2_REFUSED; }
+template<> constexpr C2Status _c2_errno2status_impl<EPERM>() { return C2_REFUSED; }
+template<> constexpr C2Status _c2_errno2status_impl<ENOMEM>() { return C2_NO_MEMORY; }
-// map standard errno-s to the equivalent C2Error
+// map standard errno-s to the equivalent C2Status
template<int... N> struct _c2_map_errno_impl;
template<int E, int ... N> struct _c2_map_errno_impl<E, N...> {
- static C2Error map(int result) {
+ static C2Status map(int result) {
if (result == E) {
- return _c2_errno2error_impl<E>();
+ return _c2_errno2status_impl <E>();
} else {
return _c2_map_errno_impl<N...>::map(result);
}
}
};
template<> struct _c2_map_errno_impl<> {
- static C2Error map(int result) {
+ static C2Status map(int result) {
return result == 0 ? C2_OK : C2_CORRUPTED;
}
};
template<int... N>
-C2Error c2_map_errno(int result) {
+C2Status c2_map_errno(int result) {
return _c2_map_errno_impl<N...>::map(result);
}
diff --git a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
index 5f55e1e..77db255 100644
--- a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
+++ b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
@@ -94,11 +94,15 @@
bool validateField(
const C2FieldSupportedValues &supportedValues, const T &value) {
switch (supportedValues.type) {
+ case C2FieldSupportedValues::EMPTY:
+ {
+ return false;
+ }
case C2FieldSupportedValues::RANGE:
{
// TODO: handle step, nom, denom
- return Getter<T>::get(supportedValues.range.min) < value
- && value < Getter<T>::get(supportedValues.range.max);
+ return Getter<T>::get(supportedValues.range.min) <= value
+ && value <= Getter<T>::get(supportedValues.range.max);
}
case C2FieldSupportedValues::VALUES:
{
@@ -153,7 +157,7 @@
const C2FieldSupportedValues &supportedValues = mSupportedValues.at(field).supported;
if (!validateField(supportedValues, param->mValue)) {
return std::unique_ptr<C2SettingResult>(
- new C2SettingResult {field, C2SettingResult::BAD_VALUE, nullptr, {}});
+ new C2SettingResult {C2SettingResult::BAD_VALUE, {field, nullptr}, {}});
}
return nullptr;
}
@@ -171,13 +175,13 @@
const C2FieldSupportedValues &supportedWidth = mSupportedValues.at(field).supported;
if (!validateField(supportedWidth, param->mWidth)) {
return std::unique_ptr<C2SettingResult>(
- new C2SettingResult {field, C2SettingResult::BAD_VALUE, nullptr, {}});
+ new C2SettingResult {C2SettingResult::BAD_VALUE, {field, nullptr}, {}});
}
field = C2ParamField(param, &T::mHeight);
const C2FieldSupportedValues &supportedHeight = mSupportedValues.at(field).supported;
if (!validateField(supportedHeight, param->mHeight)) {
return std::unique_ptr<C2SettingResult>(
- new C2SettingResult {field, C2SettingResult::BAD_VALUE, nullptr, {}});
+ new C2SettingResult {C2SettingResult::BAD_VALUE, {field, nullptr}, {}});
}
return nullptr;
}
@@ -191,7 +195,7 @@
T* param = (T*)c2param;
if (strncmp(param->m.mValue, mExpected, param->flexCount()) != 0) {
return std::unique_ptr<C2SettingResult>(
- new C2SettingResult {C2ParamField(param, &T::m), C2SettingResult::BAD_VALUE, nullptr, {}});
+ new C2SettingResult {C2SettingResult::BAD_VALUE, {C2ParamField(param, &T::m), nullptr}, {}});
}
return nullptr;
}
@@ -428,7 +432,7 @@
return mId;
}
-status_t C2SoftAvcDecIntf::query_nb(
+C2Status C2SoftAvcDecIntf::query_nb(
const std::vector<C2Param* const> & stackParams,
const std::vector<C2Param::Index> & heapParamIndices,
std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
@@ -461,10 +465,10 @@
return C2_OK;
}
-status_t C2SoftAvcDecIntf::config_nb(
+C2Status C2SoftAvcDecIntf::config_nb(
const std::vector<C2Param* const> ¶ms,
std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
- status_t err = C2_OK;
+ C2Status err = C2_OK;
for (C2Param *param : params) {
uint32_t index = restoreIndex(param);
if (mParams.count(index) == 0) {
@@ -485,45 +489,48 @@
return err;
}
-status_t C2SoftAvcDecIntf::commit_sm(
+C2Status C2SoftAvcDecIntf::commit_sm(
const std::vector<C2Param* const> ¶ms,
std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
// TODO
return config_nb(params, failures);
}
-status_t C2SoftAvcDecIntf::createTunnel_sm(node_id targetComponent) {
+C2Status C2SoftAvcDecIntf::createTunnel_sm(node_id targetComponent) {
// Tunneling is not supported
(void) targetComponent;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
-status_t C2SoftAvcDecIntf::releaseTunnel_sm(node_id targetComponent) {
+C2Status C2SoftAvcDecIntf::releaseTunnel_sm(node_id targetComponent) {
// Tunneling is not supported
(void) targetComponent;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
std::shared_ptr<C2ParamReflector> C2SoftAvcDecIntf::getParamReflector() const {
return mParamReflector;
}
-status_t C2SoftAvcDecIntf::getSupportedParams(
+C2Status C2SoftAvcDecIntf::getSupportedParams(
std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const {
params->insert(params->begin(), mParamDescs.begin(), mParamDescs.end());
return C2_OK;
}
-status_t C2SoftAvcDecIntf::getSupportedValues(
- const std::vector<const C2ParamField> &fields,
- std::vector<C2FieldSupportedValues>* const values) const {
- for (const auto &field : fields) {
- if (mSupportedValues.count(field) == 0) {
- return BAD_VALUE;
+C2Status C2SoftAvcDecIntf::getSupportedValues(
+ std::vector<C2FieldSupportedValuesQuery> &fields) const {
+ C2Status res = C2_OK;
+ for (C2FieldSupportedValuesQuery &query : fields) {
+ if (mSupportedValues.count(query.field) == 0) {
+ query.status = C2_BAD_INDEX;
+ res = C2_BAD_INDEX;
+ } else {
+ query.status = C2_OK;
+ query.values = mSupportedValues.at(query.field).supported;
}
- values->push_back(mSupportedValues.at(field).supported);
}
- return C2_OK;
+ return res;
}
void C2SoftAvcDecIntf::updateSupportedValues() {
@@ -644,7 +651,7 @@
CHECK_EQ(deInitDecoder(), (status_t)OK);
}
-status_t C2SoftAvcDec::queue_nb(
+C2Status C2SoftAvcDec::queue_nb(
std::list<std::unique_ptr<C2Work>>* const items) {
if (!mThread->isRunning()) {
return C2_CORRUPTED;
@@ -659,13 +666,13 @@
return C2_OK;
}
-status_t C2SoftAvcDec::announce_nb(const std::vector<C2WorkOutline> &items) {
+C2Status C2SoftAvcDec::announce_nb(const std::vector<C2WorkOutline> &items) {
// Tunneling is not supported
(void) items;
- return C2_UNSUPPORTED;
+ return C2_OMITTED;
}
-status_t C2SoftAvcDec::flush_sm(
+C2Status C2SoftAvcDec::flush_sm(
bool flushThrough, std::list<std::unique_ptr<C2Work>>* const flushedWork) {
// Tunneling is not supported
(void) flushThrough;
@@ -691,7 +698,7 @@
return C2_OK;
}
-status_t C2SoftAvcDec::drain_nb(bool drainThrough) {
+C2Status C2SoftAvcDec::drain_nb(bool drainThrough) {
// Tunneling is not supported
(void) drainThrough;
@@ -707,14 +714,14 @@
return C2_OK;
}
-status_t C2SoftAvcDec::start() {
+C2Status C2SoftAvcDec::start() {
if (!mThread->isRunning()) {
mThread->start(shared_from_this());
}
return C2_OK;
}
-status_t C2SoftAvcDec::stop() {
+C2Status C2SoftAvcDec::stop() {
ALOGV("stop");
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::chrono::system_clock::time_point deadline = now + std::chrono::milliseconds(500);
diff --git a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
index 6a83d1d..cc33083 100644
--- a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
+++ b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
@@ -85,24 +85,23 @@
// From C2ComponentInterface
virtual C2String getName() const override;
virtual node_id getId() const override;
- virtual status_t query_nb(
+ virtual C2Status query_nb(
const std::vector<C2Param* const> &stackParams,
const std::vector<C2Param::Index> &heapParamIndices,
std::vector<std::unique_ptr<C2Param>>* const heapParams) const override;
- virtual status_t config_nb(
+ virtual C2Status config_nb(
const std::vector<C2Param* const> ¶ms,
std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
- virtual status_t commit_sm(
+ virtual C2Status commit_sm(
const std::vector<C2Param* const> ¶ms,
std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
- virtual status_t createTunnel_sm(node_id targetComponent) override;
- virtual status_t releaseTunnel_sm(node_id targetComponent) override;
+ virtual C2Status createTunnel_sm(node_id targetComponent) override;
+ virtual C2Status releaseTunnel_sm(node_id targetComponent) override;
virtual std::shared_ptr<C2ParamReflector> getParamReflector() const override;
- virtual status_t getSupportedParams(
+ virtual C2Status getSupportedParams(
std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const override;
- virtual status_t getSupportedValues(
- const std::vector<const C2ParamField> &fields,
- std::vector<C2FieldSupportedValues>* const values) const override;
+ virtual C2Status getSupportedValues(
+ std::vector<C2FieldSupportedValuesQuery> &fields) const override;
private:
class ParamReflector;
@@ -150,13 +149,13 @@
virtual ~C2SoftAvcDec();
// From C2Component
- virtual status_t queue_nb(std::list<std::unique_ptr<C2Work>>* const items) override;
- virtual status_t announce_nb(const std::vector<C2WorkOutline> &items) override;
- virtual status_t flush_sm(
+ virtual C2Status queue_nb(std::list<std::unique_ptr<C2Work>>* const items) override;
+ virtual C2Status announce_nb(const std::vector<C2WorkOutline> &items) override;
+ virtual C2Status flush_sm(
bool flushThrough, std::list<std::unique_ptr<C2Work>>* const flushedWork) override;
- virtual status_t drain_nb(bool drainThrough) override;
- virtual status_t start() override;
- virtual status_t stop() override;
+ virtual C2Status drain_nb(bool drainThrough) override;
+ virtual C2Status start() override;
+ virtual C2Status stop() override;
virtual void reset() override;
virtual void release() override;
virtual std::shared_ptr<C2ComponentInterface> intf() override;
@@ -228,9 +227,9 @@
bool mChangingResolution;
bool mFlushNeeded;
bool mSignalledError;
- int32_t mWidth;
- int32_t mHeight;
- int32_t mStride;
+ uint32_t mWidth;
+ uint32_t mHeight;
+ uint32_t mStride;
size_t mInputOffset;
void processQueue();
diff --git a/media/libstagefright/filters/Android.bp b/media/libstagefright/filters/Android.bp
index a0af4f6..e944224 100644
--- a/media/libstagefright/filters/Android.bp
+++ b/media/libstagefright/filters/Android.bp
@@ -13,12 +13,8 @@
"ZeroFilter.cpp",
],
- header_libs: [
- "media_plugin_headers",
- ],
-
- export_header_lib_headers: [
- "media_plugin_headers",
+ include_dirs: [
+ "frameworks/native/include/media/openmax",
],
cflags: [
diff --git a/media/libstagefright/include/OmxNodeOwner.h b/media/libstagefright/include/OmxNodeOwner.h
new file mode 100644
index 0000000..64ec7f7
--- /dev/null
+++ b/media/libstagefright/include/OmxNodeOwner.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * 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 OMX_NODE_OWNER_H_
+
+#define OMX_NODE_OWNER_H_
+
+namespace android {
+
+struct OMXNodeInstance;
+
+/**
+ * This struct is needed to separate OMX from OMXNodeInstance.
+ *
+ * TODO: This might not be needed after Treble transition is complete.
+ */
+struct OmxNodeOwner {
+ virtual status_t freeNode(const sp<OMXNodeInstance> &instance) = 0;
+ virtual ~OmxNodeOwner() {}
+};
+
+}
+
+#endif // OMX_NODE_OWNER_H_
diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h
index d1a9d25..424246d 100644
--- a/media/libstagefright/include/media/stagefright/ACodec.h
+++ b/media/libstagefright/include/media/stagefright/ACodec.h
@@ -95,6 +95,11 @@
static status_t getOMXChannelMapping(size_t numChannels, OMX_AUDIO_CHANNELTYPE map[]);
+ // Save the flag.
+ void setTrebleFlag(bool trebleFlag);
+ // Return the saved flag.
+ bool getTrebleFlag() const;
+
protected:
virtual ~ACodec();
@@ -228,7 +233,9 @@
sp<IOMX> mOMX;
sp<IOMXNode> mOMXNode;
int32_t mNodeGeneration;
+ bool mTrebleFlag;
sp<TAllocator> mAllocator[2];
+ sp<MemoryDealer> mDealer[2];
bool mUsingNativeWindow;
sp<ANativeWindow> mNativeWindow;
diff --git a/media/libstagefright/include/media/stagefright/OMXClient.h b/media/libstagefright/include/media/stagefright/OMXClient.h
index e7b9be5..b1864b8 100644
--- a/media/libstagefright/include/media/stagefright/OMXClient.h
+++ b/media/libstagefright/include/media/stagefright/OMXClient.h
@@ -18,19 +18,25 @@
#define OMX_CLIENT_H_
-namespace android {
+#include <media/IOMX.h>
-class IOMX;
+namespace android {
class OMXClient {
public:
OMXClient();
- status_t connect(const char* name = "default");
+ status_t connect();
+ status_t connect(bool* trebleFlag);
+ status_t connect(const char* name, bool* trebleFlag = nullptr);
+ status_t connectLegacy();
+ status_t connectTreble(const char* name = "default");
void disconnect();
- sp<IOMX> interface();
+ sp<IOMX> interface() {
+ return mOMX;
+ }
private:
sp<IOMX> mOMX;
diff --git a/media/libstagefright/omx/Android.bp b/media/libstagefright/omx/Android.bp
index 8539864..f388a48 100644
--- a/media/libstagefright/omx/Android.bp
+++ b/media/libstagefright/omx/Android.bp
@@ -9,6 +9,8 @@
"FrameDropper.cpp",
"GraphicBufferSource.cpp",
"BWGraphicBufferSource.cpp",
+ "OMX.cpp",
+ "OMXStore.cpp",
"OMXMaster.cpp",
"OMXNodeInstance.cpp",
"OMXUtils.cpp",
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
new file mode 100644
index 0000000..09c4019
--- /dev/null
+++ b/media/libstagefright/omx/OMX.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 <inttypes.h>
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "OMX"
+#include <utils/Log.h>
+
+#include <dlfcn.h>
+
+#include <media/stagefright/omx/OMX.h>
+#include <media/stagefright/omx/OMXNodeInstance.h>
+#include <media/stagefright/omx/BWGraphicBufferSource.h>
+#include <media/stagefright/omx/OMXMaster.h>
+#include <media/stagefright/omx/OMXUtils.h>
+#include <media/stagefright/foundation/ADebug.h>
+
+namespace android {
+
+// node ids are created by concatenating the pid with a 16-bit counter
+static size_t kMaxNodeInstances = (1 << 16);
+
+OMX::OMX() : mMaster(new OMXMaster), mParser() {
+}
+
+OMX::~OMX() {
+ delete mMaster;
+ mMaster = NULL;
+}
+
+void OMX::binderDied(const wp<IBinder> &the_late_who) {
+ sp<OMXNodeInstance> instance;
+
+ {
+ Mutex::Autolock autoLock(mLock);
+
+ ssize_t index = mLiveNodes.indexOfKey(the_late_who);
+
+ if (index < 0) {
+ ALOGE("b/27597103, nonexistent observer on binderDied");
+ android_errorWriteLog(0x534e4554, "27597103");
+ return;
+ }
+
+ instance = mLiveNodes.editValueAt(index);
+ mLiveNodes.removeItemsAt(index);
+ }
+
+ instance->onObserverDied();
+}
+
+status_t OMX::listNodes(List<ComponentInfo> *list) {
+ list->clear();
+
+ OMX_U32 index = 0;
+ char componentName[256];
+ while (mMaster->enumerateComponents(
+ componentName, sizeof(componentName), index) == OMX_ErrorNone) {
+ list->push_back(ComponentInfo());
+ ComponentInfo &info = *--list->end();
+
+ info.mName = componentName;
+
+ Vector<String8> roles;
+ OMX_ERRORTYPE err =
+ mMaster->getRolesOfComponent(componentName, &roles);
+
+ if (err == OMX_ErrorNone) {
+ for (OMX_U32 i = 0; i < roles.size(); ++i) {
+ info.mRoles.push_back(roles[i]);
+ }
+ }
+
+ ++index;
+ }
+
+ return OK;
+}
+
+status_t OMX::allocateNode(
+ const char *name, const sp<IOMXObserver> &observer,
+ sp<IOMXNode> *omxNode) {
+ Mutex::Autolock autoLock(mLock);
+
+ omxNode->clear();
+
+ if (mLiveNodes.size() == kMaxNodeInstances) {
+ return NO_MEMORY;
+ }
+
+ sp<OMXNodeInstance> instance = new OMXNodeInstance(this, observer, name);
+
+ OMX_COMPONENTTYPE *handle;
+ OMX_ERRORTYPE err = mMaster->makeComponentInstance(
+ name, &OMXNodeInstance::kCallbacks,
+ instance.get(), &handle);
+
+ if (err != OMX_ErrorNone) {
+ ALOGE("FAILED to allocate omx component '%s' err=%s(%#x)", name, asString(err), err);
+
+ return StatusFromOMXError(err);
+ }
+ instance->setHandle(handle);
+
+ // Find quirks from mParser
+ const auto& codec = mParser.getCodecMap().find(name);
+ if (codec == mParser.getCodecMap().cend()) {
+ ALOGW("Failed to obtain quirks for omx component '%s' from XML files",
+ name);
+ } else {
+ uint32_t quirks = 0;
+ for (const auto& quirk : codec->second.quirkSet) {
+ if (quirk == "requires-allocate-on-input-ports") {
+ quirks |= OMXNodeInstance::
+ kRequiresAllocateBufferOnInputPorts;
+ }
+ if (quirk == "requires-allocate-on-output-ports") {
+ quirks |= OMXNodeInstance::
+ kRequiresAllocateBufferOnOutputPorts;
+ }
+ }
+ instance->setQuirks(quirks);
+ }
+
+ mLiveNodes.add(IInterface::asBinder(observer), instance);
+ IInterface::asBinder(observer)->linkToDeath(this);
+
+ *omxNode = instance;
+
+ return OK;
+}
+
+status_t OMX::freeNode(const sp<OMXNodeInstance> &instance) {
+ if (instance == NULL) {
+ return OK;
+ }
+
+ {
+ Mutex::Autolock autoLock(mLock);
+ ssize_t index = mLiveNodes.indexOfKey(IInterface::asBinder(instance->observer()));
+ if (index < 0) {
+ // This could conceivably happen if the observer dies at roughly the
+ // same time that a client attempts to free the node explicitly.
+
+ // NOTE: it's guaranteed that this method is called at most once per
+ // instance.
+ ALOGV("freeNode: instance already removed from book-keeping.");
+ } else {
+ mLiveNodes.removeItemsAt(index);
+ IInterface::asBinder(instance->observer())->unlinkToDeath(this);
+ }
+ }
+
+ CHECK(instance->handle() != NULL);
+ OMX_ERRORTYPE err = mMaster->destroyComponentInstance(
+ static_cast<OMX_COMPONENTTYPE *>(instance->handle()));
+ ALOGV("freeNode: handle destroyed: %p", instance->handle());
+
+ return StatusFromOMXError(err);
+}
+
+status_t OMX::createInputSurface(
+ sp<IGraphicBufferProducer> *bufferProducer,
+ sp<IGraphicBufferSource> *bufferSource) {
+ if (bufferProducer == NULL || bufferSource == NULL) {
+ ALOGE("b/25884056");
+ return BAD_VALUE;
+ }
+
+ sp<GraphicBufferSource> graphicBufferSource = new GraphicBufferSource();
+ status_t err = graphicBufferSource->initCheck();
+ if (err != OK) {
+ ALOGE("Failed to create persistent input surface: %s (%d)",
+ strerror(-err), err);
+ return err;
+ }
+
+ *bufferProducer = graphicBufferSource->getIGraphicBufferProducer();
+ *bufferSource = new BWGraphicBufferSource(graphicBufferSource);
+
+ return OK;
+}
+
+} // namespace android
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index ff58eb6..015a148 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -344,7 +344,7 @@
////////////////////////////////////////////////////////////////////////////////
OMXNodeInstance::OMXNodeInstance(
- Omx *owner, const sp<IOMXObserver> &observer, const char *name)
+ OmxNodeOwner *owner, const sp<IOMXObserver> &observer, const char *name)
: mOwner(owner),
mHandle(NULL),
mObserver(observer),
diff --git a/media/libstagefright/omx/OMXStore.cpp b/media/libstagefright/omx/OMXStore.cpp
new file mode 100644
index 0000000..345336d
--- /dev/null
+++ b/media/libstagefright/omx/OMXStore.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "OMXStore"
+#include <utils/Log.h>
+
+#include <media/stagefright/omx/OMXUtils.h>
+#include <media/stagefright/omx/OMX.h>
+#include <media/stagefright/omx/OMXStore.h>
+#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
+
+#include <map>
+#include <string>
+
+namespace android {
+
+namespace {
+ struct RoleProperties {
+ std::string type;
+ bool isEncoder;
+ bool preferPlatformNodes;
+ std::multimap<size_t, IOMXStore::NodeInfo> nodeList;
+ };
+} // Unnamed namespace
+
+OMXStore::OMXStore(
+ const char* owner,
+ const char* const* searchDirs,
+ const char* mainXmlName,
+ const char* performanceXmlName,
+ const char* profilingResultsXmlPath) {
+ MediaCodecsXmlParser parser(
+ searchDirs,
+ mainXmlName,
+ performanceXmlName,
+ profilingResultsXmlPath);
+ mParsingStatus = parser.getParsingStatus();
+
+ const auto& serviceAttributeMap = parser.getServiceAttributeMap();
+ mServiceAttributeList.reserve(serviceAttributeMap.size());
+ for (const auto& attributePair : serviceAttributeMap) {
+ Attribute attribute;
+ attribute.key = attributePair.first;
+ attribute.value = attributePair.second;
+ mServiceAttributeList.push_back(std::move(attribute));
+ }
+
+ const auto& roleMap = parser.getRoleMap();
+ mRoleList.reserve(roleMap.size());
+ for (const auto& rolePair : roleMap) {
+ RoleInfo role;
+ role.role = rolePair.first;
+ role.type = rolePair.second.type;
+ role.isEncoder = rolePair.second.isEncoder;
+ // TODO: Currently, preferPlatformNodes information is not available in
+ // the xml file. Once we have a way to provide this information, it
+ // should be parsed properly.
+ role.preferPlatformNodes = rolePair.first.compare(0, 5, "audio") == 0;
+ std::vector<NodeInfo>& nodeList = role.nodes;
+ nodeList.reserve(rolePair.second.nodeList.size());
+ for (const auto& nodePair : rolePair.second.nodeList) {
+ NodeInfo node;
+ node.name = nodePair.second.name;
+ node.owner = owner;
+ std::vector<Attribute>& attributeList = node.attributes;
+ attributeList.reserve(nodePair.second.attributeList.size());
+ for (const auto& attributePair : nodePair.second.attributeList) {
+ Attribute attribute;
+ attribute.key = attributePair.first;
+ attribute.value = attributePair.second;
+ attributeList.push_back(std::move(attribute));
+ }
+ nodeList.push_back(std::move(node));
+ }
+ mRoleList.push_back(std::move(role));
+ }
+
+ mPrefix = parser.getCommonPrefix();
+}
+
+status_t OMXStore::listServiceAttributes(std::vector<Attribute>* attributes) {
+ *attributes = mServiceAttributeList;
+ return mParsingStatus;
+}
+
+status_t OMXStore::getNodePrefix(std::string* prefix) {
+ *prefix = mPrefix;
+ return mParsingStatus;
+}
+
+status_t OMXStore::listRoles(std::vector<RoleInfo>* roleList) {
+ *roleList = mRoleList;
+ return mParsingStatus;
+}
+
+status_t OMXStore::getOmx(const std::string& name, sp<IOMX>* omx) {
+ *omx = new OMX();
+ return NO_ERROR;
+}
+
+OMXStore::~OMXStore() {
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/1.0/Omx.h b/media/libstagefright/omx/include/media/stagefright/omx/1.0/Omx.h
index baa7b81..a6a9d3e 100644
--- a/media/libstagefright/omx/include/media/stagefright/omx/1.0/Omx.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/1.0/Omx.h
@@ -20,13 +20,13 @@
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
+#include <media/stagefright/omx/OMXNodeInstance.h>
#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
namespace android {
struct OMXMaster;
-struct OMXNodeInstance;
namespace hardware {
namespace media {
@@ -50,9 +50,10 @@
using ::android::wp;
using ::android::OMXMaster;
+using ::android::OmxNodeOwner;
using ::android::OMXNodeInstance;
-struct Omx : public IOmx, public hidl_death_recipient {
+struct Omx : public IOmx, public hidl_death_recipient, public OmxNodeOwner {
Omx();
virtual ~Omx();
@@ -67,8 +68,8 @@
// Method from hidl_death_recipient
void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
- // Method for OMXNodeInstance
- status_t freeNode(sp<OMXNodeInstance> const& instance);
+ // Method from OmxNodeOwner
+ virtual status_t freeNode(sp<OMXNodeInstance> const& instance) override;
protected:
OMXMaster* mMaster;
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/OMX.h b/media/libstagefright/omx/include/media/stagefright/omx/OMX.h
new file mode 100644
index 0000000..594b4c0
--- /dev/null
+++ b/media/libstagefright/omx/include/media/stagefright/omx/OMX.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 ANDROID_OMX_H_
+#define ANDROID_OMX_H_
+
+#include <media/IOMX.h>
+#include <utils/threads.h>
+#include <utils/KeyedVector.h>
+#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
+#include "OmxNodeOwner.h"
+
+namespace android {
+
+struct OMXMaster;
+struct OMXNodeInstance;
+
+class OMX : public BnOMX,
+ public OmxNodeOwner,
+ public IBinder::DeathRecipient {
+public:
+ OMX();
+
+ virtual status_t listNodes(List<ComponentInfo> *list);
+
+ virtual status_t allocateNode(
+ const char *name, const sp<IOMXObserver> &observer,
+ sp<IOMXNode> *omxNode);
+
+ virtual status_t createInputSurface(
+ sp<IGraphicBufferProducer> *bufferProducer,
+ sp<IGraphicBufferSource> *bufferSource);
+
+ virtual void binderDied(const wp<IBinder> &the_late_who);
+
+ virtual status_t freeNode(const sp<OMXNodeInstance>& instance);
+
+protected:
+ virtual ~OMX();
+
+private:
+ Mutex mLock;
+ OMXMaster *mMaster;
+ MediaCodecsXmlParser mParser;
+
+ KeyedVector<wp<IBinder>, sp<OMXNodeInstance> > mLiveNodes;
+
+ OMX(const OMX &);
+ OMX &operator=(const OMX &);
+};
+
+} // namespace android
+
+#endif // ANDROID_OMX_H_
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h b/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h
index c436121..1065ca5 100644
--- a/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h
@@ -25,9 +25,9 @@
#include <utils/threads.h>
#include <utils/KeyedVector.h>
#include <utils/SortedVector.h>
+#include "OmxNodeOwner.h"
#include <android/hidl/memory/1.0/IMemory.h>
-#include <media/stagefright/omx/1.0/Omx.h>
namespace android {
class GraphicBuffer;
@@ -35,12 +35,11 @@
class IOMXObserver;
struct OMXMaster;
class OMXBuffer;
-using IHidlMemory = hidl::memory::V1_0::IMemory;
-using hardware::media::omx::V1_0::implementation::Omx;
+typedef hidl::memory::V1_0::IMemory IHidlMemory;
struct OMXNodeInstance : public BnOMXNode {
OMXNodeInstance(
- Omx *owner, const sp<IOMXObserver> &observer, const char *name);
+ OmxNodeOwner *owner, const sp<IOMXObserver> &observer, const char *name);
void setHandle(OMX_HANDLETYPE handle);
@@ -123,7 +122,7 @@
Mutex mLock;
- Omx *mOwner;
+ OmxNodeOwner *mOwner;
OMX_HANDLETYPE mHandle;
sp<IOMXObserver> mObserver;
sp<CallbackDispatcher> mDispatcher;
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/OMXStore.h b/media/libstagefright/omx/include/media/stagefright/omx/OMXStore.h
new file mode 100644
index 0000000..e00d713
--- /dev/null
+++ b/media/libstagefright/omx/include/media/stagefright/omx/OMXStore.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 ANDROID_OMXSTORE_H_
+#define ANDROID_OMXSTORE_H_
+
+#include <media/IOMXStore.h>
+#include <media/IOMX.h>
+#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
+
+#include <vector>
+#include <string>
+
+namespace android {
+
+class OMXStore : public BnOMXStore {
+public:
+ OMXStore(
+ const char* owner = "default",
+ const char* const* searchDirs
+ = MediaCodecsXmlParser::defaultSearchDirs,
+ const char* mainXmlName
+ = MediaCodecsXmlParser::defaultMainXmlName,
+ const char* performanceXmlName
+ = MediaCodecsXmlParser::defaultPerformanceXmlName,
+ const char* profilingResultsXmlPath
+ = MediaCodecsXmlParser::defaultProfilingResultsXmlPath);
+
+ status_t listServiceAttributes(
+ std::vector<Attribute>* attributes) override;
+
+ status_t getNodePrefix(std::string* prefix) override;
+
+ status_t listRoles(std::vector<RoleInfo>* roleList) override;
+
+ status_t getOmx(const std::string& name, sp<IOMX>* omx) override;
+
+ ~OMXStore() override;
+
+protected:
+ status_t mParsingStatus;
+ std::string mPrefix;
+ std::vector<Attribute> mServiceAttributeList;
+ std::vector<RoleInfo> mRoleList;
+};
+
+} // namespace android
+
+#endif // ANDROID_OMXSTORE_H_
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index 86c7211..8092887 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -25,9 +25,11 @@
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
+#include <binder/MemoryDealer.h>
#include <cutils/properties.h>
#include <media/DataSource.h>
#include <media/IMediaHTTPService.h>
+#include <media/IMediaCodecService.h>
#include <media/MediaExtractor.h>
#include <media/MediaSource.h>
#include <media/OMXBuffer.h>
@@ -69,7 +71,7 @@
/////////////////////////////////////////////////////////////////////
Harness::Harness()
- : mInitCheck(NO_INIT) {
+ : mInitCheck(NO_INIT), mUseTreble(false) {
mInitCheck = initOMX();
}
@@ -81,12 +83,21 @@
}
status_t Harness::initOMX() {
- using namespace ::android::hardware::media::omx::V1_0;
- sp<IOmx> tOmx = IOmx::getService();
- if (tOmx == nullptr) {
- return NO_INIT;
+ if (property_get_bool("persist.media.treble_omx", true)) {
+ using namespace ::android::hardware::media::omx::V1_0;
+ sp<IOmx> tOmx = IOmx::getService();
+ if (tOmx == nullptr) {
+ return NO_INIT;
+ }
+ mOMX = new utils::LWOmx(tOmx);
+ mUseTreble = true;
+ } else {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16("media.codec"));
+ sp<IMediaCodecService> service = interface_cast<IMediaCodecService>(binder);
+ mOMX = service->getOMX();
+ mUseTreble = false;
}
- mOMX = new utils::LWOmx(tOmx);
return mOMX != 0 ? OK : NO_INIT;
}
@@ -214,19 +225,25 @@
for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
Buffer buffer;
buffer.mFlags = 0;
- bool success;
- auto transStatus = mAllocator->allocate(def.nBufferSize,
- [&success, &buffer](
- bool s,
- hidl_memory const& m) {
- success = s;
- buffer.mHidlMemory = m;
- });
- EXPECT(transStatus.isOk(),
- "Cannot call allocator");
- EXPECT(success,
- "Cannot allocate memory");
- err = mOMXNode->useBuffer(portIndex, buffer.mHidlMemory, &buffer.mID);
+ if (mUseTreble) {
+ bool success;
+ auto transStatus = mAllocator->allocate(def.nBufferSize,
+ [&success, &buffer](
+ bool s,
+ hidl_memory const& m) {
+ success = s;
+ buffer.mHidlMemory = m;
+ });
+ EXPECT(transStatus.isOk(),
+ "Cannot call allocator");
+ EXPECT(success,
+ "Cannot allocate memory");
+ err = mOMXNode->useBuffer(portIndex, buffer.mHidlMemory, &buffer.mID);
+ } else {
+ buffer.mMemory = mDealer->allocate(def.nBufferSize);
+ CHECK(buffer.mMemory != NULL);
+ err = mOMXNode->useBuffer(portIndex, buffer.mMemory, &buffer.mID);
+ }
EXPECT_SUCCESS(err, "useBuffer");
@@ -295,11 +312,13 @@
return OK;
}
- mAllocator = IAllocator::getService("ashmem");
- EXPECT(mAllocator != nullptr,
- "Cannot obtain hidl AshmemAllocator");
- // TODO: When Treble has MemoryHeap/MemoryDealer, we should specify the heap
- // size to be 16 * 1024 * 1024.
+ if (mUseTreble) {
+ mAllocator = IAllocator::getService("ashmem");
+ EXPECT(mAllocator != nullptr,
+ "Cannot obtain hidl AshmemAllocator");
+ } else {
+ mDealer = new MemoryDealer(16 * 1024 * 1024, "OMXHarness");
+ }
sp<CodecObserver> observer = new CodecObserver(this, ++mCurGeneration);
diff --git a/media/libstagefright/omx/tests/OMXHarness.h b/media/libstagefright/omx/tests/OMXHarness.h
index dca787c..4fc0f79 100644
--- a/media/libstagefright/omx/tests/OMXHarness.h
+++ b/media/libstagefright/omx/tests/OMXHarness.h
@@ -93,6 +93,8 @@
Condition mMessageAddedCondition;
int32_t mLastMsgGeneration;
int32_t mCurGeneration;
+ bool mUseTreble;
+ sp<MemoryDealer> mDealer;
sp<IAllocator> mAllocator;
status_t initOMX();
diff --git a/media/ndk/NdkImage.cpp b/media/ndk/NdkImage.cpp
index c4ff537..20b1667 100644
--- a/media/ndk/NdkImage.cpp
+++ b/media/ndk/NdkImage.cpp
@@ -37,8 +37,8 @@
mTimestamp(timestamp), mWidth(width), mHeight(height), mNumPlanes(numPlanes) {
}
-// Can only be called by free() with mLock hold
AImage::~AImage() {
+ Mutex::Autolock _l(mLock);
if (!mIsClosed) {
LOG_ALWAYS_FATAL(
"Error: AImage %p is deleted before returning buffer to AImageReader!", this);
@@ -78,7 +78,6 @@
ALOGE("Cannot free AImage before close!");
return;
}
- Mutex::Autolock _l(mLock);
delete this;
}
diff --git a/media/ndk/OWNERS b/media/ndk/OWNERS
index 43e4bb3..11e8340 100644
--- a/media/ndk/OWNERS
+++ b/media/ndk/OWNERS
@@ -1 +1,5 @@
marcone@google.com
+# For AImage/AImageReader
+etalvala@google.com
+yinchiayeh@google.com
+zhijunhe@google.com
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index 31f0550..9bd68e1 100644
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -35,7 +35,8 @@
* A device mask for all audio input devices that are considered "virtual" when evaluating
* active inputs in getActiveInputs()
*/
-#define APM_AUDIO_IN_DEVICE_VIRTUAL_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX)
+#define APM_AUDIO_IN_DEVICE_VIRTUAL_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX|\
+ AUDIO_DEVICE_IN_BUS|AUDIO_DEVICE_IN_FM_TUNER)
/**
diff --git a/services/mediaanalytics/MediaAnalyticsService.cpp b/services/mediaanalytics/MediaAnalyticsService.cpp
index f08be50..83992aa 100644
--- a/services/mediaanalytics/MediaAnalyticsService.cpp
+++ b/services/mediaanalytics/MediaAnalyticsService.cpp
@@ -318,6 +318,7 @@
saveItem(mFinalized, oitem, 0);
}
// new record could itself be marked finalized...
+ id = item->getSessionID();
if (finalizing) {
summarize(item);
saveItem(mFinalized, item, 0);
@@ -325,16 +326,15 @@
} else {
saveItem(mOpen, item, 1);
}
- id = item->getSessionID();
} else {
// combine the records, send it to finalized if appropriate
oitem->merge(item);
+ id = oitem->getSessionID();
if (finalizing) {
summarize(oitem);
saveItem(mFinalized, oitem, 0);
mItemsFinalized++;
}
- id = oitem->getSessionID();
// we're responsible for disposing of the dead record
delete item;
@@ -614,17 +614,28 @@
// caller should hold mLock
void MediaAnalyticsService::saveItem(List<MediaAnalyticsItem *> *l, MediaAnalyticsItem * item, int front) {
- // adding at back of queue (fifo order)
if (front) {
+ // for non-finalized stuff, since we expect to reference it again soon,
+ // make it quicker to find (nearer the front of our list)
l->push_front(item);
} else {
+ // for finalized records, which we want to dump 'in sequence order'
l->push_back(item);
}
+ // our reclaim process is for oldest-first queues
+ if (front) {
+ return;
+ }
+
+
// keep removing old records the front until we're in-bounds (count)
if (mMaxRecords > 0) {
while (l->size() > (size_t) mMaxRecords) {
MediaAnalyticsItem * oitem = *(l->begin());
+ if (oitem == item) {
+ break;
+ }
l->erase(l->begin());
delete oitem;
mItemsDiscarded++;
@@ -638,6 +649,9 @@
while (l->size() > 0) {
MediaAnalyticsItem * oitem = *(l->begin());
nsecs_t when = oitem->getTimestamp();
+ if (oitem == item) {
+ break;
+ }
// careful about timejumps too
if ((now > when) && (now-when) <= mMaxRecordAgeNs) {
// this (and the rest) are recent enough to keep
diff --git a/services/mediacodec/Android.mk b/services/mediacodec/Android.mk
index 9348ecd..faeb0a7 100644
--- a/services/mediacodec/Android.mk
+++ b/services/mediacodec/Android.mk
@@ -1,11 +1,28 @@
LOCAL_PATH := $(call my-dir)
+# service library
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := MediaCodecService.cpp
+LOCAL_SHARED_LIBRARIES := \
+ libmedia_omx \
+ libbinder \
+ libgui \
+ libutils \
+ liblog \
+ libstagefright_omx \
+ libstagefright_xmlparser
+LOCAL_MODULE:= libmediacodecservice
+LOCAL_VENDOR_MODULE := true
+LOCAL_32_BIT_ONLY := true
+include $(BUILD_SHARED_LIBRARY)
+
# service executable
include $(CLEAR_VARS)
LOCAL_REQUIRED_MODULES_arm := mediacodec.policy
LOCAL_SRC_FILES := main_codecservice.cpp
LOCAL_SHARED_LIBRARIES := \
libmedia_omx \
+ libmediacodecservice \
libbinder \
libutils \
libgui \
@@ -25,11 +42,6 @@
LOCAL_VENDOR_MODULE := true
LOCAL_32_BIT_ONLY := true
LOCAL_INIT_RC := android.hardware.media.omx@1.0-service.rc
-
-ifeq ($(PRODUCT_FULL_TREBLE),true)
-LOCAL_CFLAGS += -DUSE_VNDBINDER
-endif
-
include $(BUILD_EXECUTABLE)
# service seccomp policy
diff --git a/services/mediacodec/MediaCodecService.cpp b/services/mediacodec/MediaCodecService.cpp
new file mode 100644
index 0000000..6b510c6
--- /dev/null
+++ b/services/mediacodec/MediaCodecService.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "MediaCodecService"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include "MediaCodecService.h"
+
+namespace android {
+
+sp<IOMX> MediaCodecService::getOMX() {
+
+ Mutex::Autolock autoLock(mOMXLock);
+
+ if (mOMX.get() == NULL) {
+ mOMX = new OMX();
+ }
+
+ return mOMX;
+}
+
+sp<IOMXStore> MediaCodecService::getOMXStore() {
+
+ Mutex::Autolock autoLock(mOMXStoreLock);
+
+ if (mOMXStore.get() == NULL) {
+ mOMXStore = new OMXStore();
+ }
+
+ return mOMXStore;
+}
+
+status_t MediaCodecService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags)
+{
+ return BnMediaCodecService::onTransact(code, data, reply, flags);
+}
+
+} // namespace android
diff --git a/services/mediacodec/MediaCodecService.h b/services/mediacodec/MediaCodecService.h
new file mode 100644
index 0000000..9301135
--- /dev/null
+++ b/services/mediacodec/MediaCodecService.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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 ANDROID_MEDIA_CODEC_SERVICE_H
+#define ANDROID_MEDIA_CODEC_SERVICE_H
+
+#include <binder/BinderService.h>
+#include <media/IMediaCodecService.h>
+#include <media/stagefright/omx/OMX.h>
+#include <media/stagefright/omx/OMXStore.h>
+
+namespace android {
+
+class MediaCodecService : public BinderService<MediaCodecService>,
+ public BnMediaCodecService
+{
+ friend class BinderService<MediaCodecService>; // for MediaCodecService()
+public:
+ MediaCodecService() : BnMediaCodecService() { }
+ virtual ~MediaCodecService() { }
+ virtual void onFirstRef() { }
+
+ static const char* getServiceName() { return "media.codec"; }
+
+ virtual sp<IOMX> getOMX();
+
+ virtual sp<IOMXStore> getOMXStore();
+
+ virtual status_t onTransact(uint32_t code, const Parcel& data,
+ Parcel* reply, uint32_t flags);
+
+private:
+ Mutex mOMXLock;
+ sp<IOMX> mOMX;
+ Mutex mOMXStoreLock;
+ sp<IOMXStore> mOMXStore;
+};
+
+} // namespace android
+
+#endif // ANDROID_MEDIA_CODEC_SERVICE_H
diff --git a/services/mediacodec/main_codecservice.cpp b/services/mediacodec/main_codecservice.cpp
index 6bb3fa2..79d6da5 100644
--- a/services/mediacodec/main_codecservice.cpp
+++ b/services/mediacodec/main_codecservice.cpp
@@ -15,12 +15,22 @@
** limitations under the License.
*/
+#include <fcntl.h>
+#include <sys/prctl.h>
+#include <sys/wait.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+#include <cutils/properties.h>
+
+#include <string>
+
#include <android-base/logging.h>
// from LOCAL_C_INCLUDES
+#include "MediaCodecService.h"
#include "minijail.h"
-#include <binder/ProcessState.h>
#include <hidl/HidlTransportSupport.h>
#include <media/stagefright/omx/1.0/Omx.h>
#include <media/stagefright/omx/1.0/OmxStore.h>
@@ -36,11 +46,10 @@
int main(int argc __unused, char** argv)
{
LOG(INFO) << "mediacodecservice starting";
-
-#ifdef USE_VNDBINDER
- android::ProcessState::initWithDriver("/dev/vndbinder");
- android::ProcessState::self()->startThreadPool();
-#endif // USE_VNDBINDER
+ bool treble = property_get_bool("persist.media.treble_omx", true);
+ if (treble) {
+ android::ProcessState::initWithDriver("/dev/vndbinder");
+ }
signal(SIGPIPE, SIG_IGN);
SetUpMinijail(kSystemSeccompPolicyPath, kVendorSeccompPolicyPath);
@@ -48,22 +57,29 @@
strcpy(argv[0], "media.codec");
::android::hardware::configureRpcThreadpool(64, false);
+ sp<ProcessState> proc(ProcessState::self());
- using namespace ::android::hardware::media::omx::V1_0;
- sp<IOmxStore> omxStore = new implementation::OmxStore();
- if (omxStore == nullptr) {
- LOG(ERROR) << "Cannot create IOmxStore HAL service.";
- } else if (omxStore->registerAsService() != OK) {
- LOG(ERROR) << "Cannot register IOmxStore HAL service.";
- }
- sp<IOmx> omx = new implementation::Omx();
- if (omx == nullptr) {
- LOG(ERROR) << "Cannot create IOmx HAL service.";
- } else if (omx->registerAsService() != OK) {
- LOG(ERROR) << "Cannot register IOmx HAL service.";
+ if (treble) {
+ using namespace ::android::hardware::media::omx::V1_0;
+ sp<IOmxStore> omxStore = new implementation::OmxStore();
+ if (omxStore == nullptr) {
+ LOG(ERROR) << "Cannot create IOmxStore HAL service.";
+ } else if (omxStore->registerAsService() != OK) {
+ LOG(ERROR) << "Cannot register IOmxStore HAL service.";
+ }
+ sp<IOmx> omx = new implementation::Omx();
+ if (omx == nullptr) {
+ LOG(ERROR) << "Cannot create IOmx HAL service.";
+ } else if (omx->registerAsService() != OK) {
+ LOG(ERROR) << "Cannot register IOmx HAL service.";
+ } else {
+ LOG(INFO) << "Treble OMX service created.";
+ }
} else {
- LOG(INFO) << "IOmx HAL service created.";
+ MediaCodecService::instantiate();
+ LOG(INFO) << "Non-Treble OMX service created.";
}
- ::android::hardware::joinRpcThreadpool();
+ ProcessState::self()->startThreadPool();
+ IPCThreadState::self()->joinThreadPool();
}
diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp
index 6d833aa..a7d6e83 100644
--- a/services/soundtrigger/SoundTriggerHwService.cpp
+++ b/services/soundtrigger/SoundTriggerHwService.cpp
@@ -313,7 +313,7 @@
}
-sp<IMemory> SoundTriggerHwService::prepareServiceStateEvent_l(sound_trigger_service_state_t state)
+sp<IMemory> SoundTriggerHwService::prepareServiceStateEvent(sound_trigger_service_state_t state)
{
AutoMutex lock(mMemoryDealerLock);
sp<IMemory> eventMemory;
@@ -328,34 +328,23 @@
return eventMemory;
}
-// call with mServiceLock held
-void SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state,
+void SoundTriggerHwService::sendServiceStateEvent(sound_trigger_service_state_t state,
Module *module)
{
- sp<IMemory> eventMemory = prepareServiceStateEvent_l(state);
+ sp<IMemory> eventMemory = prepareServiceStateEvent(state);
if (eventMemory == 0) {
return;
}
- sp<Module> strongModule;
- for (size_t i = 0; i < mModules.size(); i++) {
- if (mModules.valueAt(i).get() == module) {
- strongModule = mModules.valueAt(i);
- break;
- }
- }
- if (strongModule == 0) {
- return;
- }
sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE,
eventMemory);
- callbackEvent->setModule(strongModule);
+ callbackEvent->setModule(module);
sendCallbackEvent(callbackEvent);
}
-void SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state,
- ModuleClient *moduleClient)
+void SoundTriggerHwService::sendServiceStateEvent(sound_trigger_service_state_t state,
+ ModuleClient *moduleClient)
{
- sp<IMemory> eventMemory = prepareServiceStateEvent_l(state);
+ sp<IMemory> eventMemory = prepareServiceStateEvent(state);
if (eventMemory == 0) {
return;
}
@@ -906,7 +895,7 @@
}
exit:
- service->sendServiceStateEvent_l(state, this);
+ service->sendServiceStateEvent(state, this);
}
@@ -1051,7 +1040,7 @@
return;
}
}
- service->sendServiceStateEvent_l(state, this);
+ service->sendServiceStateEvent(state, this);
}
void SoundTriggerHwService::ModuleClient::onCallbackEvent(const sp<CallbackEvent>& event)
diff --git a/services/soundtrigger/SoundTriggerHwService.h b/services/soundtrigger/SoundTriggerHwService.h
index a955f40..708fc98 100644
--- a/services/soundtrigger/SoundTriggerHwService.h
+++ b/services/soundtrigger/SoundTriggerHwService.h
@@ -221,10 +221,10 @@
sp<IMemory> prepareSoundModelEvent(struct sound_trigger_model_event *event);
void sendSoundModelEvent(struct sound_trigger_model_event *event, Module *module);
- sp<IMemory> prepareServiceStateEvent_l(sound_trigger_service_state_t state);
- void sendServiceStateEvent_l(sound_trigger_service_state_t state, Module *module);
- void sendServiceStateEvent_l(sound_trigger_service_state_t state,
- ModuleClient *moduleClient);
+ sp<IMemory> prepareServiceStateEvent(sound_trigger_service_state_t state);
+ void sendServiceStateEvent(sound_trigger_service_state_t state, Module *module);
+ void sendServiceStateEvent(sound_trigger_service_state_t state,
+ ModuleClient *moduleClient);
void sendCallbackEvent(const sp<CallbackEvent>& event);
void onCallbackEvent(const sp<CallbackEvent>& event);