Merge "AudioRecord: Use original flags during track recreation" into nyc-dev
diff --git a/include/media/stagefright/CodecBase.h b/include/media/stagefright/CodecBase.h
index 3de0d21..2d28432 100644
--- a/include/media/stagefright/CodecBase.h
+++ b/include/media/stagefright/CodecBase.h
@@ -20,9 +20,12 @@
 
 #include <stdint.h>
 
+#define STRINGIFY_ENUMS
+
 #include <media/IOMX.h>
 #include <media/MediaCodecInfo.h>
 #include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/ColorUtils.h>
 #include <media/hardware/HardwareAPI.h>
 
 #include <utils/NativeHandle.h>
@@ -34,7 +37,7 @@
 struct ABuffer;
 struct PersistentSurface;
 
-struct CodecBase : public AHandler {
+struct CodecBase : public AHandler, /* static */ ColorUtils {
     enum {
         kWhatFillThisBuffer      = 'fill',
         kWhatDrainThisBuffer     = 'drai',
@@ -97,113 +100,6 @@
      * Codec-related defines
      */
 
-    /**********************************************************************************************/
-
-    /*
-     * Media-platform color constants. MediaCodec uses (an extended version of) platform-defined
-     * constants that are derived from HAL_DATASPACE, since these are directly exposed to the user.
-     * We extend the values to maintain the richer set of information defined inside media
-     * containers and bitstreams that are not supported by the platform. We also expect vendors
-     * to extend some of these values with vendor-specific values. These are separated into a
-     * vendor-extension section so they won't collide with future platform values.
-     */
-
-    enum ColorStandard : uint32_t {
-        kColorStandardUnspecified =
-                HAL_DATASPACE_STANDARD_UNSPECIFIED >> HAL_DATASPACE_STANDARD_SHIFT,
-        kColorStandardBT709 =     HAL_DATASPACE_STANDARD_BT709 >> HAL_DATASPACE_STANDARD_SHIFT,
-        kColorStandardBT601_625 = HAL_DATASPACE_STANDARD_BT601_625 >> HAL_DATASPACE_STANDARD_SHIFT,
-        kColorStandardBT601_625_Unadjusted =
-                HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED >> HAL_DATASPACE_STANDARD_SHIFT,
-        kColorStandardBT601_525 = HAL_DATASPACE_STANDARD_BT601_525 >> HAL_DATASPACE_STANDARD_SHIFT,
-        kColorStandardBT601_525_Unadjusted =
-                HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED >> HAL_DATASPACE_STANDARD_SHIFT,
-        kColorStandardBT2020 =    HAL_DATASPACE_STANDARD_BT2020 >> HAL_DATASPACE_STANDARD_SHIFT,
-        kColorStandardBT2020Constant =
-                HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE >> HAL_DATASPACE_STANDARD_SHIFT,
-        kColorStandardBT470M =    HAL_DATASPACE_STANDARD_BT470M >> HAL_DATASPACE_STANDARD_SHIFT,
-        kColorStandardFilm =      HAL_DATASPACE_STANDARD_FILM >> HAL_DATASPACE_STANDARD_SHIFT,
-        kColorStandardMax =       HAL_DATASPACE_STANDARD_MASK >> HAL_DATASPACE_STANDARD_SHIFT,
-
-        /* This marks a section of color-standard values that are not supported by graphics HAL,
-           but track defined color primaries-matrix coefficient combinations in media.
-           These are stable for a given release. */
-        kColorStandardExtendedStart = kColorStandardMax + 1,
-
-        /* This marks a section of color-standard values that are not supported by graphics HAL
-           nor using media defined color primaries or matrix coefficients. These may differ per
-           device. */
-        kColorStandardVendorStart = 0x10000,
-    };
-
-    enum ColorTransfer : uint32_t  {
-        kColorTransferUnspecified =
-                HAL_DATASPACE_TRANSFER_UNSPECIFIED >> HAL_DATASPACE_TRANSFER_SHIFT,
-        kColorTransferLinear =      HAL_DATASPACE_TRANSFER_LINEAR >> HAL_DATASPACE_TRANSFER_SHIFT,
-        kColorTransferSRGB =        HAL_DATASPACE_TRANSFER_SRGB >> HAL_DATASPACE_TRANSFER_SHIFT,
-        kColorTransferSMPTE_170M =
-                HAL_DATASPACE_TRANSFER_SMPTE_170M >> HAL_DATASPACE_TRANSFER_SHIFT,
-        kColorTransferGamma22 =     HAL_DATASPACE_TRANSFER_GAMMA2_2 >> HAL_DATASPACE_TRANSFER_SHIFT,
-        kColorTransferGamma28 =     HAL_DATASPACE_TRANSFER_GAMMA2_8 >> HAL_DATASPACE_TRANSFER_SHIFT,
-        kColorTransferST2084 =      HAL_DATASPACE_TRANSFER_ST2084 >> HAL_DATASPACE_TRANSFER_SHIFT,
-        kColorTransferHLG =         HAL_DATASPACE_TRANSFER_HLG >> HAL_DATASPACE_TRANSFER_SHIFT,
-        kColorTransferMax =         HAL_DATASPACE_TRANSFER_MASK >> HAL_DATASPACE_TRANSFER_SHIFT,
-
-        /* This marks a section of color-transfer values that are not supported by graphics HAL,
-           but track media-defined color-transfer. These are stable for a given release. */
-        kColorTransferExtendedStart = kColorTransferMax + 1,
-
-        /* This marks a section of color-transfer values that are not supported by graphics HAL
-           nor defined by media. These may differ per device. */
-        kColorTransferVendorStart = 0x10000,
-    };
-
-    enum ColorRange : uint32_t  {
-        kColorRangeUnspecified = HAL_DATASPACE_RANGE_UNSPECIFIED >> HAL_DATASPACE_RANGE_SHIFT,
-        kColorRangeFull =        HAL_DATASPACE_RANGE_FULL >> HAL_DATASPACE_RANGE_SHIFT,
-        kColorRangeLimited =     HAL_DATASPACE_RANGE_LIMITED >> HAL_DATASPACE_RANGE_SHIFT,
-        kColorRangeMax =         HAL_DATASPACE_RANGE_MASK >> HAL_DATASPACE_RANGE_SHIFT,
-
-        /* This marks a section of color-transfer values that are not supported by graphics HAL,
-           but track media-defined color-transfer. These are stable for a given release. */
-        kColorRangeExtendedStart = kColorRangeMax + 1,
-
-        /* This marks a section of color-transfer values that are not supported by graphics HAL
-           nor defined by media. These may differ per device. */
-        kColorRangeVendorStart = 0x10000,
-    };
-
-    /*
-     * Static utilities for codec support
-     */
-
-    // using int32_t for media range/standard/transfers to denote extended ranges
-    static int32_t wrapColorAspectsIntoColorStandard(
-            ColorAspects::Primaries primaries, ColorAspects::MatrixCoeffs coeffs);
-    static int32_t wrapColorAspectsIntoColorRange(ColorAspects::Range range);
-    static int32_t wrapColorAspectsIntoColorTransfer(ColorAspects::Transfer transfer);
-
-    static status_t unwrapColorAspectsFromColorRange(
-            int32_t range, ColorAspects::Range *aspect);
-    static status_t unwrapColorAspectsFromColorTransfer(
-            int32_t transfer, ColorAspects::Transfer *aspect);
-    static status_t unwrapColorAspectsFromColorStandard(
-            int32_t standard,
-            ColorAspects::Primaries *primaries, ColorAspects::MatrixCoeffs *coeffs);
-
-    static status_t convertPlatformColorAspectsToCodecAspects(
-            int32_t range, int32_t standard, int32_t transfer, ColorAspects &aspects);
-    static status_t convertCodecColorAspectsToPlatformAspects(
-            const ColorAspects &aspects,
-            int32_t *range, int32_t *standard, int32_t *transfer);
-
-    // updates unspecified range, standard and transfer values to their defaults
-    static void setDefaultPlatformColorAspectsIfNeeded(
-            int32_t &range, int32_t &standard, int32_t &transfer,
-            int32_t width, int32_t height);
-    static void setDefaultCodecColorAspectsIfNeeded(
-            ColorAspects &aspects, int32_t width, int32_t height);
-
 protected:
     CodecBase();
     virtual ~CodecBase();
diff --git a/include/media/stagefright/foundation/ColorUtils.h b/include/media/stagefright/foundation/ColorUtils.h
new file mode 100644
index 0000000..b95c80b
--- /dev/null
+++ b/include/media/stagefright/foundation/ColorUtils.h
@@ -0,0 +1,184 @@
+/*
+ * 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 COLOR_UTILS_H_
+
+#define COLOR_UTILS_H_
+
+#include <stdint.h>
+
+#define STRINGIFY_ENUMS
+
+#include <media/stagefright/foundation/AMessage.h>
+
+#include <media/hardware/VideoAPI.h>
+#include <system/graphics.h>
+
+namespace android {
+
+struct ColorUtils {
+    /*
+     * Media-platform color constants. MediaCodec uses (an extended version of) platform-defined
+     * constants that are derived from HAL_DATASPACE, since these are directly exposed to the user.
+     * We extend the values to maintain the richer set of information defined inside media
+     * containers and bitstreams that are not supported by the platform. We also expect vendors
+     * to extend some of these values with vendor-specific values. These are separated into a
+     * vendor-extension section so they won't collide with future platform values.
+     */
+
+#define GET_HAL_ENUM(class, name) HAL_DATASPACE_##class##name
+#define GET_HAL_BITFIELD(class, name) (GET_HAL_ENUM(class, _##name) >> GET_HAL_ENUM(class, _SHIFT))
+
+    enum ColorStandard : uint32_t {
+        kColorStandardUnspecified =          GET_HAL_BITFIELD(STANDARD, UNSPECIFIED),
+        kColorStandardBT709 =                GET_HAL_BITFIELD(STANDARD, BT709),
+        kColorStandardBT601_625 =            GET_HAL_BITFIELD(STANDARD, BT601_625),
+        kColorStandardBT601_625_Unadjusted = GET_HAL_BITFIELD(STANDARD, BT601_625_UNADJUSTED),
+        kColorStandardBT601_525 =            GET_HAL_BITFIELD(STANDARD, BT601_525),
+        kColorStandardBT601_525_Unadjusted = GET_HAL_BITFIELD(STANDARD, BT601_525_UNADJUSTED),
+        kColorStandardBT2020 =               GET_HAL_BITFIELD(STANDARD, BT2020),
+        kColorStandardBT2020Constant =       GET_HAL_BITFIELD(STANDARD, BT2020_CONSTANT_LUMINANCE),
+        kColorStandardBT470M =               GET_HAL_BITFIELD(STANDARD, BT470M),
+        kColorStandardFilm =                 GET_HAL_BITFIELD(STANDARD, FILM),
+        kColorStandardMax =                  GET_HAL_BITFIELD(STANDARD, MASK),
+
+        /* This marks a section of color-standard values that are not supported by graphics HAL,
+           but track defined color primaries-matrix coefficient combinations in media.
+           These are stable for a given release. */
+        kColorStandardExtendedStart = kColorStandardMax + 1,
+
+        /* This marks a section of color-standard values that are not supported by graphics HAL
+           nor using media defined color primaries or matrix coefficients. These may differ per
+           device. */
+        kColorStandardVendorStart = 0x10000,
+    };
+
+    enum ColorTransfer : uint32_t  {
+        kColorTransferUnspecified = GET_HAL_BITFIELD(TRANSFER, UNSPECIFIED),
+        kColorTransferLinear =      GET_HAL_BITFIELD(TRANSFER, LINEAR),
+        kColorTransferSRGB =        GET_HAL_BITFIELD(TRANSFER, SRGB),
+        kColorTransferSMPTE_170M =  GET_HAL_BITFIELD(TRANSFER, SMPTE_170M),
+        kColorTransferGamma22 =     GET_HAL_BITFIELD(TRANSFER, GAMMA2_2),
+        kColorTransferGamma28 =     GET_HAL_BITFIELD(TRANSFER, GAMMA2_8),
+        kColorTransferST2084 =      GET_HAL_BITFIELD(TRANSFER, ST2084),
+        kColorTransferHLG =         GET_HAL_BITFIELD(TRANSFER, HLG),
+        kColorTransferMax =         GET_HAL_BITFIELD(TRANSFER, MASK),
+
+        /* This marks a section of color-transfer values that are not supported by graphics HAL,
+           but track media-defined color-transfer. These are stable for a given release. */
+        kColorTransferExtendedStart = kColorTransferMax + 1,
+
+        /* This marks a section of color-transfer values that are not supported by graphics HAL
+           nor defined by media. These may differ per device. */
+        kColorTransferVendorStart = 0x10000,
+    };
+
+    enum ColorRange : uint32_t  {
+        kColorRangeUnspecified = GET_HAL_BITFIELD(RANGE, UNSPECIFIED),
+        kColorRangeFull =        GET_HAL_BITFIELD(RANGE, FULL),
+        kColorRangeLimited =     GET_HAL_BITFIELD(RANGE, LIMITED),
+        kColorRangeMax =         GET_HAL_BITFIELD(RANGE, MASK),
+
+        /* This marks a section of color-transfer values that are not supported by graphics HAL,
+           but track media-defined color-transfer. These are stable for a given release. */
+        kColorRangeExtendedStart = kColorRangeMax + 1,
+
+        /* This marks a section of color-transfer values that are not supported by graphics HAL
+           nor defined by media. These may differ per device. */
+        kColorRangeVendorStart = 0x10000,
+    };
+
+#undef GET_HAL_BITFIELD
+#undef GET_HAL_ENUM
+
+    /*
+     * Static utilities for codec support
+     */
+
+    // using int32_t for media range/standard/transfers to denote extended ranges
+    // wrap methods change invalid aspects to the Unspecified value
+    static int32_t wrapColorAspectsIntoColorStandard(
+            ColorAspects::Primaries primaries, ColorAspects::MatrixCoeffs coeffs);
+    static int32_t wrapColorAspectsIntoColorRange(ColorAspects::Range range);
+    static int32_t wrapColorAspectsIntoColorTransfer(ColorAspects::Transfer transfer);
+
+    // unwrap methods change invalid aspects to the Other value
+    static status_t unwrapColorAspectsFromColorRange(
+            int32_t range, ColorAspects::Range *aspect);
+    static status_t unwrapColorAspectsFromColorTransfer(
+            int32_t transfer, ColorAspects::Transfer *aspect);
+    static status_t unwrapColorAspectsFromColorStandard(
+            int32_t standard,
+            ColorAspects::Primaries *primaries, ColorAspects::MatrixCoeffs *coeffs);
+
+    static status_t convertPlatformColorAspectsToCodecAspects(
+            int32_t range, int32_t standard, int32_t transfer, ColorAspects &aspects);
+    static status_t convertCodecColorAspectsToPlatformAspects(
+            const ColorAspects &aspects, int32_t *range, int32_t *standard, int32_t *transfer);
+
+    // updates unspecified range, standard and transfer values to their defaults
+    static void setDefaultPlatformColorAspectsIfNeeded(
+            int32_t &range, int32_t &standard, int32_t &transfer, int32_t width, int32_t height);
+    static void setDefaultCodecColorAspectsIfNeeded(
+            ColorAspects &aspects, int32_t width, int32_t height);
+};
+
+inline static const char *asString(android::ColorUtils::ColorStandard i, const char *def = "??") {
+    using namespace android;
+    switch (i) {
+        case ColorUtils::kColorStandardUnspecified:          return "Unspecified";
+        case ColorUtils::kColorStandardBT709:                return "BT709";
+        case ColorUtils::kColorStandardBT601_625:            return "BT601_625";
+        case ColorUtils::kColorStandardBT601_625_Unadjusted: return "BT601_625_Unadjusted";
+        case ColorUtils::kColorStandardBT601_525:            return "BT601_525";
+        case ColorUtils::kColorStandardBT601_525_Unadjusted: return "BT601_525_Unadjusted";
+        case ColorUtils::kColorStandardBT2020:               return "BT2020";
+        case ColorUtils::kColorStandardBT2020Constant:       return "BT2020Constant";
+        case ColorUtils::kColorStandardBT470M:               return "BT470M";
+        case ColorUtils::kColorStandardFilm:                 return "Film";
+        default:                                            return def;
+    }
+}
+
+inline static const char *asString(android::ColorUtils::ColorTransfer i, const char *def = "??") {
+    using namespace android;
+    switch (i) {
+        case ColorUtils::kColorTransferUnspecified: return "Unspecified";
+        case ColorUtils::kColorTransferLinear:      return "Linear";
+        case ColorUtils::kColorTransferSRGB:        return "SRGB";
+        case ColorUtils::kColorTransferSMPTE_170M:  return "SMPTE_170M";
+        case ColorUtils::kColorTransferGamma22:     return "Gamma22";
+        case ColorUtils::kColorTransferGamma28:     return "Gamma28";
+        case ColorUtils::kColorTransferST2084:      return "ST2084";
+        case ColorUtils::kColorTransferHLG:         return "HLG";
+        default:                                   return def;
+    }
+}
+
+inline static const char *asString(android::ColorUtils::ColorRange i, const char *def = "??") {
+    using namespace android;
+    switch (i) {
+        case ColorUtils::kColorRangeUnspecified: return "Unspecified";
+        case ColorUtils::kColorRangeFull:        return "Full";
+        case ColorUtils::kColorRangeLimited:     return "Limited";
+        default:                                return def;
+    }
+}
+
+}  // namespace android
+
+#endif  // COLOR_UTILS_H_
+
diff --git a/media/libstagefright/CodecBase.cpp b/media/libstagefright/CodecBase.cpp
index c9de2b0..f729d4d 100644
--- a/media/libstagefright/CodecBase.cpp
+++ b/media/libstagefright/CodecBase.cpp
@@ -20,8 +20,6 @@
 #include <inttypes.h>
 
 #include <media/stagefright/CodecBase.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/ALookup.h>
 
 namespace android {
 
@@ -37,277 +35,4 @@
 CodecBase::PortDescription::~PortDescription() {
 }
 
-/***************************************** COLOR SUPPORT *****************************************/
-
-// shortcut names for brevity in the following tables
-typedef ColorAspects CA;
-typedef CodecBase CB;
-
-ALookup<CB::ColorRange, CA::Range> sRanges{
-    {
-        { CB::kColorRangeLimited, CA::RangeLimited },
-        { CB::kColorRangeFull, CA::RangeFull },
-        { CB::kColorRangeUnspecified, CA::RangeUnspecified },
-    }
-};
-
-ALookup<CB::ColorStandard, std::pair<CA::Primaries, CA::MatrixCoeffs>> sStandards {
-    {
-        { CB::kColorStandardUnspecified,    { CA::PrimariesUnspecified, CA::MatrixUnspecified } },
-        { CB::kColorStandardBT709,          { CA::PrimariesBT709_5, CA::MatrixBT709_5 } },
-        { CB::kColorStandardBT601_625,      { CA::PrimariesBT601_6_625, CA::MatrixBT601_6 } },
-        { CB::kColorStandardBT601_625_Unadjusted,
-                                            // this is a really close match
-                                            { CA::PrimariesBT601_6_625, CA::MatrixBT709_5 } },
-        { CB::kColorStandardBT601_525,      { CA::PrimariesBT601_6_525, CA::MatrixBT601_6 } },
-        { CB::kColorStandardBT601_525_Unadjusted,
-                                            { CA::PrimariesBT601_6_525, CA::MatrixSMPTE240M } },
-        { CB::kColorStandardBT2020,         { CA::PrimariesBT2020, CA::MatrixBT2020 } },
-        { CB::kColorStandardBT2020Constant, { CA::PrimariesBT2020, CA::MatrixBT2020Constant } },
-        { CB::kColorStandardBT470M,         { CA::PrimariesBT470_6M, CA::MatrixBT470_6M } },
-        // NOTE: there is no close match to the matrix used by standard film, chose closest
-        { CB::kColorStandardFilm,           { CA::PrimariesGenericFilm, CA::MatrixBT2020 } },
-    }
-};
-
-ALookup<CB::ColorTransfer, CA::Transfer> sTransfers{
-    {
-        { CB::kColorTransferUnspecified,    CA::TransferUnspecified },
-        { CB::kColorTransferLinear,         CA::TransferLinear },
-        { CB::kColorTransferSRGB,           CA::TransferSRGB },
-        { CB::kColorTransferSMPTE_170M,     CA::TransferSMPTE170M },
-        { CB::kColorTransferGamma22,        CA::TransferGamma22 },
-        { CB::kColorTransferGamma28,        CA::TransferGamma28 },
-        { CB::kColorTransferST2084,         CA::TransferST2084 },
-        { CB::kColorTransferHLG,            CA::TransferHLG },
-    }
-};
-
-static bool isValid(ColorAspects::Primaries p) {
-    return p <= ColorAspects::PrimariesOther;
-}
-
-static bool isDefined(ColorAspects::Primaries p) {
-    return p <= ColorAspects::PrimariesBT2020;
-}
-
-static bool isValid(ColorAspects::MatrixCoeffs c) {
-    return c <= ColorAspects::MatrixOther;
-}
-
-static bool isDefined(ColorAspects::MatrixCoeffs c) {
-    return c <= ColorAspects::MatrixBT2020Constant;
-}
-
-//static
-int32_t CodecBase::wrapColorAspectsIntoColorStandard(
-        ColorAspects::Primaries primaries, ColorAspects::MatrixCoeffs coeffs) {
-    ColorStandard res;
-    if (sStandards.map(std::make_pair(primaries, coeffs), &res)) {
-        return res;
-    } else if (!isValid(primaries) || !isValid(coeffs)) {
-        return kColorStandardUnspecified;
-    }
-
-    // check platform media limits
-    uint32_t numPrimaries = ColorAspects::PrimariesBT2020 + 1;
-    if (isDefined(primaries) && isDefined(coeffs)) {
-        return kColorStandardExtendedStart + primaries + coeffs * numPrimaries;
-    } else {
-        return kColorStandardVendorStart + primaries + coeffs * 0x100;
-    }
-}
-
-//static
-status_t CodecBase::unwrapColorAspectsFromColorStandard(
-        int32_t standard,
-        ColorAspects::Primaries *primaries, ColorAspects::MatrixCoeffs *coeffs) {
-    std::pair<ColorAspects::Primaries, ColorAspects::MatrixCoeffs> res;
-    if (sStandards.map((ColorStandard)standard, &res)) {
-        *primaries = res.first;
-        *coeffs = res.second;
-        return OK;
-    }
-
-    int32_t start = kColorStandardExtendedStart;
-    int32_t numPrimaries = ColorAspects::PrimariesBT2020 + 1;
-    int32_t numCoeffs = ColorAspects::MatrixBT2020Constant + 1;
-    if (standard >= (int32_t)kColorStandardVendorStart) {
-        start = kColorStandardVendorStart;
-        numPrimaries = ColorAspects::PrimariesOther + 1; // 0x100
-        numCoeffs = ColorAspects::MatrixOther + 1; // 0x100;
-    }
-    if (standard >= start && standard < start + numPrimaries * numCoeffs) {
-        int32_t product = standard - start;
-        *primaries = (ColorAspects::Primaries)(product % numPrimaries);
-        *coeffs = (ColorAspects::MatrixCoeffs)(product / numPrimaries);
-        return OK;
-    }
-    *primaries = ColorAspects::PrimariesOther;
-    *coeffs = ColorAspects::MatrixOther;
-    return BAD_VALUE;
-}
-
-static bool isValid(ColorAspects::Range r) {
-    return r <= ColorAspects::RangeOther;
-}
-
-static bool isDefined(ColorAspects::Range r) {
-    return r <= ColorAspects::RangeLimited;
-}
-
-//  static
-int32_t CodecBase::wrapColorAspectsIntoColorRange(ColorAspects::Range range) {
-    ColorRange res;
-    if (sRanges.map(range, &res)) {
-        return res;
-    } else if (!isValid(range)) {
-        return kColorRangeUnspecified;
-    } else {
-        CHECK(!isDefined(range));
-        // all platform values are in sRanges
-        return kColorRangeVendorStart + range;
-    }
-}
-
-//static
-status_t CodecBase::unwrapColorAspectsFromColorRange(
-        int32_t range, ColorAspects::Range *aspect) {
-    if (sRanges.map((ColorRange)range, aspect)) {
-        return OK;
-    }
-
-    int32_t start = kColorRangeVendorStart;
-    int32_t numRanges = ColorAspects::RangeOther + 1; // 0x100
-    if (range >= start && range < start + numRanges) {
-        *aspect = (ColorAspects::Range)(range - start);
-        return OK;
-    }
-    *aspect = ColorAspects::RangeOther;
-    return BAD_VALUE;
-}
-
-static bool isValid(ColorAspects::Transfer t) {
-    return t <= ColorAspects::TransferOther;
-}
-
-static bool isDefined(ColorAspects::Transfer t) {
-    return t <= ColorAspects::TransferHLG
-            || (t >= ColorAspects::TransferSMPTE240M && t <= ColorAspects::TransferST428);
-}
-
-//  static
-int32_t CodecBase::wrapColorAspectsIntoColorTransfer(
-        ColorAspects::Transfer transfer) {
-    ColorTransfer res;
-    if (sTransfers.map(transfer, &res)) {
-        return res;
-    } else if (!isValid(transfer)) {
-        return kColorTransferUnspecified;
-    } else if (isDefined(transfer)) {
-        return kColorTransferExtendedStart + transfer;
-    } else {
-        // all platform values are in sRanges
-        return kColorTransferVendorStart + transfer;
-    }
-}
-
-//static
-status_t CodecBase::unwrapColorAspectsFromColorTransfer(
-        int32_t transfer, ColorAspects::Transfer *aspect) {
-    if (sTransfers.map((ColorTransfer)transfer, aspect)) {
-        return OK;
-    }
-
-    int32_t start = kColorTransferExtendedStart;
-    int32_t numTransfers = ColorAspects::TransferST428 + 1;
-    if (transfer >= (int32_t)kColorTransferVendorStart) {
-        start = kColorTransferVendorStart;
-        numTransfers = ColorAspects::TransferOther + 1; // 0x100
-    }
-    if (transfer >= start && transfer < start + numTransfers) {
-        *aspect = (ColorAspects::Transfer)(transfer - start);
-        return OK;
-    }
-    *aspect = ColorAspects::TransferOther;
-    return BAD_VALUE;
-}
-
-// static
-status_t CodecBase::convertPlatformColorAspectsToCodecAspects(
-    int32_t range, int32_t standard, int32_t transfer, ColorAspects &aspects) {
-    status_t res1 = unwrapColorAspectsFromColorRange(range, &aspects.mRange);
-    status_t res2 = unwrapColorAspectsFromColorStandard(
-            standard, &aspects.mPrimaries, &aspects.mMatrixCoeffs);
-    status_t res3 = unwrapColorAspectsFromColorTransfer(transfer, &aspects.mTransfer);
-    return res1 != OK ? res1 : (res2 != OK ? res2 : res3);
-}
-
-// static
-status_t CodecBase::convertCodecColorAspectsToPlatformAspects(
-    const ColorAspects &aspects, int32_t *range, int32_t *standard, int32_t *transfer) {
-    *range = wrapColorAspectsIntoColorRange(aspects.mRange);
-    *standard = wrapColorAspectsIntoColorStandard(aspects.mPrimaries, aspects.mMatrixCoeffs);
-    *transfer = wrapColorAspectsIntoColorTransfer(aspects.mTransfer);
-    if (isValid(aspects.mRange) && isValid(aspects.mPrimaries)
-            && isValid(aspects.mMatrixCoeffs) && isValid(aspects.mTransfer)) {
-        return OK;
-    } else {
-        return BAD_VALUE;
-    }
-}
-
-// static
-void CodecBase::setDefaultPlatformColorAspectsIfNeeded(
-        int32_t &range, int32_t &standard, int32_t &transfer,
-        int32_t width, int32_t height) {
-    if (range == CodecBase::kColorRangeUnspecified) {
-        range = CodecBase::kColorRangeLimited;
-    }
-
-    if (standard == CodecBase::kColorStandardUnspecified) {
-        // Default to BT2020, BT709 or BT601 based on size. Allow 2.35:1 aspect ratio. Limit BT601
-        // to PAL or smaller, BT2020 to 4K or larger, leaving BT709 for all resolutions in between.
-        if (width >= 3840 || height >= 3840 || width * (int64_t)height >= 3840 * 1634) {
-            standard = CodecBase::kColorStandardBT2020;
-        } else if ((width <= 720 && height > 480) || (height <= 720 && width > 480)) {
-            standard = CodecBase::kColorStandardBT601_625;
-        } else if ((width <= 720 && height <= 480) || (height <= 720 && width <= 480)) {
-            standard = CodecBase::kColorStandardBT601_525;
-        } else {
-            standard = CodecBase::kColorStandardBT709;
-        }
-    }
-
-    if (transfer == CodecBase::kColorTransferUnspecified) {
-        transfer = CodecBase::kColorTransferSMPTE_170M;
-    }
-}
-
-// static
-void CodecBase::setDefaultCodecColorAspectsIfNeeded(
-        ColorAspects &aspects, int32_t width, int32_t height) {
-    // reuse other method to get default aspects
-    int32_t range = 0, standard = 0, transfer = 0;
-    setDefaultPlatformColorAspectsIfNeeded(range, standard, transfer, width, height);
-    ColorAspects defaultAspects;
-    memset(&defaultAspects, 0, sizeof(defaultAspects));
-    convertPlatformColorAspectsToCodecAspects(range, standard, transfer, defaultAspects);
-
-    if (aspects.mRange == ColorAspects::RangeUnspecified) {
-        aspects.mRange = defaultAspects.mRange;
-    }
-    if (aspects.mPrimaries == ColorAspects::PrimariesUnspecified) {
-        aspects.mPrimaries = defaultAspects.mPrimaries;
-    }
-    if (aspects.mMatrixCoeffs == ColorAspects::MatrixUnspecified) {
-        aspects.mMatrixCoeffs = defaultAspects.mMatrixCoeffs;
-    }
-    if (aspects.mTransfer == ColorAspects::TransferUnspecified) {
-        aspects.mTransfer = defaultAspects.mTransfer;
-    }
-}
-
-/**************************************************************************************************/
-
 }  // namespace android
diff --git a/media/libstagefright/foundation/Android.mk b/media/libstagefright/foundation/Android.mk
index 711601f..3c3ed59 100644
--- a/media/libstagefright/foundation/Android.mk
+++ b/media/libstagefright/foundation/Android.mk
@@ -15,6 +15,7 @@
     AString.cpp                   \
     AStringUtils.cpp              \
     AWakeLock.cpp                 \
+    ColorUtils.cpp                \
     MediaBuffer.cpp               \
     MediaBufferGroup.cpp          \
     MetaData.cpp                  \
diff --git a/media/libstagefright/foundation/ColorUtils.cpp b/media/libstagefright/foundation/ColorUtils.cpp
new file mode 100644
index 0000000..2b86b0e
--- /dev/null
+++ b/media/libstagefright/foundation/ColorUtils.cpp
@@ -0,0 +1,312 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ColorUtils"
+
+#include <inttypes.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALookup.h>
+#include <media/stagefright/foundation/ColorUtils.h>
+
+namespace android {
+
+// shortcut names for brevity in the following tables
+typedef ColorAspects CA;
+typedef ColorUtils CU;
+
+ALookup<CU::ColorRange, CA::Range> sRanges{
+    {
+        { CU::kColorRangeLimited, CA::RangeLimited },
+        { CU::kColorRangeFull, CA::RangeFull },
+        { CU::kColorRangeUnspecified, CA::RangeUnspecified },
+    }
+};
+
+ALookup<CU::ColorStandard, std::pair<CA::Primaries, CA::MatrixCoeffs>> sStandards {
+    {
+        { CU::kColorStandardUnspecified,    { CA::PrimariesUnspecified, CA::MatrixUnspecified } },
+        { CU::kColorStandardBT709,          { CA::PrimariesBT709_5, CA::MatrixBT709_5 } },
+        { CU::kColorStandardBT601_625,      { CA::PrimariesBT601_6_625, CA::MatrixBT601_6 } },
+        { CU::kColorStandardBT601_625_Unadjusted,
+                                            // this is a really close match
+                                            { CA::PrimariesBT601_6_625, CA::MatrixBT709_5 } },
+        { CU::kColorStandardBT601_525,      { CA::PrimariesBT601_6_525, CA::MatrixBT601_6 } },
+        { CU::kColorStandardBT601_525_Unadjusted,
+                                            { CA::PrimariesBT601_6_525, CA::MatrixSMPTE240M } },
+        { CU::kColorStandardBT2020,         { CA::PrimariesBT2020, CA::MatrixBT2020 } },
+        { CU::kColorStandardBT2020Constant, { CA::PrimariesBT2020, CA::MatrixBT2020Constant } },
+        { CU::kColorStandardBT470M,         { CA::PrimariesBT470_6M, CA::MatrixBT470_6M } },
+        // NOTE: there is no close match to the matrix used by standard film, chose closest
+        { CU::kColorStandardFilm,           { CA::PrimariesGenericFilm, CA::MatrixBT2020 } },
+    }
+};
+
+ALookup<CU::ColorTransfer, CA::Transfer> sTransfers{
+    {
+        { CU::kColorTransferUnspecified,    CA::TransferUnspecified },
+        { CU::kColorTransferLinear,         CA::TransferLinear },
+        { CU::kColorTransferSRGB,           CA::TransferSRGB },
+        { CU::kColorTransferSMPTE_170M,     CA::TransferSMPTE170M },
+        { CU::kColorTransferGamma22,        CA::TransferGamma22 },
+        { CU::kColorTransferGamma28,        CA::TransferGamma28 },
+        { CU::kColorTransferST2084,         CA::TransferST2084 },
+        { CU::kColorTransferHLG,            CA::TransferHLG },
+    }
+};
+
+static bool isValid(ColorAspects::Primaries p) {
+    return p <= ColorAspects::PrimariesOther;
+}
+
+static bool isDefined(ColorAspects::Primaries p) {
+    return p <= ColorAspects::PrimariesBT2020;
+}
+
+static bool isValid(ColorAspects::MatrixCoeffs c) {
+    return c <= ColorAspects::MatrixOther;
+}
+
+static bool isDefined(ColorAspects::MatrixCoeffs c) {
+    return c <= ColorAspects::MatrixBT2020Constant;
+}
+
+//static
+int32_t ColorUtils::wrapColorAspectsIntoColorStandard(
+        ColorAspects::Primaries primaries, ColorAspects::MatrixCoeffs coeffs) {
+    ColorStandard res;
+    if (sStandards.map(std::make_pair(primaries, coeffs), &res)) {
+        return res;
+    } else if (!isValid(primaries) || !isValid(coeffs)) {
+        return kColorStandardUnspecified;
+    }
+
+    // check platform media limits
+    uint32_t numPrimaries = ColorAspects::PrimariesBT2020 + 1;
+    if (isDefined(primaries) && isDefined(coeffs)) {
+        return kColorStandardExtendedStart + primaries + coeffs * numPrimaries;
+    } else {
+        return kColorStandardVendorStart + primaries + coeffs * 0x100;
+    }
+}
+
+//static
+status_t ColorUtils::unwrapColorAspectsFromColorStandard(
+        int32_t standard,
+        ColorAspects::Primaries *primaries, ColorAspects::MatrixCoeffs *coeffs) {
+    std::pair<ColorAspects::Primaries, ColorAspects::MatrixCoeffs> res;
+    if (sStandards.map((ColorStandard)standard, &res)) {
+        *primaries = res.first;
+        *coeffs = res.second;
+        return OK;
+    }
+
+    int32_t start = kColorStandardExtendedStart;
+    int32_t numPrimaries = ColorAspects::PrimariesBT2020 + 1;
+    int32_t numCoeffs = ColorAspects::MatrixBT2020Constant + 1;
+    if (standard >= (int32_t)kColorStandardVendorStart) {
+        start = kColorStandardVendorStart;
+        numPrimaries = ColorAspects::PrimariesOther + 1; // 0x100
+        numCoeffs = ColorAspects::MatrixOther + 1; // 0x100;
+    }
+    if (standard >= start && standard < start + numPrimaries * numCoeffs) {
+        int32_t product = standard - start;
+        *primaries = (ColorAspects::Primaries)(product % numPrimaries);
+        *coeffs = (ColorAspects::MatrixCoeffs)(product / numPrimaries);
+        return OK;
+    }
+    *primaries = ColorAspects::PrimariesOther;
+    *coeffs = ColorAspects::MatrixOther;
+    return BAD_VALUE;
+}
+
+static bool isValid(ColorAspects::Range r) {
+    return r <= ColorAspects::RangeOther;
+}
+
+static bool isDefined(ColorAspects::Range r) {
+    return r <= ColorAspects::RangeLimited;
+}
+
+//  static
+int32_t ColorUtils::wrapColorAspectsIntoColorRange(ColorAspects::Range range) {
+    ColorRange res;
+    if (sRanges.map(range, &res)) {
+        return res;
+    } else if (!isValid(range)) {
+        return kColorRangeUnspecified;
+    } else {
+        CHECK(!isDefined(range));
+        // all platform values are in sRanges
+        return kColorRangeVendorStart + range;
+    }
+}
+
+//static
+status_t ColorUtils::unwrapColorAspectsFromColorRange(
+        int32_t range, ColorAspects::Range *aspect) {
+    if (sRanges.map((ColorRange)range, aspect)) {
+        return OK;
+    }
+
+    int32_t start = kColorRangeVendorStart;
+    int32_t numRanges = ColorAspects::RangeOther + 1; // 0x100
+    if (range >= start && range < start + numRanges) {
+        *aspect = (ColorAspects::Range)(range - start);
+        return OK;
+    }
+    *aspect = ColorAspects::RangeOther;
+    return BAD_VALUE;
+}
+
+static bool isValid(ColorAspects::Transfer t) {
+    return t <= ColorAspects::TransferOther;
+}
+
+static bool isDefined(ColorAspects::Transfer t) {
+    return t <= ColorAspects::TransferHLG
+            || (t >= ColorAspects::TransferSMPTE240M && t <= ColorAspects::TransferST428);
+}
+
+//  static
+int32_t ColorUtils::wrapColorAspectsIntoColorTransfer(
+        ColorAspects::Transfer transfer) {
+    ColorTransfer res;
+    if (sTransfers.map(transfer, &res)) {
+        return res;
+    } else if (!isValid(transfer)) {
+        return kColorTransferUnspecified;
+    } else if (isDefined(transfer)) {
+        return kColorTransferExtendedStart + transfer;
+    } else {
+        // all platform values are in sRanges
+        return kColorTransferVendorStart + transfer;
+    }
+}
+
+//static
+status_t ColorUtils::unwrapColorAspectsFromColorTransfer(
+        int32_t transfer, ColorAspects::Transfer *aspect) {
+    if (sTransfers.map((ColorTransfer)transfer, aspect)) {
+        return OK;
+    }
+
+    int32_t start = kColorTransferExtendedStart;
+    int32_t numTransfers = ColorAspects::TransferST428 + 1;
+    if (transfer >= (int32_t)kColorTransferVendorStart) {
+        start = kColorTransferVendorStart;
+        numTransfers = ColorAspects::TransferOther + 1; // 0x100
+    }
+    if (transfer >= start && transfer < start + numTransfers) {
+        *aspect = (ColorAspects::Transfer)(transfer - start);
+        return OK;
+    }
+    *aspect = ColorAspects::TransferOther;
+    return BAD_VALUE;
+}
+
+// static
+status_t ColorUtils::convertPlatformColorAspectsToCodecAspects(
+    int32_t range, int32_t standard, int32_t transfer, ColorAspects &aspects) {
+    status_t res1 = unwrapColorAspectsFromColorRange(range, &aspects.mRange);
+    status_t res2 = unwrapColorAspectsFromColorStandard(
+            standard, &aspects.mPrimaries, &aspects.mMatrixCoeffs);
+    status_t res3 = unwrapColorAspectsFromColorTransfer(transfer, &aspects.mTransfer);
+    return res1 != OK ? res1 : (res2 != OK ? res2 : res3);
+}
+
+// static
+status_t ColorUtils::convertCodecColorAspectsToPlatformAspects(
+    const ColorAspects &aspects, int32_t *range, int32_t *standard, int32_t *transfer) {
+    *range = wrapColorAspectsIntoColorRange(aspects.mRange);
+    *standard = wrapColorAspectsIntoColorStandard(aspects.mPrimaries, aspects.mMatrixCoeffs);
+    *transfer = wrapColorAspectsIntoColorTransfer(aspects.mTransfer);
+    if (isValid(aspects.mRange) && isValid(aspects.mPrimaries)
+            && isValid(aspects.mMatrixCoeffs) && isValid(aspects.mTransfer)) {
+        return OK;
+    } else {
+        return BAD_VALUE;
+    }
+}
+
+// static
+void ColorUtils::setDefaultPlatformColorAspectsIfNeeded(
+        int32_t &range, int32_t &standard, int32_t &transfer,
+        int32_t width, int32_t height) {
+    if (range == ColorUtils::kColorRangeUnspecified) {
+        range = ColorUtils::kColorRangeLimited;
+    }
+
+    if (standard == ColorUtils::kColorStandardUnspecified) {
+        // Default to BT2020, BT709 or BT601 based on size. Allow 2.35:1 aspect ratio. Limit BT601
+        // to PAL or smaller, BT2020 to 4K or larger, leaving BT709 for all resolutions in between.
+        if (width >= 3840 || height >= 3840 || width * (int64_t)height >= 3840 * 1634) {
+            standard = ColorUtils::kColorStandardBT2020;
+        } else if ((width <= 720 && height > 480) || (height <= 720 && width > 480)) {
+            standard = ColorUtils::kColorStandardBT601_625;
+        } else if ((width <= 720 && height <= 480) || (height <= 720 && width <= 480)) {
+            standard = ColorUtils::kColorStandardBT601_525;
+        } else {
+            standard = ColorUtils::kColorStandardBT709;
+        }
+    }
+
+    if (transfer == ColorUtils::kColorTransferUnspecified) {
+        transfer = ColorUtils::kColorTransferSMPTE_170M;
+    }
+}
+
+// static
+void ColorUtils::setDefaultCodecColorAspectsIfNeeded(
+        ColorAspects &aspects, int32_t width, int32_t height) {
+    ColorAspects::MatrixCoeffs coeffs;
+    ColorAspects::Primaries primaries;
+
+    // Default to BT2020, BT709 or BT601 based on size. Allow 2.35:1 aspect ratio. Limit BT601
+    // to PAL or smaller, BT2020 to 4K or larger, leaving BT709 for all resolutions in between.
+    if (width >= 3840 || height >= 3840 || width * (int64_t)height >= 3840 * 1634) {
+        primaries = ColorAspects::PrimariesBT2020;
+        coeffs = ColorAspects::MatrixBT2020;
+    } else if ((width <= 720 && height > 480 && height <= 576)
+            || (height <= 720 && width > 480 && width <= 576)) {
+        primaries = ColorAspects::PrimariesBT601_6_625;
+        coeffs = ColorAspects::MatrixBT601_6;
+    } else if ((width <= 720 && height <= 480) || (height <= 720 && width <= 480)) {
+        primaries = ColorAspects::PrimariesBT601_6_525;
+        coeffs = ColorAspects::MatrixBT601_6;
+    } else {
+        primaries = ColorAspects::PrimariesBT709_5;
+        coeffs = ColorAspects::MatrixBT709_5;
+    }
+
+    if (aspects.mRange == ColorAspects::RangeUnspecified) {
+        aspects.mRange = ColorAspects::RangeLimited;
+    }
+
+    if (aspects.mPrimaries == ColorAspects::PrimariesUnspecified) {
+        aspects.mPrimaries = primaries;
+    }
+    if (aspects.mMatrixCoeffs == ColorAspects::MatrixUnspecified) {
+        aspects.mMatrixCoeffs = coeffs;
+    }
+    if (aspects.mTransfer == ColorAspects::TransferUnspecified) {
+        aspects.mTransfer = ColorAspects::TransferSMPTE170M;
+    }
+}
+
+}  // namespace android
+