Merge "codec2: query supported pixel formats from Codec2InfoBuilder"
diff --git a/OWNERS b/OWNERS
index 0be1196..40c65e7 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,7 +1,6 @@
# Bug component: 1344
elaurent@google.com
etalvala@google.com
-hkuang@google.com
lajos@google.com
# go/android-fwk-media-solutions for info on areas of ownership.
diff --git a/media/OWNERS b/media/OWNERS
index 099729f..4a25b68 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -1,7 +1,6 @@
# Bug component: 1344
elaurent@google.com
essick@google.com
-hkuang@google.com
hunga@google.com
jiabin@google.com
jmtrivi@google.com
diff --git a/media/TEST_MAPPING b/media/TEST_MAPPING
index 5bc7262..41fe080 100644
--- a/media/TEST_MAPPING
+++ b/media/TEST_MAPPING
@@ -3,18 +3,18 @@
"presubmit-large": [
// runs whenever we change something in this tree
{
- "name": "CtsMediaTestCases",
+ "name": "CtsMediaCodecTestCases",
"options": [
{
- "include-filter": "android.media.cts.EncodeDecodeTest"
+ "include-filter": "android.media.codec.cts.EncodeDecodeTest"
}
]
},
{
- "name": "CtsMediaTestCases",
+ "name": "CtsMediaCodecTestCases",
"options": [
{
- "include-filter": "android.media.cts.DecodeEditEncodeTest"
+ "include-filter": "android.media.codec.cts.DecodeEditEncodeTest"
}
]
}
@@ -46,18 +46,18 @@
// runs regularly, independent of changes in this tree.
// signals if changes elsewhere break media functionality
{
- "name": "CtsMediaTestCases",
+ "name": "CtsMediaCodecTestCases",
"options": [
{
- "include-filter": "android.media.cts.EncodeDecodeTest"
+ "include-filter": "android.media.codec.cts.EncodeDecodeTest"
}
]
},
{
- "name": "CtsMediaTestCases",
+ "name": "CtsMediaCodecTestCases",
"options": [
{
- "include-filter": "android.media.cts.DecodeEditEncodeTest"
+ "include-filter": "android.media.codec.cts.DecodeEditEncodeTest"
}
]
}
diff --git a/media/codec2/TEST_MAPPING b/media/codec2/TEST_MAPPING
index 2b96055..f477f1c 100644
--- a/media/codec2/TEST_MAPPING
+++ b/media/codec2/TEST_MAPPING
@@ -37,6 +37,17 @@
]
},
{
+ "name": "CtsMediaDecoderTestCases",
+ "options": [
+ {
+ "include-annotation": "android.platform.test.annotations.Presubmit"
+ },
+ {
+ "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
+ }
+ ]
+ },
+ {
"name": "CtsMediaEncoderTestCases",
"options": [
{
@@ -48,6 +59,17 @@
]
},
{
+ "name": "CtsMediaCodecTestCases",
+ "options": [
+ {
+ "include-annotation": "android.platform.test.annotations.Presubmit"
+ },
+ {
+ "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
+ }
+ ]
+ },
+ {
"name": "CtsMediaPlayerTestCases",
"options": [
{
diff --git a/media/codec2/components/aom/C2SoftAomDec.cpp b/media/codec2/components/aom/C2SoftAomDec.cpp
index c08cd59..c7985ca 100644
--- a/media/codec2/components/aom/C2SoftAomDec.cpp
+++ b/media/codec2/components/aom/C2SoftAomDec.cpp
@@ -505,124 +505,6 @@
}
}
-static void copyOutputBufferToYuvPlanarFrame(
- uint8_t *dstY, uint8_t *dstU, uint8_t *dstV,
- const uint8_t *srcY, const uint8_t *srcU, const uint8_t *srcV,
- size_t srcYStride, size_t srcUStride, size_t srcVStride,
- size_t dstYStride, size_t dstUVStride,
- uint32_t width, uint32_t height) {
-
- for (size_t i = 0; i < height; ++i) {
- memcpy(dstY, srcY, width);
- srcY += srcYStride;
- dstY += dstYStride;
- }
-
- for (size_t i = 0; i < height / 2; ++i) {
- memcpy(dstV, srcV, width / 2);
- srcV += srcVStride;
- dstV += dstUVStride;
- }
-
- for (size_t i = 0; i < height / 2; ++i) {
- memcpy(dstU, srcU, width / 2);
- srcU += srcUStride;
- dstU += dstUVStride;
- }
-}
-
-static void convertYUV420Planar16ToY410(uint32_t *dst,
- const uint16_t *srcY, const uint16_t *srcU, const uint16_t *srcV,
- size_t srcYStride, size_t srcUStride, size_t srcVStride,
- size_t dstStride, size_t width, size_t height) {
-
- // Converting two lines at a time, slightly faster
- for (size_t y = 0; y < height; y += 2) {
- uint32_t *dstTop = (uint32_t *) dst;
- uint32_t *dstBot = (uint32_t *) (dst + dstStride);
- uint16_t *ySrcTop = (uint16_t*) srcY;
- uint16_t *ySrcBot = (uint16_t*) (srcY + srcYStride);
- uint16_t *uSrc = (uint16_t*) srcU;
- uint16_t *vSrc = (uint16_t*) srcV;
-
- uint32_t u01, v01, y01, y23, y45, y67, uv0, uv1;
- size_t x = 0;
- for (; x < width - 3; x += 4) {
-
- u01 = *((uint32_t*)uSrc); uSrc += 2;
- v01 = *((uint32_t*)vSrc); vSrc += 2;
-
- y01 = *((uint32_t*)ySrcTop); ySrcTop += 2;
- y23 = *((uint32_t*)ySrcTop); ySrcTop += 2;
- y45 = *((uint32_t*)ySrcBot); ySrcBot += 2;
- y67 = *((uint32_t*)ySrcBot); ySrcBot += 2;
-
- uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
- uv1 = (u01 >> 16) | ((v01 >> 16) << 20);
-
- *dstTop++ = 3 << 30 | ((y01 & 0x3FF) << 10) | uv0;
- *dstTop++ = 3 << 30 | ((y01 >> 16) << 10) | uv0;
- *dstTop++ = 3 << 30 | ((y23 & 0x3FF) << 10) | uv1;
- *dstTop++ = 3 << 30 | ((y23 >> 16) << 10) | uv1;
-
- *dstBot++ = 3 << 30 | ((y45 & 0x3FF) << 10) | uv0;
- *dstBot++ = 3 << 30 | ((y45 >> 16) << 10) | uv0;
- *dstBot++ = 3 << 30 | ((y67 & 0x3FF) << 10) | uv1;
- *dstBot++ = 3 << 30 | ((y67 >> 16) << 10) | uv1;
- }
-
- // There should be at most 2 more pixels to process. Note that we don't
- // need to consider odd case as the buffer is always aligned to even.
- if (x < width) {
- u01 = *uSrc;
- v01 = *vSrc;
- y01 = *((uint32_t*)ySrcTop);
- y45 = *((uint32_t*)ySrcBot);
- uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
- *dstTop++ = ((y01 & 0x3FF) << 10) | uv0;
- *dstTop++ = ((y01 >> 16) << 10) | uv0;
- *dstBot++ = ((y45 & 0x3FF) << 10) | uv0;
- *dstBot++ = ((y45 >> 16) << 10) | uv0;
- }
-
- srcY += srcYStride * 2;
- srcU += srcUStride;
- srcV += srcVStride;
- dst += dstStride * 2;
- }
-
- return;
-}
-
-static void convertYUV420Planar16ToYUV420Planar(
- uint8_t *dstY, uint8_t *dstU, uint8_t *dstV,
- const uint16_t *srcY, const uint16_t *srcU, const uint16_t *srcV,
- size_t srcYStride, size_t srcUStride, size_t srcVStride,
- size_t dstYStride, size_t dstUVStride,
- size_t width, size_t height) {
-
- for (size_t y = 0; y < height; ++y) {
- for (size_t x = 0; x < width; ++x) {
- dstY[x] = (uint8_t)(srcY[x] >> 2);
- }
-
- srcY += srcYStride;
- dstY += dstYStride;
- }
-
- for (size_t y = 0; y < (height + 1) / 2; ++y) {
- for (size_t x = 0; x < (width + 1) / 2; ++x) {
- dstU[x] = (uint8_t)(srcU[x] >> 2);
- dstV[x] = (uint8_t)(srcV[x] >> 2);
- }
-
- srcU += srcUStride;
- srcV += srcVStride;
- dstU += dstUVStride;
- dstV += dstUVStride;
- }
- return;
-}
bool C2SoftAomDec::outputBuffer(
const std::shared_ptr<C2BlockPool> &pool,
const std::unique_ptr<C2Work> &work)
@@ -711,21 +593,16 @@
dstYStride / sizeof(uint32_t),
mWidth, mHeight);
} else {
- convertYUV420Planar16ToYUV420Planar(dstY, dstU, dstV,
- srcY, srcU, srcV,
- srcYStride / 2, srcUStride / 2, srcVStride / 2,
- dstYStride, dstUVStride,
- mWidth, mHeight);
+ convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2,
+ srcUStride / 2, srcVStride / 2, dstYStride, dstUVStride,
+ mWidth, mHeight);
}
} else {
const uint8_t *srcY = (const uint8_t *)img->planes[AOM_PLANE_Y];
const uint8_t *srcU = (const uint8_t *)img->planes[AOM_PLANE_U];
const uint8_t *srcV = (const uint8_t *)img->planes[AOM_PLANE_V];
- copyOutputBufferToYuvPlanarFrame(
- dstY, dstU, dstV, srcY, srcU, srcV,
- srcYStride, srcUStride, srcVStride,
- dstYStride, dstUVStride,
- mWidth, mHeight);
+ convertYUV420Planar8ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
+ srcVStride, dstYStride, dstUVStride, mWidth, mHeight);
}
finishWork(*(int64_t*)img->user_priv, work, std::move(block));
block = nullptr;
diff --git a/media/codec2/components/base/SimpleC2Component.cpp b/media/codec2/components/base/SimpleC2Component.cpp
index 6c4b7d9..99ff450 100644
--- a/media/codec2/components/base/SimpleC2Component.cpp
+++ b/media/codec2/components/base/SimpleC2Component.cpp
@@ -29,7 +29,179 @@
#include <SimpleC2Component.h>
namespace android {
+constexpr uint8_t kNeutralUVBitDepth8 = 128;
+constexpr uint16_t kNeutralUVBitDepth10 = 512;
+void convertYUV420Planar8ToYV12(uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, const uint8_t *srcY,
+ const uint8_t *srcU, const uint8_t *srcV, size_t srcYStride,
+ size_t srcUStride, size_t srcVStride, size_t dstYStride,
+ size_t dstUVStride, uint32_t width, uint32_t height,
+ bool isMonochrome) {
+ for (size_t i = 0; i < height; ++i) {
+ memcpy(dstY, srcY, width);
+ srcY += srcYStride;
+ dstY += dstYStride;
+ }
+
+ if (isMonochrome) {
+ // Fill with neutral U/V values.
+ for (size_t i = 0; i < height / 2; ++i) {
+ memset(dstV, kNeutralUVBitDepth8, width / 2);
+ memset(dstU, kNeutralUVBitDepth8, width / 2);
+ dstV += dstUVStride;
+ dstU += dstUVStride;
+ }
+ return;
+ }
+
+ for (size_t i = 0; i < height / 2; ++i) {
+ memcpy(dstV, srcV, width / 2);
+ srcV += srcVStride;
+ dstV += dstUVStride;
+ }
+
+ for (size_t i = 0; i < height / 2; ++i) {
+ memcpy(dstU, srcU, width / 2);
+ srcU += srcUStride;
+ dstU += dstUVStride;
+ }
+}
+
+void convertYUV420Planar16ToY410(uint32_t *dst, const uint16_t *srcY, const uint16_t *srcU,
+ const uint16_t *srcV, size_t srcYStride, size_t srcUStride,
+ size_t srcVStride, size_t dstStride, size_t width, size_t height) {
+ // Converting two lines at a time, slightly faster
+ for (size_t y = 0; y < height; y += 2) {
+ uint32_t *dstTop = (uint32_t *)dst;
+ uint32_t *dstBot = (uint32_t *)(dst + dstStride);
+ uint16_t *ySrcTop = (uint16_t *)srcY;
+ uint16_t *ySrcBot = (uint16_t *)(srcY + srcYStride);
+ uint16_t *uSrc = (uint16_t *)srcU;
+ uint16_t *vSrc = (uint16_t *)srcV;
+
+ uint32_t u01, v01, y01, y23, y45, y67, uv0, uv1;
+ size_t x = 0;
+ for (; x < width - 3; x += 4) {
+ u01 = *((uint32_t *)uSrc);
+ uSrc += 2;
+ v01 = *((uint32_t *)vSrc);
+ vSrc += 2;
+
+ y01 = *((uint32_t *)ySrcTop);
+ ySrcTop += 2;
+ y23 = *((uint32_t *)ySrcTop);
+ ySrcTop += 2;
+ y45 = *((uint32_t *)ySrcBot);
+ ySrcBot += 2;
+ y67 = *((uint32_t *)ySrcBot);
+ ySrcBot += 2;
+
+ uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
+ uv1 = (u01 >> 16) | ((v01 >> 16) << 20);
+
+ *dstTop++ = 3 << 30 | ((y01 & 0x3FF) << 10) | uv0;
+ *dstTop++ = 3 << 30 | ((y01 >> 16) << 10) | uv0;
+ *dstTop++ = 3 << 30 | ((y23 & 0x3FF) << 10) | uv1;
+ *dstTop++ = 3 << 30 | ((y23 >> 16) << 10) | uv1;
+
+ *dstBot++ = 3 << 30 | ((y45 & 0x3FF) << 10) | uv0;
+ *dstBot++ = 3 << 30 | ((y45 >> 16) << 10) | uv0;
+ *dstBot++ = 3 << 30 | ((y67 & 0x3FF) << 10) | uv1;
+ *dstBot++ = 3 << 30 | ((y67 >> 16) << 10) | uv1;
+ }
+
+ // There should be at most 2 more pixels to process. Note that we don't
+ // need to consider odd case as the buffer is always aligned to even.
+ if (x < width) {
+ u01 = *uSrc;
+ v01 = *vSrc;
+ y01 = *((uint32_t *)ySrcTop);
+ y45 = *((uint32_t *)ySrcBot);
+ uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
+ *dstTop++ = ((y01 & 0x3FF) << 10) | uv0;
+ *dstTop++ = ((y01 >> 16) << 10) | uv0;
+ *dstBot++ = ((y45 & 0x3FF) << 10) | uv0;
+ *dstBot++ = ((y45 >> 16) << 10) | uv0;
+ }
+
+ srcY += srcYStride * 2;
+ srcU += srcUStride;
+ srcV += srcVStride;
+ dst += dstStride * 2;
+ }
+}
+
+void convertYUV420Planar16ToYV12(uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, const uint16_t *srcY,
+ const uint16_t *srcU, const uint16_t *srcV, size_t srcYStride,
+ size_t srcUStride, size_t srcVStride, size_t dstYStride,
+ size_t dstUVStride, size_t width, size_t height,
+ bool isMonochrome) {
+ for (size_t y = 0; y < height; ++y) {
+ for (size_t x = 0; x < width; ++x) {
+ dstY[x] = (uint8_t)(srcY[x] >> 2);
+ }
+ srcY += srcYStride;
+ dstY += dstYStride;
+ }
+
+ if (isMonochrome) {
+ // Fill with neutral U/V values.
+ for (size_t y = 0; y < (height + 1) / 2; ++y) {
+ memset(dstV, kNeutralUVBitDepth8, (width + 1) / 2);
+ memset(dstU, kNeutralUVBitDepth8, (width + 1) / 2);
+ dstV += dstUVStride;
+ dstU += dstUVStride;
+ }
+ return;
+ }
+
+ for (size_t y = 0; y < (height + 1) / 2; ++y) {
+ for (size_t x = 0; x < (width + 1) / 2; ++x) {
+ dstU[x] = (uint8_t)(srcU[x] >> 2);
+ dstV[x] = (uint8_t)(srcV[x] >> 2);
+ }
+ srcU += srcUStride;
+ srcV += srcVStride;
+ dstU += dstUVStride;
+ dstV += dstUVStride;
+ }
+}
+
+void convertYUV420Planar16ToP010(uint16_t *dstY, uint16_t *dstUV, const uint16_t *srcY,
+ const uint16_t *srcU, const uint16_t *srcV, size_t srcYStride,
+ size_t srcUStride, size_t srcVStride, size_t dstYStride,
+ size_t dstUVStride, size_t width, size_t height,
+ bool isMonochrome) {
+ for (size_t y = 0; y < height; ++y) {
+ for (size_t x = 0; x < width; ++x) {
+ dstY[x] = srcY[x] << 6;
+ }
+ srcY += srcYStride;
+ dstY += dstYStride;
+ }
+
+ if (isMonochrome) {
+ // Fill with neutral U/V values.
+ for (size_t y = 0; y < (height + 1) / 2; ++y) {
+ for (size_t x = 0; x < (width + 1) / 2; ++x) {
+ dstUV[2 * x] = kNeutralUVBitDepth10 << 6;
+ dstUV[2 * x + 1] = kNeutralUVBitDepth10 << 6;
+ }
+ dstUV += dstUVStride;
+ }
+ return;
+ }
+
+ for (size_t y = 0; y < (height + 1) / 2; ++y) {
+ for (size_t x = 0; x < (width + 1) / 2; ++x) {
+ dstUV[2 * x] = srcU[x] << 6;
+ dstUV[2 * x + 1] = srcV[x] << 6;
+ }
+ srcU += srcUStride;
+ srcV += srcVStride;
+ dstUV += dstUVStride;
+ }
+}
std::unique_ptr<C2Work> SimpleC2Component::WorkQueue::pop_front() {
std::unique_ptr<C2Work> work = std::move(mQueue.front().work);
mQueue.pop_front();
diff --git a/media/codec2/components/base/include/SimpleC2Component.h b/media/codec2/components/base/include/SimpleC2Component.h
index e5e16d8..3b4e212 100644
--- a/media/codec2/components/base/include/SimpleC2Component.h
+++ b/media/codec2/components/base/include/SimpleC2Component.h
@@ -28,6 +28,24 @@
namespace android {
+void convertYUV420Planar8ToYV12(uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, const uint8_t *srcY,
+ const uint8_t *srcU, const uint8_t *srcV, size_t srcYStride,
+ size_t srcUStride, size_t srcVStride, size_t dstYStride,
+ size_t dstUVStride, uint32_t width, uint32_t height,
+ bool isMonochrome = false);
+void convertYUV420Planar16ToY410(uint32_t *dst, const uint16_t *srcY, const uint16_t *srcU,
+ const uint16_t *srcV, size_t srcYStride, size_t srcUStride,
+ size_t srcVStride, size_t dstStride, size_t width, size_t height);
+void convertYUV420Planar16ToYV12(uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, const uint16_t *srcY,
+ const uint16_t *srcU, const uint16_t *srcV, size_t srcYStride,
+ size_t srcUStride, size_t srcVStride, size_t dstYStride,
+ size_t dstUVStride, size_t width, size_t height,
+ bool isMonochrome = false);
+void convertYUV420Planar16ToP010(uint16_t *dstY, uint16_t *dstUV, const uint16_t *srcY,
+ const uint16_t *srcU, const uint16_t *srcV, size_t srcYStride,
+ size_t srcUStride, size_t srcVStride, size_t dstYStride,
+ size_t dstUVStride, size_t width, size_t height,
+ bool isMonochrome = false);
class SimpleC2Component
: public C2Component, public std::enable_shared_from_this<SimpleC2Component> {
public:
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.cpp b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
index 475d863..ff6080d 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.cpp
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
@@ -28,11 +28,6 @@
#include <media/stagefright/foundation/MediaDefs.h>
namespace android {
-namespace {
-
-constexpr uint8_t NEUTRAL_UV_VALUE = 128;
-
-} // namespace
// codecname set and passed in as a compile flag from Android.bp
constexpr char COMPONENT_NAME[] = CODECNAME;
@@ -545,150 +540,6 @@
}
}
-static void copyOutputBufferToYV12Frame(uint8_t *dstY, uint8_t *dstU, uint8_t *dstV,
- const uint8_t *srcY, const uint8_t *srcU, const uint8_t *srcV,
- size_t srcYStride, size_t srcUStride, size_t srcVStride,
- size_t dstYStride, size_t dstUVStride,
- uint32_t width, uint32_t height,
- bool isMonochrome) {
-
- for (size_t i = 0; i < height; ++i) {
- memcpy(dstY, srcY, width);
- srcY += srcYStride;
- dstY += dstYStride;
- }
-
- if (isMonochrome) {
- // Fill with neutral U/V values.
- for (size_t i = 0; i < height / 2; ++i) {
- memset(dstV, NEUTRAL_UV_VALUE, width / 2);
- memset(dstU, NEUTRAL_UV_VALUE, width / 2);
- dstV += dstUVStride;
- dstU += dstUVStride;
- }
- return;
- }
-
- for (size_t i = 0; i < height / 2; ++i) {
- memcpy(dstV, srcV, width / 2);
- srcV += srcVStride;
- dstV += dstUVStride;
- }
-
- for (size_t i = 0; i < height / 2; ++i) {
- memcpy(dstU, srcU, width / 2);
- srcU += srcUStride;
- dstU += dstUVStride;
- }
-}
-
-static void convertYUV420Planar16ToY410(uint32_t *dst, const uint16_t *srcY,
- const uint16_t *srcU,
- const uint16_t *srcV, size_t srcYStride,
- size_t srcUStride, size_t srcVStride,
- size_t dstStride, size_t width,
- size_t height) {
- // Converting two lines at a time, slightly faster
- for (size_t y = 0; y < height; y += 2) {
- uint32_t *dstTop = (uint32_t *)dst;
- uint32_t *dstBot = (uint32_t *)(dst + dstStride);
- uint16_t *ySrcTop = (uint16_t *)srcY;
- uint16_t *ySrcBot = (uint16_t *)(srcY + srcYStride);
- uint16_t *uSrc = (uint16_t *)srcU;
- uint16_t *vSrc = (uint16_t *)srcV;
-
- uint32_t u01, v01, y01, y23, y45, y67, uv0, uv1;
- size_t x = 0;
- for (; x < width - 3; x += 4) {
- u01 = *((uint32_t *)uSrc);
- uSrc += 2;
- v01 = *((uint32_t *)vSrc);
- vSrc += 2;
-
- y01 = *((uint32_t *)ySrcTop);
- ySrcTop += 2;
- y23 = *((uint32_t *)ySrcTop);
- ySrcTop += 2;
- y45 = *((uint32_t *)ySrcBot);
- ySrcBot += 2;
- y67 = *((uint32_t *)ySrcBot);
- ySrcBot += 2;
-
- uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
- uv1 = (u01 >> 16) | ((v01 >> 16) << 20);
-
- *dstTop++ = 3 << 30 | ((y01 & 0x3FF) << 10) | uv0;
- *dstTop++ = 3 << 30 | ((y01 >> 16) << 10) | uv0;
- *dstTop++ = 3 << 30 | ((y23 & 0x3FF) << 10) | uv1;
- *dstTop++ = 3 << 30 | ((y23 >> 16) << 10) | uv1;
-
- *dstBot++ = 3 << 30 | ((y45 & 0x3FF) << 10) | uv0;
- *dstBot++ = 3 << 30 | ((y45 >> 16) << 10) | uv0;
- *dstBot++ = 3 << 30 | ((y67 & 0x3FF) << 10) | uv1;
- *dstBot++ = 3 << 30 | ((y67 >> 16) << 10) | uv1;
- }
-
- // There should be at most 2 more pixels to process. Note that we don't
- // need to consider odd case as the buffer is always aligned to even.
- if (x < width) {
- u01 = *uSrc;
- v01 = *vSrc;
- y01 = *((uint32_t *)ySrcTop);
- y45 = *((uint32_t *)ySrcBot);
- uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
- *dstTop++ = ((y01 & 0x3FF) << 10) | uv0;
- *dstTop++ = ((y01 >> 16) << 10) | uv0;
- *dstBot++ = ((y45 & 0x3FF) << 10) | uv0;
- *dstBot++ = ((y45 >> 16) << 10) | uv0;
- }
-
- srcY += srcYStride * 2;
- srcU += srcUStride;
- srcV += srcVStride;
- dst += dstStride * 2;
- }
-}
-
-static void convertYUV420Planar16ToYUV420Planar(
- uint8_t *dstY, uint8_t *dstU, uint8_t *dstV,
- const uint16_t *srcY, const uint16_t *srcU, const uint16_t *srcV,
- size_t srcYStride, size_t srcUStride, size_t srcVStride,
- size_t dstYStride, size_t dstUVStride,
- size_t width, size_t height, bool isMonochrome) {
-
- for (size_t y = 0; y < height; ++y) {
- for (size_t x = 0; x < width; ++x) {
- dstY[x] = (uint8_t)(srcY[x] >> 2);
- }
-
- srcY += srcYStride;
- dstY += dstYStride;
- }
-
- if (isMonochrome) {
- // Fill with neutral U/V values.
- for (size_t y = 0; y < (height + 1) / 2; ++y) {
- memset(dstV, NEUTRAL_UV_VALUE, (width + 1) / 2);
- memset(dstU, NEUTRAL_UV_VALUE, (width + 1) / 2);
- dstV += dstUVStride;
- dstU += dstUVStride;
- }
- return;
- }
-
- for (size_t y = 0; y < (height + 1) / 2; ++y) {
- for (size_t x = 0; x < (width + 1) / 2; ++x) {
- dstU[x] = (uint8_t)(srcU[x] >> 2);
- dstV[x] = (uint8_t)(srcV[x] >> 2);
- }
-
- srcU += srcUStride;
- srcV += srcVStride;
- dstU += dstUVStride;
- dstV += dstUVStride;
- }
-}
-
void C2SoftGav1Dec::getVuiParams(const libgav1::DecoderBuffer *buffer) {
VuiColorAspects vuiColorAspects;
vuiColorAspects.primaries = buffer->color_primary;
@@ -841,22 +692,24 @@
const uint16_t *srcV = (const uint16_t *)buffer->plane[2];
if (format == HAL_PIXEL_FORMAT_RGBA_1010102) {
- convertYUV420Planar16ToY410(
- (uint32_t *)dstY, srcY, srcU, srcV, srcYStride / 2, srcUStride / 2,
- srcVStride / 2, dstYStride / sizeof(uint32_t), mWidth, mHeight);
+ convertYUV420Planar16ToY410((uint32_t *)dstY, srcY, srcU, srcV, srcYStride / 2,
+ srcUStride / 2, srcVStride / 2, dstYStride / sizeof(uint32_t),
+ mWidth, mHeight);
+ } else if (format == HAL_PIXEL_FORMAT_YCBCR_P010) {
+ convertYUV420Planar16ToP010((uint16_t *)dstY, (uint16_t *)dstU, srcY, srcU, srcV,
+ srcYStride / 2, srcUStride / 2, srcVStride / 2, dstYStride / 2,
+ dstUVStride / 2, mWidth, mHeight, isMonochrome);
} else {
- convertYUV420Planar16ToYUV420Planar(
- dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2, srcUStride / 2,
- srcVStride / 2, dstYStride, dstUVStride, mWidth, mHeight,
- isMonochrome);
+ convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2,
+ srcUStride / 2, srcVStride / 2, dstYStride, dstUVStride, mWidth,
+ mHeight, isMonochrome);
}
} else {
const uint8_t *srcY = (const uint8_t *)buffer->plane[0];
const uint8_t *srcU = (const uint8_t *)buffer->plane[1];
const uint8_t *srcV = (const uint8_t *)buffer->plane[2];
- copyOutputBufferToYV12Frame(
- dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride,
- dstYStride, dstUVStride, mWidth, mHeight, isMonochrome);
+ convertYUV420Planar8ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
+ srcVStride, dstYStride, dstUVStride, mWidth, mHeight, isMonochrome);
}
finishWork(buffer->user_private_data, work, std::move(block));
block = nullptr;
diff --git a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
index 81f4679..54a1d0e 100644
--- a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
+++ b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
@@ -419,40 +419,6 @@
return resChanged;
}
-/* TODO: can remove temporary copy after library supports writing to display
- * buffer Y, U and V plane pointers using stride info. */
-static void copyOutputBufferToYuvPlanarFrame(
- uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, uint8_t *src,
- size_t dstYStride, size_t dstUVStride,
- size_t srcYStride, uint32_t width,
- uint32_t height) {
- size_t srcUVStride = srcYStride / 2;
- uint8_t *srcStart = src;
-
- size_t vStride = align(height, 16);
- for (size_t i = 0; i < height; ++i) {
- memcpy(dstY, src, width);
- src += srcYStride;
- dstY += dstYStride;
- }
-
- /* U buffer */
- src = srcStart + vStride * srcYStride;
- for (size_t i = 0; i < height / 2; ++i) {
- memcpy(dstU, src, width / 2);
- src += srcUVStride;
- dstU += dstUVStride;
- }
-
- /* V buffer */
- src = srcStart + vStride * srcYStride * 5 / 4;
- for (size_t i = 0; i < height / 2; ++i) {
- memcpy(dstV, src, width / 2);
- src += srcUVStride;
- dstV += dstUVStride;
- }
-}
-
void C2SoftMpeg4Dec::process(
const std::unique_ptr<C2Work> &work,
const std::shared_ptr<C2BlockPool> &pool) {
@@ -636,11 +602,17 @@
C2PlanarLayout layout = wView.layout();
size_t dstYStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
size_t dstUVStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
- (void)copyOutputBufferToYuvPlanarFrame(
- outputBufferY, outputBufferU, outputBufferV,
- mOutputBuffer[mNumSamplesOutput & 1],
- dstYStride, dstUVStride,
- align(mWidth, 16), mWidth, mHeight);
+ size_t srcYStride = align(mWidth, 16);
+ size_t srcUStride = srcYStride / 2;
+ size_t srcVStride = srcYStride / 2;
+ size_t vStride = align(mHeight, 16);
+ const uint8_t *srcY = (const uint8_t *)mOutputBuffer[mNumSamplesOutput & 1];
+ const uint8_t *srcU = (const uint8_t *)srcY + vStride * srcYStride;
+ const uint8_t *srcV = (const uint8_t *)srcY + vStride * srcYStride * 5 / 4;
+
+ convertYUV420Planar8ToYV12(outputBufferY, outputBufferU, outputBufferV, srcY, srcU, srcV,
+ srcYStride, srcUStride, srcVStride, dstYStride, dstUVStride,
+ mWidth, mHeight);
inPos += inSize - (size_t)tmpInSize;
finishWork(workIndex, work);
diff --git a/media/codec2/components/vpx/C2SoftVpxDec.cpp b/media/codec2/components/vpx/C2SoftVpxDec.cpp
index 2da9d5b..0a27821 100644
--- a/media/codec2/components/vpx/C2SoftVpxDec.cpp
+++ b/media/codec2/components/vpx/C2SoftVpxDec.cpp
@@ -640,125 +640,6 @@
}
}
-static void copyOutputBufferToYuvPlanarFrame(
- uint8_t *dstY, uint8_t *dstU, uint8_t *dstV,
- const uint8_t *srcY, const uint8_t *srcU, const uint8_t *srcV,
- size_t srcYStride, size_t srcUStride, size_t srcVStride,
- size_t dstYStride, size_t dstUVStride,
- uint32_t width, uint32_t height) {
-
- for (size_t i = 0; i < height; ++i) {
- memcpy(dstY, srcY, width);
- srcY += srcYStride;
- dstY += dstYStride;
- }
-
- for (size_t i = 0; i < height / 2; ++i) {
- memcpy(dstV, srcV, width / 2);
- srcV += srcVStride;
- dstV += dstUVStride;
- }
-
- for (size_t i = 0; i < height / 2; ++i) {
- memcpy(dstU, srcU, width / 2);
- srcU += srcUStride;
- dstU += dstUVStride;
- }
-
-}
-
-static void convertYUV420Planar16ToY410(uint32_t *dst,
- const uint16_t *srcY, const uint16_t *srcU, const uint16_t *srcV,
- size_t srcYStride, size_t srcUStride, size_t srcVStride,
- size_t dstStride, size_t width, size_t height) {
-
- // Converting two lines at a time, slightly faster
- for (size_t y = 0; y < height; y += 2) {
- uint32_t *dstTop = (uint32_t *) dst;
- uint32_t *dstBot = (uint32_t *) (dst + dstStride);
- uint16_t *ySrcTop = (uint16_t*) srcY;
- uint16_t *ySrcBot = (uint16_t*) (srcY + srcYStride);
- uint16_t *uSrc = (uint16_t*) srcU;
- uint16_t *vSrc = (uint16_t*) srcV;
-
- uint32_t u01, v01, y01, y23, y45, y67, uv0, uv1;
- size_t x = 0;
- for (; x < width - 3; x += 4) {
-
- u01 = *((uint32_t*)uSrc); uSrc += 2;
- v01 = *((uint32_t*)vSrc); vSrc += 2;
-
- y01 = *((uint32_t*)ySrcTop); ySrcTop += 2;
- y23 = *((uint32_t*)ySrcTop); ySrcTop += 2;
- y45 = *((uint32_t*)ySrcBot); ySrcBot += 2;
- y67 = *((uint32_t*)ySrcBot); ySrcBot += 2;
-
- uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
- uv1 = (u01 >> 16) | ((v01 >> 16) << 20);
-
- *dstTop++ = 3 << 30 | ((y01 & 0x3FF) << 10) | uv0;
- *dstTop++ = 3 << 30 | ((y01 >> 16) << 10) | uv0;
- *dstTop++ = 3 << 30 | ((y23 & 0x3FF) << 10) | uv1;
- *dstTop++ = 3 << 30 | ((y23 >> 16) << 10) | uv1;
-
- *dstBot++ = 3 << 30 | ((y45 & 0x3FF) << 10) | uv0;
- *dstBot++ = 3 << 30 | ((y45 >> 16) << 10) | uv0;
- *dstBot++ = 3 << 30 | ((y67 & 0x3FF) << 10) | uv1;
- *dstBot++ = 3 << 30 | ((y67 >> 16) << 10) | uv1;
- }
-
- // There should be at most 2 more pixels to process. Note that we don't
- // need to consider odd case as the buffer is always aligned to even.
- if (x < width) {
- u01 = *uSrc;
- v01 = *vSrc;
- y01 = *((uint32_t*)ySrcTop);
- y45 = *((uint32_t*)ySrcBot);
- uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
- *dstTop++ = ((y01 & 0x3FF) << 10) | uv0;
- *dstTop++ = ((y01 >> 16) << 10) | uv0;
- *dstBot++ = ((y45 & 0x3FF) << 10) | uv0;
- *dstBot++ = ((y45 >> 16) << 10) | uv0;
- }
-
- srcY += srcYStride * 2;
- srcU += srcUStride;
- srcV += srcVStride;
- dst += dstStride * 2;
- }
-
- return;
-}
-
-static void convertYUV420Planar16ToYUV420Planar(
- uint8_t *dstY, uint8_t *dstU, uint8_t *dstV,
- const uint16_t *srcY, const uint16_t *srcU, const uint16_t *srcV,
- size_t srcYStride, size_t srcUStride, size_t srcVStride,
- size_t dstYStride, size_t dstUVStride,
- size_t width, size_t height) {
-
- for (size_t y = 0; y < height; ++y) {
- for (size_t x = 0; x < width; ++x) {
- dstY[x] = (uint8_t)(srcY[x] >> 2);
- }
-
- srcY += srcYStride;
- dstY += dstYStride;
- }
-
- for (size_t y = 0; y < (height + 1) / 2; ++y) {
- for (size_t x = 0; x < (width + 1) / 2; ++x) {
- dstU[x] = (uint8_t)(srcU[x] >> 2);
- dstV[x] = (uint8_t)(srcV[x] >> 2);
- }
-
- srcU += srcUStride;
- srcV += srcVStride;
- dstU += dstUVStride;
- dstV += dstUVStride;
- }
- return;
-}
status_t C2SoftVpxDec::outputBuffer(
const std::shared_ptr<C2BlockPool> &pool,
const std::unique_ptr<C2Work> &work)
@@ -876,24 +757,22 @@
queue->cond.signal();
queue.waitForCondition(queue->cond);
}
+ } else if (format == HAL_PIXEL_FORMAT_YCBCR_P010) {
+ convertYUV420Planar16ToP010((uint16_t *)dstY, (uint16_t *)dstU, srcY, srcU, srcV,
+ srcYStride / 2, srcUStride / 2, srcVStride / 2,
+ dstYStride / 2, dstUVStride / 2, mWidth, mHeight);
} else {
- convertYUV420Planar16ToYUV420Planar(dstY, dstU, dstV,
- srcY, srcU, srcV,
- srcYStride / 2, srcUStride / 2, srcVStride / 2,
- dstYStride, dstUVStride,
- mWidth, mHeight);
+ convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2,
+ srcUStride / 2, srcVStride / 2, dstYStride, dstUVStride,
+ mWidth, mHeight);
}
} else {
const uint8_t *srcY = (const uint8_t *)img->planes[VPX_PLANE_Y];
const uint8_t *srcU = (const uint8_t *)img->planes[VPX_PLANE_U];
const uint8_t *srcV = (const uint8_t *)img->planes[VPX_PLANE_V];
- copyOutputBufferToYuvPlanarFrame(
- dstY, dstU, dstV,
- srcY, srcU, srcV,
- srcYStride, srcUStride, srcVStride,
- dstYStride, dstUVStride,
- mWidth, mHeight);
+ convertYUV420Planar8ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
+ srcVStride, dstYStride, dstUVStride, mWidth, mHeight);
}
finishWork(((c2_cntr64_t *)img->user_priv)->peekull(), work, std::move(block));
return OK;
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index feaa98c..70e742c 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -59,6 +59,7 @@
enum drc_compression_mode_t : int32_t; ///< DRC compression mode
enum drc_effect_type_t : int32_t; ///< DRC effect type
enum drc_album_mode_t : int32_t; ///< DRC album mode
+ enum hdr_dynamic_metadata_type_t : uint32_t; ///< HDR dynamic metadata type
enum intra_refresh_mode_t : uint32_t; ///< intra refresh modes
enum level_t : uint32_t; ///< coding level
enum ordinal_key_t : uint32_t; ///< work ordering keys
@@ -189,10 +190,13 @@
kParamIndexPictureTypeMask,
kParamIndexPictureType,
+ // deprecated
kParamIndexHdr10PlusMetadata,
kParamIndexPictureQuantization,
+ kParamIndexHdrDynamicMetadata,
+
/* ------------------------------------ video components ------------------------------------ */
kParamIndexFrameRate = C2_PARAM_INDEX_VIDEO_PARAM_START,
@@ -270,6 +274,9 @@
// encoding quality requirements
kParamIndexEncodingQualityLevel, // encoders, enum
+
+ // encoding statistics, average block qp of a frame
+ kParamIndexAverageBlockQuantization, // int32
};
}
@@ -680,6 +687,9 @@
LEVEL_DV_MAIN_UHD_30, ///< Dolby Vision main tier uhd30
LEVEL_DV_MAIN_UHD_48, ///< Dolby Vision main tier uhd48
LEVEL_DV_MAIN_UHD_60, ///< Dolby Vision main tier uhd60
+ LEVEL_DV_MAIN_UHD_120, ///< Dolby Vision main tier uhd120
+ LEVEL_DV_MAIN_8K_30, ///< Dolby Vision main tier 8k30
+ LEVEL_DV_MAIN_8K_60, ///< Dolby Vision main tier 8k60
LEVEL_DV_HIGH_HD_24 = _C2_PL_DV_BASE + 0x100, ///< Dolby Vision high tier hd24
LEVEL_DV_HIGH_HD_30, ///< Dolby Vision high tier hd30
@@ -690,6 +700,9 @@
LEVEL_DV_HIGH_UHD_30, ///< Dolby Vision high tier uhd30
LEVEL_DV_HIGH_UHD_48, ///< Dolby Vision high tier uhd48
LEVEL_DV_HIGH_UHD_60, ///< Dolby Vision high tier uhd60
+ LEVEL_DV_HIGH_UHD_120, ///< Dolby Vision high tier uhd120
+ LEVEL_DV_HIGH_8K_30, ///< Dolby Vision high tier 8k30
+ LEVEL_DV_HIGH_8K_60, ///< Dolby Vision high tier 8k60
// AV1 levels
LEVEL_AV1_2 = _C2_PL_AV1_BASE , ///< AV1 Level 2
@@ -1602,16 +1615,54 @@
C2FIELD(maxFall, "max-fall")
};
typedef C2StreamParam<C2Info, C2HdrStaticMetadataStruct, kParamIndexHdrStaticMetadata>
- C2StreamHdrStaticInfo;
+ C2StreamHdrStaticMetadataInfo;
+typedef C2StreamParam<C2Info, C2HdrStaticMetadataStruct, kParamIndexHdrStaticMetadata>
+ C2StreamHdrStaticInfo; // deprecated
constexpr char C2_PARAMKEY_HDR_STATIC_INFO[] = "raw.hdr-static-info";
/**
* HDR10+ Metadata Info.
+ *
+ * Deprecated. Use C2StreamHdrDynamicMetadataInfo with
+ * HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40
*/
typedef C2StreamParam<C2Info, C2BlobValue, kParamIndexHdr10PlusMetadata>
- C2StreamHdr10PlusInfo;
-constexpr char C2_PARAMKEY_INPUT_HDR10_PLUS_INFO[] = "input.hdr10-plus-info";
-constexpr char C2_PARAMKEY_OUTPUT_HDR10_PLUS_INFO[] = "output.hdr10-plus-info";
+ C2StreamHdr10PlusInfo; // deprecated
+constexpr char C2_PARAMKEY_INPUT_HDR10_PLUS_INFO[] = "input.hdr10-plus-info"; // deprecated
+constexpr char C2_PARAMKEY_OUTPUT_HDR10_PLUS_INFO[] = "output.hdr10-plus-info"; // deprecated
+
+/**
+ * HDR dynamic metadata types
+ */
+C2ENUM(C2Config::hdr_dynamic_metadata_type_t, uint32_t,
+ HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_10, ///< SMPTE ST 2094-10
+ HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40, ///< SMPTE ST 2094-40
+)
+
+struct C2HdrDynamicMetadataStruct {
+ inline C2HdrDynamicMetadataStruct() { memset(this, 0, sizeof(*this)); }
+
+ inline C2HdrDynamicMetadataStruct(
+ size_t flexCount, C2Config::hdr_dynamic_metadata_type_t type)
+ : type_(type) {
+ memset(data, 0, flexCount);
+ }
+
+ C2Config::hdr_dynamic_metadata_type_t type_;
+ uint8_t data[];
+
+ DEFINE_AND_DESCRIBE_FLEX_C2STRUCT(HdrDynamicMetadata, data)
+ C2FIELD(type_, "type")
+ C2FIELD(data, "data")
+};
+
+/**
+ * Dynamic HDR Metadata Info.
+ */
+typedef C2StreamParam<C2Info, C2HdrDynamicMetadataStruct, kParamIndexHdrDynamicMetadata>
+ C2StreamHdrDynamicMetadataInfo;
+constexpr char C2_PARAMKEY_INPUT_HDR_DYNAMIC_INFO[] = "input.hdr-dynamic-info";
+constexpr char C2_PARAMKEY_OUTPUT_HDR_DYNAMIC_INFO[] = "output.hdr-dynamic-info";
/* ------------------------------------ block-based coding ----------------------------------- */
@@ -2411,6 +2462,17 @@
S_HANDHELD = 1 // corresponds to VMAF=70
);
+/**
+ * Video Encoding Statistics Export
+ */
+
+/**
+ * Average block QP exported from video encoder.
+ */
+typedef C2StreamParam<C2Info, C2SimpleValueStruct<int32_t>, kParamIndexAverageBlockQuantization>
+ C2AndroidStreamAverageBlockQuantizationInfo;
+constexpr char C2_PARAMKEY_AVERAGE_QP[] = "coded.average-qp";
+
/// @}
#endif // C2CONFIG_H_
diff --git a/media/codec2/hidl/plugin/FilterWrapper.cpp b/media/codec2/hidl/plugin/FilterWrapper.cpp
index b6024ff..d5124fd 100644
--- a/media/codec2/hidl/plugin/FilterWrapper.cpp
+++ b/media/codec2/hidl/plugin/FilterWrapper.cpp
@@ -49,6 +49,11 @@
std::weak_ptr<FilterWrapper> filterWrapper)
: mIntf(intf), mFilterWrapper(filterWrapper) {
takeFilters(std::move(filters));
+ for (size_t i = 0; i < mFilters.size(); ++i) {
+ mControlParamTypes.insert(
+ mFilters[i].desc.controlParams.begin(),
+ mFilters[i].desc.controlParams.end());
+ }
}
~WrappedDecoderInterface() override = default;
@@ -187,7 +192,12 @@
}
std::vector<C2Param *> stackParamsForIntf;
- std::copy_n(stackParamsList.begin(), stackParamsList.size(), stackParamsForIntf.begin());
+ for (C2Param *param : stackParamsList) {
+ if (mControlParamTypes.count(param->type()) != 0) {
+ continue;
+ }
+ stackParamsForIntf.push_back(param);
+ }
// Gather heap params that did not get queried from the filter interfaces above.
// These need to be queried from the decoder interface.
@@ -197,6 +207,9 @@
if (mTypeToIndexForQuery.find(type) != mTypeToIndexForQuery.end()) {
continue;
}
+ if (mControlParamTypes.count(type) != 0) {
+ continue;
+ }
heapParamIndicesForIntf.push_back(heapParamIndices[j]);
}
@@ -251,11 +264,14 @@
std::vector<C2Param *> paramsForFilter;
for (C2Param* param : params) {
auto it = mTypeToIndexForConfig.find(param->type().type());
- if (it != mTypeToIndexForConfig.end() && it->second != i) {
+ if (it == mTypeToIndexForConfig.end() || it->second != i) {
continue;
}
paramsForFilter.push_back(param);
}
+ if (paramsForFilter.empty()) {
+ continue;
+ }
c2_status_t err = filter->config_vb(paramsForFilter, mayBlock, &filterFailures);
if (err != C2_OK) {
LOG(err == C2_BAD_INDEX ? VERBOSE : WARNING)
@@ -356,6 +372,7 @@
std::weak_ptr<FilterWrapper> mFilterWrapper;
std::map<uint32_t, size_t> mTypeToIndexForQuery;
std::map<uint32_t, size_t> mTypeToIndexForConfig;
+ std::set<C2Param::Type> mControlParamTypes;
c2_status_t transferParams_l(
const std::shared_ptr<C2ComponentInterface> &curr,
@@ -598,6 +615,8 @@
}
}
mRunningFilters.clear();
+ std::vector<FilterWrapper::Component> filters(mFilters);
+ mIntf->takeFilters(std::move(filters));
return result;
}
diff --git a/media/codec2/sfplugin/Android.bp b/media/codec2/sfplugin/Android.bp
index 2bc748f..feeddb5 100644
--- a/media/codec2/sfplugin/Android.bp
+++ b/media/codec2/sfplugin/Android.bp
@@ -42,12 +42,14 @@
"android.hardware.drm@1.0",
"android.hardware.media.c2@1.0",
"android.hardware.media.omx@1.0",
+ "android.hardware.graphics.mapper@4.0",
"libbase",
"libbinder",
"libcodec2",
"libcodec2_client",
"libcodec2_vndk",
"libcutils",
+ "libgralloctypes",
"libgui",
"libhidlallocatorutils",
"libhidlbase",
diff --git a/media/codec2/sfplugin/C2OMXNode.cpp b/media/codec2/sfplugin/C2OMXNode.cpp
index c049187..ed7d69c 100644
--- a/media/codec2/sfplugin/C2OMXNode.cpp
+++ b/media/codec2/sfplugin/C2OMXNode.cpp
@@ -42,6 +42,7 @@
#include "utils/Codec2Mapper.h"
#include "C2OMXNode.h"
+#include "Codec2Buffer.h"
namespace android {
@@ -466,6 +467,18 @@
new Buffer2D(block->share(
C2Rect(block->width(), block->height()), ::C2Fence())));
work->input.buffers.push_back(c2Buffer);
+ std::shared_ptr<C2StreamHdrStaticInfo::input> staticInfo;
+ std::shared_ptr<C2StreamHdrDynamicMetadataInfo::input> dynamicInfo;
+ GetHdrMetadataFromGralloc4Handle(
+ block->handle(),
+ &staticInfo,
+ &dynamicInfo);
+ if (staticInfo && *staticInfo) {
+ c2Buffer->setInfo(staticInfo);
+ }
+ if (dynamicInfo && *dynamicInfo) {
+ c2Buffer->setInfo(dynamicInfo);
+ }
}
work->worklets.clear();
work->worklets.emplace_back(new C2Worklet);
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 5389339..1f8b33d 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1443,6 +1443,27 @@
config->mOutputFormat->setInt32("android._tunneled", 1);
}
+ // Convert an encoding statistics level to corresponding encoding statistics
+ // kinds
+ int32_t encodingStatisticsLevel = VIDEO_ENCODING_STATISTICS_LEVEL_NONE;
+ if ((config->mDomain & Config::IS_ENCODER)
+ && (config->mDomain & Config::IS_VIDEO)
+ && msg->findInt32(KEY_VIDEO_ENCODING_STATISTICS_LEVEL, &encodingStatisticsLevel)) {
+ // Higher level include all the enc stats belong to lower level.
+ switch (encodingStatisticsLevel) {
+ // case VIDEO_ENCODING_STATISTICS_LEVEL_2: // reserved for the future level 2
+ // with more enc stat kinds
+ // Future extended encoding statistics for the level 2 should be added here
+ case VIDEO_ENCODING_STATISTICS_LEVEL_1:
+ config->subscribeToConfigUpdate(comp,
+ {kParamIndexAverageBlockQuantization, kParamIndexPictureType});
+ break;
+ case VIDEO_ENCODING_STATISTICS_LEVEL_NONE:
+ break;
+ }
+ }
+ ALOGD("encoding statistics level = %d", encodingStatisticsLevel);
+
ALOGD("setup formats input: %s",
config->mInputFormat->debugString().c_str());
ALOGD("setup formats output: %s",
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 0de0b77..99aa593 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -840,6 +840,35 @@
hdr10PlusInfo.reset();
}
+ // HDR dynamic info
+ std::shared_ptr<const C2StreamHdrDynamicMetadataInfo::output> hdrDynamicInfo =
+ std::static_pointer_cast<const C2StreamHdrDynamicMetadataInfo::output>(
+ c2Buffer->getInfo(C2StreamHdrDynamicMetadataInfo::output::PARAM_TYPE));
+ // TODO: make this sticky & enable unset
+ if (hdrDynamicInfo && hdrDynamicInfo->flexCount() == 0) {
+ hdrDynamicInfo.reset();
+ }
+
+ if (hdr10PlusInfo) {
+ // C2StreamHdr10PlusInfo is deprecated; components should use
+ // C2StreamHdrDynamicMetadataInfo
+ // TODO: #metric
+ if (hdrDynamicInfo) {
+ // It is unexpected that C2StreamHdr10PlusInfo and
+ // C2StreamHdrDynamicMetadataInfo is both present.
+ // C2StreamHdrDynamicMetadataInfo takes priority.
+ // TODO: #metric
+ } else {
+ std::shared_ptr<C2StreamHdrDynamicMetadataInfo::output> info =
+ C2StreamHdrDynamicMetadataInfo::output::AllocShared(
+ hdr10PlusInfo->flexCount(),
+ 0u,
+ C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40);
+ memcpy(info->m.data, hdr10PlusInfo->m.value, hdr10PlusInfo->flexCount());
+ hdrDynamicInfo = info;
+ }
+ }
+
std::vector<C2ConstGraphicBlock> blocks = c2Buffer->data().graphicBlocks();
if (blocks.size() != 1u) {
ALOGD("[%s] expected 1 graphic block, but got %zu", mName, blocks.size());
@@ -859,7 +888,7 @@
videoScalingMode,
transform,
Fence::NO_FENCE, 0);
- if (hdrStaticInfo || hdr10PlusInfo) {
+ if (hdrStaticInfo || hdrDynamicInfo) {
HdrMetadata hdr;
if (hdrStaticInfo) {
// If mastering max and min luminance fields are 0, do not use them.
@@ -896,13 +925,16 @@
hdr.cta8613 = cta861_meta;
}
}
- if (hdr10PlusInfo) {
+ if (hdrDynamicInfo
+ && hdrDynamicInfo->m.type_ == C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40) {
hdr.validTypes |= HdrMetadata::HDR10PLUS;
hdr.hdr10plus.assign(
- hdr10PlusInfo->m.value,
- hdr10PlusInfo->m.value + hdr10PlusInfo->flexCount());
+ hdrDynamicInfo->m.data,
+ hdrDynamicInfo->m.data + hdrDynamicInfo->flexCount());
}
qbi.setHdrMetadata(hdr);
+
+ SetHdrMetadataToGralloc4Handle(hdrStaticInfo, hdrDynamicInfo, block.handle());
}
// we don't have dirty regions
qbi.setSurfaceDamage(Region::INVALID_REGION);
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index 03418d9..0899e99 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -953,6 +953,12 @@
return value == 0 ? C2_FALSE : C2_TRUE;
}));
+ add(ConfigMapper(KEY_VIDEO_QP_AVERAGE, C2_PARAMKEY_AVERAGE_QP, "value")
+ .limitTo(D::ENCODER & D::VIDEO & D::READ));
+
+ add(ConfigMapper(KEY_PICTURE_TYPE, C2_PARAMKEY_PICTURE_TYPE, "value")
+ .limitTo(D::ENCODER & D::VIDEO & D::READ));
+
/* still to do
constexpr char KEY_PUSH_BLANK_BUFFERS_ON_STOP[] = "push-blank-buffers-on-shutdown";
diff --git a/media/codec2/sfplugin/CCodecConfig.h b/media/codec2/sfplugin/CCodecConfig.h
index 417b773..88e6239 100644
--- a/media/codec2/sfplugin/CCodecConfig.h
+++ b/media/codec2/sfplugin/CCodecConfig.h
@@ -363,11 +363,6 @@
const std::vector<std::string> &names,
c2_blocking_t blocking = C2_DONT_BLOCK);
-private:
-
- /// initializes the standard MediaCodec to Codec 2.0 params mapping
- void initializeStandardParams();
-
/// Adds indices to the subscribed indices, and updated subscription to component
/// \param blocking blocking mode to use with the component
status_t subscribeToConfigUpdate(
@@ -375,6 +370,11 @@
const std::vector<C2Param::Index> &indices,
c2_blocking_t blocking = C2_DONT_BLOCK);
+private:
+
+ /// initializes the standard MediaCodec to Codec 2.0 params mapping
+ void initializeStandardParams();
+
/// Gets SDK format from codec 2.0 reflected configuration
/// \param domain input/output bitmask
sp<AMessage> getFormatForDomain(
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 4070478..7f9de21 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -18,9 +18,14 @@
#define LOG_TAG "Codec2Buffer"
#include <utils/Log.h>
+#include <aidl/android/hardware/graphics/common/Cta861_3.h>
+#include <aidl/android/hardware/graphics/common/Smpte2086.h>
#include <android-base/properties.h>
#include <android/hardware/cas/native/1.0/types.h>
#include <android/hardware/drm/1.0/types.h>
+#include <android/hardware/graphics/common/1.2/types.h>
+#include <android/hardware/graphics/mapper/4.0/IMapper.h>
+#include <gralloctypes/Gralloc4.h>
#include <hidlmemory/FrameworkUtils.h>
#include <media/hardware/HardwareAPI.h>
#include <media/stagefright/CodecBase.h>
@@ -941,4 +946,218 @@
return const_cast<native_handle_t *>(mBlock->handle());
}
+using ::aidl::android::hardware::graphics::common::Cta861_3;
+using ::aidl::android::hardware::graphics::common::Smpte2086;
+
+using ::android::gralloc4::MetadataType_Cta861_3;
+using ::android::gralloc4::MetadataType_Smpte2086;
+using ::android::gralloc4::MetadataType_Smpte2094_40;
+
+using ::android::hardware::Return;
+using ::android::hardware::hidl_vec;
+
+using Error4 = ::android::hardware::graphics::mapper::V4_0::Error;
+using IMapper4 = ::android::hardware::graphics::mapper::V4_0::IMapper;
+
+namespace {
+
+sp<IMapper4> GetMapper4() {
+ static sp<IMapper4> sMapper = IMapper4::getService();
+ return sMapper;
+}
+
+class NativeHandleDeleter {
+public:
+ explicit NativeHandleDeleter(native_handle_t *handle) : mHandle(handle) {}
+ ~NativeHandleDeleter() {
+ if (mHandle) {
+ native_handle_delete(mHandle);
+ }
+ }
+private:
+ native_handle_t *mHandle;
+};
+
+} // namspace
+
+c2_status_t GetHdrMetadataFromGralloc4Handle(
+ const C2Handle *const handle,
+ std::shared_ptr<C2StreamHdrStaticMetadataInfo::input> *staticInfo,
+ std::shared_ptr<C2StreamHdrDynamicMetadataInfo::input> *dynamicInfo) {
+ c2_status_t err = C2_OK;
+ native_handle_t *nativeHandle = UnwrapNativeCodec2GrallocHandle(handle);
+ if (nativeHandle == nullptr) {
+ // Nothing to do
+ return err;
+ }
+ // TRICKY: UnwrapNativeCodec2GrallocHandle creates a new handle but
+ // does not clone the fds. Thus we need to delete the handle
+ // without closing it when going out of scope.
+ // NativeHandle cannot solve this problem, as it would close and
+ // delete the handle, while we need delete only.
+ NativeHandleDeleter nhd(nativeHandle);
+ sp<IMapper4> mapper = GetMapper4();
+ if (!mapper) {
+ // Gralloc4 not supported; nothing to do
+ return err;
+ }
+ Error4 mapperErr = Error4::NONE;
+ if (staticInfo) {
+ staticInfo->reset(new C2StreamHdrStaticMetadataInfo::input(0u));
+ memset(&(*staticInfo)->mastering, 0, sizeof((*staticInfo)->mastering));
+ (*staticInfo)->maxCll = 0;
+ (*staticInfo)->maxFall = 0;
+ IMapper4::get_cb cb = [&mapperErr, staticInfo](Error4 err, const hidl_vec<uint8_t> &vec) {
+ mapperErr = err;
+ if (err != Error4::NONE) {
+ return;
+ }
+
+ std::optional<Smpte2086> smpte2086;
+ gralloc4::decodeSmpte2086(vec, &smpte2086);
+ if (smpte2086) {
+ (*staticInfo)->mastering.red.x = smpte2086->primaryRed.x;
+ (*staticInfo)->mastering.red.y = smpte2086->primaryRed.y;
+ (*staticInfo)->mastering.green.x = smpte2086->primaryGreen.x;
+ (*staticInfo)->mastering.green.y = smpte2086->primaryGreen.y;
+ (*staticInfo)->mastering.blue.x = smpte2086->primaryBlue.x;
+ (*staticInfo)->mastering.blue.y = smpte2086->primaryBlue.y;
+ (*staticInfo)->mastering.white.x = smpte2086->whitePoint.x;
+ (*staticInfo)->mastering.white.y = smpte2086->whitePoint.y;
+
+ (*staticInfo)->mastering.maxLuminance = smpte2086->maxLuminance;
+ (*staticInfo)->mastering.minLuminance = smpte2086->minLuminance;
+ } else {
+ mapperErr = Error4::BAD_VALUE;
+ }
+ };
+ Return<void> ret = mapper->get(nativeHandle, MetadataType_Smpte2086, cb);
+ if (!ret.isOk()) {
+ err = C2_REFUSED;
+ } else if (mapperErr != Error4::NONE) {
+ err = C2_CORRUPTED;
+ }
+ cb = [&mapperErr, staticInfo](Error4 err, const hidl_vec<uint8_t> &vec) {
+ mapperErr = err;
+ if (err != Error4::NONE) {
+ return;
+ }
+
+ std::optional<Cta861_3> cta861_3;
+ gralloc4::decodeCta861_3(vec, &cta861_3);
+ if (cta861_3) {
+ (*staticInfo)->maxCll = cta861_3->maxContentLightLevel;
+ (*staticInfo)->maxFall = cta861_3->maxFrameAverageLightLevel;
+ } else {
+ mapperErr = Error4::BAD_VALUE;
+ }
+ };
+ ret = mapper->get(nativeHandle, MetadataType_Cta861_3, cb);
+ if (!ret.isOk()) {
+ err = C2_REFUSED;
+ } else if (mapperErr != Error4::NONE) {
+ err = C2_CORRUPTED;
+ }
+ }
+ if (dynamicInfo) {
+ dynamicInfo->reset();
+ IMapper4::get_cb cb = [&mapperErr, dynamicInfo](Error4 err, const hidl_vec<uint8_t> &vec) {
+ mapperErr = err;
+ if (err != Error4::NONE) {
+ return;
+ }
+ if (!dynamicInfo) {
+ return;
+ }
+ *dynamicInfo = C2StreamHdrDynamicMetadataInfo::input::AllocShared(
+ vec.size(), 0u, C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40);
+ memcpy((*dynamicInfo)->m.data, vec.data(), vec.size());
+ };
+ Return<void> ret = mapper->get(nativeHandle, MetadataType_Smpte2094_40, cb);
+ if (!ret.isOk() || mapperErr != Error4::NONE) {
+ dynamicInfo->reset();
+ }
+ }
+
+ return err;
+}
+
+c2_status_t SetHdrMetadataToGralloc4Handle(
+ const std::shared_ptr<const C2StreamHdrStaticMetadataInfo::output> &staticInfo,
+ const std::shared_ptr<const C2StreamHdrDynamicMetadataInfo::output> &dynamicInfo,
+ const C2Handle *const handle) {
+ c2_status_t err = C2_OK;
+ native_handle_t *nativeHandle = UnwrapNativeCodec2GrallocHandle(handle);
+ if (nativeHandle == nullptr) {
+ // Nothing to do
+ return err;
+ }
+ // TRICKY: UnwrapNativeCodec2GrallocHandle creates a new handle but
+ // does not clone the fds. Thus we need to delete the handle
+ // without closing it when going out of scope.
+ NativeHandleDeleter nhd(nativeHandle);
+ sp<IMapper4> mapper = GetMapper4();
+ if (!mapper) {
+ // Gralloc4 not supported; nothing to do
+ return err;
+ }
+ if (staticInfo && *staticInfo) {
+ std::optional<Smpte2086> smpte2086 = Smpte2086{
+ {staticInfo->mastering.red.x, staticInfo->mastering.red.y},
+ {staticInfo->mastering.green.x, staticInfo->mastering.green.y},
+ {staticInfo->mastering.blue.x, staticInfo->mastering.blue.y},
+ {staticInfo->mastering.white.x, staticInfo->mastering.white.y},
+ staticInfo->mastering.maxLuminance,
+ staticInfo->mastering.minLuminance,
+ };
+ hidl_vec<uint8_t> vec;
+ if (gralloc4::encodeSmpte2086(smpte2086, &vec) == OK) {
+ Return<Error4> ret = mapper->set(nativeHandle, MetadataType_Smpte2086, vec);
+ if (!ret.isOk()) {
+ err = C2_REFUSED;
+ } else if (ret != Error4::NONE) {
+ err = C2_CORRUPTED;
+ }
+ }
+ std::optional<Cta861_3> cta861_3 = Cta861_3{
+ staticInfo->maxCll,
+ staticInfo->maxFall,
+ };
+ if (gralloc4::encodeCta861_3(cta861_3, &vec) == OK) {
+ Return<Error4> ret = mapper->set(nativeHandle, MetadataType_Cta861_3, vec);
+ if (!ret.isOk()) {
+ err = C2_REFUSED;
+ } else if (ret != Error4::NONE) {
+ err = C2_CORRUPTED;
+ }
+ }
+ }
+ if (dynamicInfo && *dynamicInfo) {
+ hidl_vec<uint8_t> vec;
+ vec.resize(dynamicInfo->flexCount());
+ memcpy(vec.data(), dynamicInfo->m.data, dynamicInfo->flexCount());
+ std::optional<IMapper4::MetadataType> metadataType;
+ switch (dynamicInfo->m.type_) {
+ case C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_10:
+ // TODO
+ break;
+ case C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40:
+ metadataType = MetadataType_Smpte2094_40;
+ break;
+ }
+ if (metadataType) {
+ Return<Error4> ret = mapper->set(nativeHandle, *metadataType, vec);
+ if (!ret.isOk()) {
+ err = C2_REFUSED;
+ } else if (ret != Error4::NONE) {
+ err = C2_CORRUPTED;
+ }
+ } else {
+ err = C2_BAD_VALUE;
+ }
+ }
+
+ return err;
+}
+
} // namespace android
diff --git a/media/codec2/sfplugin/Codec2Buffer.h b/media/codec2/sfplugin/Codec2Buffer.h
index dc788cd..b02b042 100644
--- a/media/codec2/sfplugin/Codec2Buffer.h
+++ b/media/codec2/sfplugin/Codec2Buffer.h
@@ -19,6 +19,7 @@
#define CODEC2_BUFFER_H_
#include <C2Buffer.h>
+#include <C2Config.h>
#include <binder/IMemory.h>
#include <media/hardware/VideoAPI.h>
@@ -391,6 +392,36 @@
int32_t mHeapSeqNum;
};
+/**
+ * Get HDR metadata from Gralloc4 handle.
+ *
+ * \param[in] handle handle of the allocation
+ * \param[out] staticInfo HDR static info to be filled. Ignored if null;
+ * if |handle| is invalid or does not contain the metadata,
+ * the shared_ptr is reset.
+ * \param[out] dynamicInfo HDR dynamic info to be filled. Ignored if null;
+ * if |handle| is invalid or does not contain the metadata,
+ * the shared_ptr is reset.
+ * \return C2_OK if successful
+ */
+c2_status_t GetHdrMetadataFromGralloc4Handle(
+ const C2Handle *const handle,
+ std::shared_ptr<C2StreamHdrStaticMetadataInfo::input> *staticInfo,
+ std::shared_ptr<C2StreamHdrDynamicMetadataInfo::input> *dynamicInfo);
+
+/**
+ * Set HDR metadata to Gralloc4 handle.
+ *
+ * \param[in] staticInfo HDR static info to set. Ignored if null or invalid.
+ * \param[in] dynamicInfo HDR dynamic info to set. Ignored if null or invalid.
+ * \param[out] handle handle of the allocation.
+ * \return C2_OK if successful
+ */
+c2_status_t SetHdrMetadataToGralloc4Handle(
+ const std::shared_ptr<const C2StreamHdrStaticMetadataInfo::output> &staticInfo,
+ const std::shared_ptr<const C2StreamHdrDynamicMetadataInfo::output> &dynamicInfo,
+ const C2Handle *const handle);
+
} // namespace android
#endif // CODEC2_BUFFER_H_
diff --git a/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp b/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
index 2213001..b761c35 100644
--- a/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
+++ b/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
@@ -88,7 +88,7 @@
uint32_t planeW = img->mWidth / plane.colSampling;
uint32_t planeH = img->mHeight / plane.rowSampling;
- bool canCopyByRow = (plane.colInc == 1) && (img->mPlane[i].mColInc == 1);
+ bool canCopyByRow = (plane.colInc == bpp) && (img->mPlane[i].mColInc == bpp);
bool canCopyByPlane = canCopyByRow && (plane.rowInc == img->mPlane[i].mRowInc);
if (canCopyByPlane) {
MemCopier<ToMediaImage, 0>::copy(imgRow, viewRow, plane.rowInc * planeH);
diff --git a/media/codec2/sfplugin/utils/Codec2Mapper.cpp b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
index c075199..93f29ca 100644
--- a/media/codec2/sfplugin/utils/Codec2Mapper.cpp
+++ b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
@@ -170,6 +170,9 @@
{ C2Config::LEVEL_DV_MAIN_UHD_30, DolbyVisionLevelUhd30 },
{ C2Config::LEVEL_DV_MAIN_UHD_48, DolbyVisionLevelUhd48 },
{ C2Config::LEVEL_DV_MAIN_UHD_60, DolbyVisionLevelUhd60 },
+ { C2Config::LEVEL_DV_MAIN_UHD_120, DolbyVisionLevelUhd120 },
+ { C2Config::LEVEL_DV_MAIN_8K_30, DolbyVisionLevel8k30 },
+ { C2Config::LEVEL_DV_MAIN_8K_60, DolbyVisionLevel8k60 },
// high tiers are not yet supported on android, for now map them to main tier
{ C2Config::LEVEL_DV_HIGH_HD_24, DolbyVisionLevelHd24 },
@@ -181,6 +184,9 @@
{ C2Config::LEVEL_DV_HIGH_UHD_30, DolbyVisionLevelUhd30 },
{ C2Config::LEVEL_DV_HIGH_UHD_48, DolbyVisionLevelUhd48 },
{ C2Config::LEVEL_DV_HIGH_UHD_60, DolbyVisionLevelUhd60 },
+ { C2Config::LEVEL_DV_HIGH_UHD_120, DolbyVisionLevelUhd120 },
+ { C2Config::LEVEL_DV_HIGH_8K_30, DolbyVisionLevel8k30 },
+ { C2Config::LEVEL_DV_HIGH_8K_60, DolbyVisionLevel8k60 },
};
ALookup<C2Config::profile_t, int32_t> sDolbyVisionProfiles = {
diff --git a/media/codec2/vndk/C2Store.cpp b/media/codec2/vndk/C2Store.cpp
index 1660c38..dfdd84d 100644
--- a/media/codec2/vndk/C2Store.cpp
+++ b/media/codec2/vndk/C2Store.cpp
@@ -301,13 +301,21 @@
std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
_mComponentStore = store;
}
- std::shared_ptr<C2AllocatorIon> allocator;
+ std::shared_ptr<C2AllocatorIon> ionAllocator;
{
std::lock_guard<std::mutex> lock(gIonAllocatorMutex);
- allocator = gIonAllocator.lock();
+ ionAllocator = gIonAllocator.lock();
}
- if (allocator) {
- UseComponentStoreForIonAllocator(allocator, store);
+ if (ionAllocator) {
+ UseComponentStoreForIonAllocator(ionAllocator, store);
+ }
+ std::shared_ptr<C2DmaBufAllocator> dmaAllocator;
+ {
+ std::lock_guard<std::mutex> lock(gDmaBufAllocatorMutex);
+ dmaAllocator = gDmaBufAllocator.lock();
+ }
+ if (dmaAllocator) {
+ UseComponentStoreForDmaBufAllocator(dmaAllocator, store);
}
}
diff --git a/media/extractors/flac/Android.bp b/media/extractors/flac/Android.bp
index 9a2a76b..f6ce969 100644
--- a/media/extractors/flac/Android.bp
+++ b/media/extractors/flac/Android.bp
@@ -19,7 +19,7 @@
cc_library {
name: "libflacextractor",
- defaults: ["extractor-defaults", "libbinder_ndk_host_user"],
+ defaults: ["extractor-defaults"],
srcs: ["FLACExtractor.cpp"],
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 8836c47..fb935b6 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -1127,10 +1127,10 @@
void *data;
size_t size;
- if (AMediaFormat_getBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_2,
+ if (AMediaFormat_getBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_0,
&data, &size)
- && size >= 5) {
- const uint8_t *ptr = (const uint8_t *)data;
+ && size >= 24) {
+ const uint8_t *ptr = (const uint8_t *)data + (size - 24);
const uint8_t profile = ptr[2] >> 1;
const uint8_t bl_compatibility_id = (ptr[4]) >> 4;
bool create_two_tracks = false;
@@ -1147,13 +1147,15 @@
track_b->timescale = mLastTrack->timescale;
track_b->sampleTable = mLastTrack->sampleTable;
- track_b->includes_expensive_metadata = mLastTrack->includes_expensive_metadata;
+ track_b->includes_expensive_metadata =
+ mLastTrack->includes_expensive_metadata;
track_b->skipTrack = mLastTrack->skipTrack;
track_b->elst_needs_processing = mLastTrack->elst_needs_processing;
track_b->elst_media_time = mLastTrack->elst_media_time;
track_b->elst_segment_duration = mLastTrack->elst_segment_duration;
track_b->elst_shift_start_ticks = mLastTrack->elst_shift_start_ticks;
- track_b->elst_initial_empty_edit_ticks = mLastTrack->elst_initial_empty_edit_ticks;
+ track_b->elst_initial_empty_edit_ticks =
+ mLastTrack->elst_initial_empty_edit_ticks;
track_b->subsample_encryption = mLastTrack->subsample_encryption;
track_b->mTx3gBuffer = mLastTrack->mTx3gBuffer;
@@ -1166,11 +1168,11 @@
mLastTrack->next = track_b;
track_b->next = NULL;
- // we want to remove the csd-2 key from the metadata, but
+ // we want to remove the csd-0 key from the metadata, but
// don't have an AMediaFormat_* function to do so. Settle
- // for replacing this csd-2 with an empty csd-2.
+ // for replacing this csd-0 with an empty csd-0.
uint8_t emptybuffer[8] = {};
- AMediaFormat_setBuffer(track_b->meta, AMEDIAFORMAT_KEY_CSD_2,
+ AMediaFormat_setBuffer(track_b->meta, AMEDIAFORMAT_KEY_CSD_0,
emptybuffer, 0);
if (4 == profile || 7 == profile || 8 == profile ) {
@@ -1182,6 +1184,8 @@
} else if (10 == profile) {
AMediaFormat_setString(track_b->meta,
AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_AV1);
+ AMediaFormat_setBuffer(track_b->meta, AMEDIAFORMAT_KEY_CSD_0,
+ data, size - 24);
} // Should never get to else part
mLastTrack = track_b;
@@ -2591,9 +2595,11 @@
*offset += chunk_size;
break;
}
- case FOURCC("dvcC"):
- case FOURCC("dvvC"): {
+ case FOURCC("dvcC"):
+ case FOURCC("dvvC"):
+ case FOURCC("dvwC"):
+ {
if (chunk_data_size != 24) {
return ERROR_MALFORMED;
}
@@ -2612,14 +2618,29 @@
if (mLastTrack == NULL)
return ERROR_MALFORMED;
- AMediaFormat_setBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_2,
- buffer.get(), chunk_data_size);
+ void *data = nullptr;
+ size_t size = 0;
+ if (AMediaFormat_getBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_0, &data, &size)) {
+ //if csd-0 is already present, then append dvcc
+ auto csd0_dvcc = heapbuffer<uint8_t>(size + chunk_data_size);
+
+ memcpy(csd0_dvcc.get(), data, size);
+ memcpy(csd0_dvcc.get() + size, buffer.get(), chunk_data_size);
+
+ AMediaFormat_setBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_0,
+ csd0_dvcc.get(), size + chunk_data_size);
+ } else {
+ //if not set csd-0 directly
+ AMediaFormat_setBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_0,
+ buffer.get(), chunk_data_size);
+ }
AMediaFormat_setString(mLastTrack->meta, AMEDIAFORMAT_KEY_MIME,
MEDIA_MIMETYPE_VIDEO_DOLBY_VISION);
*offset += chunk_size;
break;
}
+
case FOURCC("d263"):
{
*offset += chunk_size;
@@ -4458,7 +4479,6 @@
if (!AMediaFormat_getString(track->meta, AMEDIAFORMAT_KEY_MIME, &mime)) {
return NULL;
}
-
sp<ItemTable> itemTable;
if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
void *data;
@@ -4491,14 +4511,14 @@
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION)) {
void *data;
size_t size;
- if (!AMediaFormat_getBuffer(track->meta, AMEDIAFORMAT_KEY_CSD_2, &data, &size)) {
+ if (!AMediaFormat_getBuffer(track->meta, AMEDIAFORMAT_KEY_CSD_0, &data, &size)
+ || size < 24) {
return NULL;
}
- const uint8_t *ptr = (const uint8_t *)data;
-
+ const uint8_t *ptr = (const uint8_t *)data + (size - 24);
// dv_major.dv_minor Should be 1.0 or 2.1
- if (size != 24 || ((ptr[0] != 1 || ptr[1] != 0) && (ptr[0] != 2 || ptr[1] != 1))) {
+ if ((ptr[0] != 1 || ptr[1] != 0) && (ptr[0] != 2 || ptr[1] != 1)) {
return NULL;
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AV1)
@@ -4576,7 +4596,7 @@
return ERROR_MALFORMED;
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION)) {
- if (!AMediaFormat_getBuffer(track->meta, AMEDIAFORMAT_KEY_CSD_2, &data, &size)) {
+ if (!AMediaFormat_getBuffer(track->meta, AMEDIAFORMAT_KEY_CSD_0, &data, &size)) {
return ERROR_MALFORMED;
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AV1)) {
@@ -5152,11 +5172,11 @@
ALOGV("%s DolbyVision stream detected", __FUNCTION__);
void *data;
size_t size;
- CHECK(AMediaFormat_getBuffer(format, AMEDIAFORMAT_KEY_CSD_2, &data, &size));
+ CHECK(AMediaFormat_getBuffer(format, AMEDIAFORMAT_KEY_CSD_0, &data, &size));
- const uint8_t *ptr = (const uint8_t *)data;
+ const uint8_t *ptr = (const uint8_t *)data + (size - 24);
- CHECK(size == 24);
+ CHECK(size >= 24);
// dv_major.dv_minor Should be 1.0 or 2.1
CHECK(!((ptr[0] != 1 || ptr[1] != 0) && (ptr[0] != 2 || ptr[1] != 1)));
diff --git a/media/extractors/wav/Android.bp b/media/extractors/wav/Android.bp
index cc5e1c7..76546b8 100644
--- a/media/extractors/wav/Android.bp
+++ b/media/extractors/wav/Android.bp
@@ -18,7 +18,7 @@
cc_library {
name: "libwavextractor",
- defaults: ["extractor-defaults", "libbinder_ndk_host_user"],
+ defaults: ["extractor-defaults"],
srcs: ["WAVExtractor.cpp"],
diff --git a/media/janitors/reliability_mainline_OWNERS b/media/janitors/reliability_mainline_OWNERS
index e4c4fc2..cced19c 100644
--- a/media/janitors/reliability_mainline_OWNERS
+++ b/media/janitors/reliability_mainline_OWNERS
@@ -1,5 +1,5 @@
# Bug component: 1051309
-# go/android-media-relaibility
+# go/android-media-reliability
essick@google.com
nchalko@google.com
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index b0f155a..8cc67c4 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -39,7 +39,7 @@
},
}
-cc_library_shared {
+cc_library {
name: "libaudiopolicy",
srcs: [
"AudioAttributes.cpp",
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 7c7fcac..1c7cfae 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -156,7 +156,7 @@
bool isHeic() const { return mIsHeic; }
bool isAudio() const { return mIsAudio; }
bool isMPEG4() const { return mIsMPEG4; }
- bool usePrefix() const { return mIsAvc || mIsHevc || mIsHeic; }
+ bool usePrefix() const { return mIsAvc || mIsHevc || mIsHeic || mIsDovi; }
bool isExifData(MediaBufferBase *buffer, uint32_t *tiffHdrOffset) const;
void addChunkOffset(off64_t offset);
void addItemOffsetAndSize(off64_t offset, size_t size, bool isExif);
@@ -164,6 +164,7 @@
TrackId& getTrackId() { return mTrackId; }
status_t dump(int fd, const Vector<String16>& args) const;
static const char *getFourCCForMime(const char *mime);
+ const char *getDoviFourCC() const;
const char *getTrackType() const;
void resetInternal();
int64_t trackMetaDataSize();
@@ -316,6 +317,7 @@
volatile bool mStarted;
bool mIsAvc;
bool mIsHevc;
+ bool mIsDovi;
bool mIsAudio;
bool mIsVideo;
bool mIsHeic;
@@ -370,6 +372,10 @@
uint8_t mProfileCompatible;
uint8_t mLevelIdc;
+ uint8_t mDoviProfile;
+ void *mDoviConfigData;
+ size_t mDoviConfigDataSize;
+
void *mCodecSpecificData;
size_t mCodecSpecificDataSize;
bool mGotAllCodecSpecificData;
@@ -422,6 +428,8 @@
status_t parseHEVCCodecSpecificData(
const uint8_t *data, size_t size, HevcParameterSets ¶mSets);
+ status_t makeDoviCodecSpecificData();
+
// Track authoring progress status
void trackProgressStatus(int64_t timeUs, status_t err = OK);
void initTrackingProgressStatus(MetaData *params);
@@ -459,6 +467,7 @@
void writePaspBox();
void writeAvccBox();
void writeHvccBox();
+ void writeDoviConfigBox();
void writeUrlBox();
void writeDrefBox();
void writeDinfBox();
@@ -617,6 +626,17 @@
return OK;
}
+const char *MPEG4Writer::Track::getDoviFourCC() const {
+ if (mDoviProfile == 5) {
+ return "dvh1";
+ } else if (mDoviProfile == 8) {
+ return "hvc1";
+ } else if (mDoviProfile == 9 || mDoviProfile == 32) {
+ return "avc1";
+ }
+ return (const char*)NULL;
+}
+
// static
const char *MPEG4Writer::Track::getFourCCForMime(const char *mime) {
if (mime == NULL) {
@@ -671,7 +691,9 @@
mIsBackgroundMode |= isBackgroundMode;
}
- if (Track::getFourCCForMime(mime) == NULL) {
+ if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION)) {
+ ALOGV("Add source mime '%s'", mime);
+ } else if (Track::getFourCCForMime(mime) == NULL) {
ALOGE("Unsupported mime '%s'", mime);
return ERROR_UNSUPPORTED;
}
@@ -2150,6 +2172,8 @@
mMinCttsOffsetTimeUs(0),
mMinCttsOffsetTicks(0),
mMaxCttsOffsetTicks(0),
+ mDoviConfigData(NULL),
+ mDoviConfigDataSize(0),
mCodecSpecificData(NULL),
mCodecSpecificDataSize(0),
mGotAllCodecSpecificData(false),
@@ -2176,6 +2200,7 @@
mMeta->findCString(kKeyMIMEType, &mime);
mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
mIsHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
+ mIsDovi = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION);
mIsAudio = !strncasecmp(mime, "audio/", 6);
mIsVideo = !strncasecmp(mime, "video/", 6);
mIsHeic = !strcasecmp(mime, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC);
@@ -2610,7 +2635,12 @@
!strcasecmp(mime, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC)) {
mMeta->findData(kKeyHVCC, &type, &data, &size);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION)) {
- mMeta->findData(kKeyDVCC, &type, &data, &size);
+ makeDoviCodecSpecificData();
+ if (!mMeta->findData(kKeyAVCC, &type, &data, &size) &&
+ !mMeta->findData(kKeyHVCC, &type, &data, &size)) {
+ ALOGE("Failed: No HVCC/AVCC for Dolby Vision ..\n");
+ return;
+ }
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
@@ -2651,6 +2681,11 @@
free(mCodecSpecificData);
mCodecSpecificData = NULL;
}
+
+ if (mDoviConfigData != NULL) {
+ free(mDoviConfigData);
+ mDoviConfigData = NULL;
+ }
}
void MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
@@ -3329,6 +3364,37 @@
return OK;
}
+status_t MPEG4Writer::Track::makeDoviCodecSpecificData() {
+ uint32_t type;
+ const void *data = NULL;
+ size_t size = 0;
+
+ if (mDoviConfigData != NULL) {
+ ALOGE("Already have Dolby Vision codec specific data");
+ return OK;
+ }
+
+ if (!mMeta->findData(kKeyDVCC, &type, &data, &size)
+ && !mMeta->findData(kKeyDVVC, &type, &data, &size)
+ && !mMeta->findData(kKeyDVWC, &type, &data, &size)) {
+ ALOGE("Failed getting Dovi config for Dolby Vision %d", (int)size);
+ return ERROR_MALFORMED;
+ }
+
+ mDoviConfigData = malloc(size);
+ if (mDoviConfigData == NULL) {
+ ALOGE("Failed allocating Dolby Vision config data");
+ return ERROR_MALFORMED;
+ }
+
+ mDoviConfigDataSize = size;
+ memcpy(mDoviConfigData, data, size);
+
+ mDoviProfile = (((char *)data)[2] >> 1) & 0x7f; //getting profile info
+
+ return OK;
+}
+
/*
* Updates the drift time from the audio track so that
* the video track can get the updated drift time information
@@ -3474,6 +3540,23 @@
err = copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(),
buffer->range_length());
}
+ if (mIsDovi) {
+ err = makeDoviCodecSpecificData();
+
+ const void *data = NULL;
+ size_t size = 0;
+
+ uint32_t type = 0;
+ if (mDoviProfile == 9){
+ mMeta->findData(kKeyAVCC, &type, &data, &size);
+ } else if (mDoviProfile < 9) {
+ mMeta->findData(kKeyHVCC, &type, &data, &size);
+ }
+
+ if (data != NULL && copyCodecSpecificData((uint8_t *)data, size) == OK) {
+ mGotAllCodecSpecificData = true;
+ }
+ }
}
buffer->release();
@@ -4173,6 +4256,7 @@
!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) ||
!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime) ||
+ !strcasecmp(MEDIA_MIMETYPE_VIDEO_DOLBY_VISION, mime) ||
!strcasecmp(MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC, mime)) {
if (!mCodecSpecificData ||
mCodecSpecificDataSize <= 0) {
@@ -4297,7 +4381,13 @@
const char *mime;
bool success = mMeta->findCString(kKeyMIMEType, &mime);
CHECK(success);
- const char *fourcc = getFourCCForMime(mime);
+ const char *fourcc;
+ if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION)) {
+ fourcc = getDoviFourCC();
+ } else {
+ fourcc = getFourCCForMime(mime);
+ }
+
if (fourcc == NULL) {
ALOGE("Unknown mime type '%s'.", mime);
TRESPASS();
@@ -4337,6 +4427,13 @@
writeAvccBox();
} else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
writeHvccBox();
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_DOLBY_VISION, mime)) {
+ if (mDoviProfile <= 8) {
+ writeHvccBox();
+ } else if (mDoviProfile == 9 || mDoviProfile == 32) {
+ writeAvccBox();
+ }
+ writeDoviConfigBox();
}
writePaspBox();
@@ -4829,12 +4926,11 @@
mOwner->endBox(); // avcC
}
-
void MPEG4Writer::Track::writeHvccBox() {
CHECK(mCodecSpecificData);
CHECK_GE(mCodecSpecificDataSize, 5u);
- // Patch avcc's lengthSize field to match the number
+ // Patch hvcc's lengthSize field to match the number
// of bytes we use to indicate the size of a nal unit.
uint8_t *ptr = (uint8_t *)mCodecSpecificData;
ptr[21] = (ptr[21] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
@@ -4843,6 +4939,24 @@
mOwner->endBox(); // hvcC
}
+void MPEG4Writer::Track::writeDoviConfigBox() {
+ CHECK(mDoviConfigData);
+ CHECK_EQ(mDoviConfigDataSize, 24u);
+
+ uint8_t *ptr = (uint8_t *)mDoviConfigData;
+ uint8_t profile = (ptr[2] >> 1) & 0x7f;
+
+ if (profile > 10) {
+ mOwner->beginBox("dvwC");
+ } else if (profile > 7) {
+ mOwner->beginBox("dvvC");
+ } else {
+ mOwner->beginBox("dvcC");
+ }
+ mOwner->write(mDoviConfigData, mDoviConfigDataSize);
+ mOwner->endBox(); // dvwC/dvvC/dvcC
+}
+
void MPEG4Writer::Track::writeD263Box() {
mOwner->beginBox("d263");
mOwner->writeInt32(0); // vendor
diff --git a/media/libstagefright/TEST_MAPPING b/media/libstagefright/TEST_MAPPING
index 53181cc..91a44d1 100644
--- a/media/libstagefright/TEST_MAPPING
+++ b/media/libstagefright/TEST_MAPPING
@@ -42,6 +42,17 @@
]
},
{
+ "name": "CtsMediaDecoderTestCases",
+ "options": [
+ {
+ "include-annotation": "android.platform.test.annotations.Presubmit"
+ },
+ {
+ "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
+ }
+ ]
+ },
+ {
"name": "CtsMediaEncoderTestCases",
"options": [
{
@@ -53,6 +64,17 @@
]
},
{
+ "name": "CtsMediaCodecTestCases",
+ "options": [
+ {
+ "include-annotation": "android.platform.test.annotations.Presubmit"
+ },
+ {
+ "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
+ }
+ ]
+ },
+ {
"name": "CtsMediaPlayerTestCases",
"options": [
{
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index a6df5bb..1854588 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -28,9 +28,6 @@
#include "include/HevcUtils.h"
#include <cutils/properties.h>
-#include <media/openmax/OMX_Audio.h>
-#include <media/openmax/OMX_Video.h>
-#include <media/openmax/OMX_VideoExt.h>
#include <media/stagefright/CodecBase.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -57,6 +54,14 @@
#define AMEDIAFORMAT_KEY_MPEGH_COMPATIBLE_SETS \
"mpegh-compatible-sets"
+namespace {
+ // TODO: this should possibly be handled in an else
+ constexpr static int32_t AACObjectNull = 0;
+
+ // TODO: decide if we should just not transmit the level in this case
+ constexpr static int32_t DolbyVisionLevelUnknown = 0;
+}
+
namespace android {
static status_t copyNALUToABuffer(sp<ABuffer> *buffer, const uint8_t *ptr, size_t length) {
@@ -156,21 +161,22 @@
audioObjectType >>= 11;
}
- const static ALookup<uint16_t, OMX_AUDIO_AACPROFILETYPE> profiles {
- { 1, OMX_AUDIO_AACObjectMain },
- { 2, OMX_AUDIO_AACObjectLC },
- { 3, OMX_AUDIO_AACObjectSSR },
- { 4, OMX_AUDIO_AACObjectLTP },
- { 5, OMX_AUDIO_AACObjectHE },
- { 6, OMX_AUDIO_AACObjectScalable },
- { 17, OMX_AUDIO_AACObjectERLC },
- { 23, OMX_AUDIO_AACObjectLD },
- { 29, OMX_AUDIO_AACObjectHE_PS },
- { 39, OMX_AUDIO_AACObjectELD },
- { 42, OMX_AUDIO_AACObjectXHE },
+
+ const static ALookup<uint16_t, int32_t> profiles {
+ { 1, AACObjectMain },
+ { 2, AACObjectLC },
+ { 3, AACObjectSSR },
+ { 4, AACObjectLTP },
+ { 5, AACObjectHE },
+ { 6, AACObjectScalable },
+ { 17, AACObjectERLC },
+ { 23, AACObjectLD },
+ { 29, AACObjectHE_PS },
+ { 39, AACObjectELD },
+ { 42, AACObjectXHE },
};
- OMX_AUDIO_AACPROFILETYPE profile;
+ int32_t profile;
if (profiles.map(audioObjectType, &profile)) {
format->setInt32("profile", profile);
}
@@ -184,53 +190,53 @@
const uint8_t constraints = ptr[2];
const uint8_t level = ptr[3];
- const static ALookup<uint8_t, OMX_VIDEO_AVCLEVELTYPE> levels {
- { 9, OMX_VIDEO_AVCLevel1b }, // technically, 9 is only used for High+ profiles
- { 10, OMX_VIDEO_AVCLevel1 },
- { 11, OMX_VIDEO_AVCLevel11 }, // prefer level 1.1 for the value 11
- { 11, OMX_VIDEO_AVCLevel1b },
- { 12, OMX_VIDEO_AVCLevel12 },
- { 13, OMX_VIDEO_AVCLevel13 },
- { 20, OMX_VIDEO_AVCLevel2 },
- { 21, OMX_VIDEO_AVCLevel21 },
- { 22, OMX_VIDEO_AVCLevel22 },
- { 30, OMX_VIDEO_AVCLevel3 },
- { 31, OMX_VIDEO_AVCLevel31 },
- { 32, OMX_VIDEO_AVCLevel32 },
- { 40, OMX_VIDEO_AVCLevel4 },
- { 41, OMX_VIDEO_AVCLevel41 },
- { 42, OMX_VIDEO_AVCLevel42 },
- { 50, OMX_VIDEO_AVCLevel5 },
- { 51, OMX_VIDEO_AVCLevel51 },
- { 52, OMX_VIDEO_AVCLevel52 },
- { 60, OMX_VIDEO_AVCLevel6 },
- { 61, OMX_VIDEO_AVCLevel61 },
- { 62, OMX_VIDEO_AVCLevel62 },
+ const static ALookup<uint8_t, int32_t> levels {
+ { 9, AVCLevel1b }, // technically, 9 is only used for High+ profiles
+ { 10, AVCLevel1 },
+ { 11, AVCLevel11 }, // prefer level 1.1 for the value 11
+ { 11, AVCLevel1b },
+ { 12, AVCLevel12 },
+ { 13, AVCLevel13 },
+ { 20, AVCLevel2 },
+ { 21, AVCLevel21 },
+ { 22, AVCLevel22 },
+ { 30, AVCLevel3 },
+ { 31, AVCLevel31 },
+ { 32, AVCLevel32 },
+ { 40, AVCLevel4 },
+ { 41, AVCLevel41 },
+ { 42, AVCLevel42 },
+ { 50, AVCLevel5 },
+ { 51, AVCLevel51 },
+ { 52, AVCLevel52 },
+ { 60, AVCLevel6 },
+ { 61, AVCLevel61 },
+ { 62, AVCLevel62 },
};
- const static ALookup<uint8_t, OMX_VIDEO_AVCPROFILETYPE> profiles {
- { 66, OMX_VIDEO_AVCProfileBaseline },
- { 77, OMX_VIDEO_AVCProfileMain },
- { 88, OMX_VIDEO_AVCProfileExtended },
- { 100, OMX_VIDEO_AVCProfileHigh },
- { 110, OMX_VIDEO_AVCProfileHigh10 },
- { 122, OMX_VIDEO_AVCProfileHigh422 },
- { 244, OMX_VIDEO_AVCProfileHigh444 },
+ const static ALookup<uint8_t, int32_t> profiles {
+ { 66, AVCProfileBaseline },
+ { 77, AVCProfileMain },
+ { 88, AVCProfileExtended },
+ { 100, AVCProfileHigh },
+ { 110, AVCProfileHigh10 },
+ { 122, AVCProfileHigh422 },
+ { 244, AVCProfileHigh444 },
};
// set profile & level if they are recognized
- OMX_VIDEO_AVCPROFILETYPE codecProfile;
- OMX_VIDEO_AVCLEVELTYPE codecLevel;
+ int32_t codecProfile;
+ int32_t codecLevel;
if (profiles.map(profile, &codecProfile)) {
if (profile == 66 && (constraints & 0x40)) {
- codecProfile = (OMX_VIDEO_AVCPROFILETYPE)OMX_VIDEO_AVCProfileConstrainedBaseline;
+ codecProfile = AVCProfileConstrainedBaseline;
} else if (profile == 100 && (constraints & 0x0C) == 0x0C) {
- codecProfile = (OMX_VIDEO_AVCPROFILETYPE)OMX_VIDEO_AVCProfileConstrainedHigh;
+ codecProfile = AVCProfileConstrainedHigh;
}
format->setInt32("profile", codecProfile);
if (levels.map(level, &codecLevel)) {
// for 9 && 11 decide level based on profile and constraint_set3 flag
if (level == 11 && (profile == 66 || profile == 77 || profile == 88)) {
- codecLevel = (constraints & 0x10) ? OMX_VIDEO_AVCLevel1b : OMX_VIDEO_AVCLevel11;
+ codecLevel = (constraints & 0x10) ? AVCLevel1b : AVCLevel11;
}
format->setInt32("level", codecLevel);
}
@@ -256,41 +262,44 @@
// All Dolby Profiles will have profile and level info in MediaFormat
// Profile 8 and 9 will have bl_compatibility_id too.
- const static ALookup<uint8_t, OMX_VIDEO_DOLBYVISIONPROFILETYPE> profiles{
- {1, OMX_VIDEO_DolbyVisionProfileDvavPen},
- {3, OMX_VIDEO_DolbyVisionProfileDvheDen},
- {4, OMX_VIDEO_DolbyVisionProfileDvheDtr},
- {5, OMX_VIDEO_DolbyVisionProfileDvheStn},
- {6, OMX_VIDEO_DolbyVisionProfileDvheDth},
- {7, OMX_VIDEO_DolbyVisionProfileDvheDtb},
- {8, OMX_VIDEO_DolbyVisionProfileDvheSt},
- {9, OMX_VIDEO_DolbyVisionProfileDvavSe},
- {10, OMX_VIDEO_DolbyVisionProfileDvav110},
+ const static ALookup<uint8_t, int32_t> profiles{
+ {1, DolbyVisionProfileDvavPen},
+ {3, DolbyVisionProfileDvheDen},
+ {4, DolbyVisionProfileDvheDtr},
+ {5, DolbyVisionProfileDvheStn},
+ {6, DolbyVisionProfileDvheDth},
+ {7, DolbyVisionProfileDvheDtb},
+ {8, DolbyVisionProfileDvheSt},
+ {9, DolbyVisionProfileDvavSe},
+ {10, DolbyVisionProfileDvav110},
};
- const static ALookup<uint8_t, OMX_VIDEO_DOLBYVISIONLEVELTYPE> levels{
- {0, OMX_VIDEO_DolbyVisionLevelUnknown},
- {1, OMX_VIDEO_DolbyVisionLevelHd24},
- {2, OMX_VIDEO_DolbyVisionLevelHd30},
- {3, OMX_VIDEO_DolbyVisionLevelFhd24},
- {4, OMX_VIDEO_DolbyVisionLevelFhd30},
- {5, OMX_VIDEO_DolbyVisionLevelFhd60},
- {6, OMX_VIDEO_DolbyVisionLevelUhd24},
- {7, OMX_VIDEO_DolbyVisionLevelUhd30},
- {8, OMX_VIDEO_DolbyVisionLevelUhd48},
- {9, OMX_VIDEO_DolbyVisionLevelUhd60},
+ const static ALookup<uint8_t, int32_t> levels{
+ {0, DolbyVisionLevelUnknown},
+ {1, DolbyVisionLevelHd24},
+ {2, DolbyVisionLevelHd30},
+ {3, DolbyVisionLevelFhd24},
+ {4, DolbyVisionLevelFhd30},
+ {5, DolbyVisionLevelFhd60},
+ {6, DolbyVisionLevelUhd24},
+ {7, DolbyVisionLevelUhd30},
+ {8, DolbyVisionLevelUhd48},
+ {9, DolbyVisionLevelUhd60},
+ {10, DolbyVisionLevelUhd120},
+ {11, DolbyVisionLevel8k30},
+ {12, DolbyVisionLevel8k60},
};
// set rpuAssoc
if (rpu_present_flag && el_present_flag && !bl_present_flag) {
format->setInt32("rpuAssoc", 1);
}
// set profile & level if they are recognized
- OMX_VIDEO_DOLBYVISIONPROFILETYPE codecProfile;
- OMX_VIDEO_DOLBYVISIONLEVELTYPE codecLevel;
+ int32_t codecProfile;
+ int32_t codecLevel;
if (profiles.map(profile, &codecProfile)) {
format->setInt32("profile", codecProfile);
- if (codecProfile == OMX_VIDEO_DolbyVisionProfileDvheSt ||
- codecProfile == OMX_VIDEO_DolbyVisionProfileDvavSe) {
+ if (codecProfile == DolbyVisionProfileDvheSt ||
+ codecProfile == DolbyVisionProfileDvavSe) {
format->setInt32("bl_compatibility_id", bl_compatibility_id);
}
if (levels.map(level, &codecLevel)) {
@@ -307,32 +316,32 @@
const uint8_t profile = ptr[6];
const uint8_t level = ptr[5];
- const static ALookup<uint8_t, OMX_VIDEO_H263PROFILETYPE> profiles {
- { 0, OMX_VIDEO_H263ProfileBaseline },
- { 1, OMX_VIDEO_H263ProfileH320Coding },
- { 2, OMX_VIDEO_H263ProfileBackwardCompatible },
- { 3, OMX_VIDEO_H263ProfileISWV2 },
- { 4, OMX_VIDEO_H263ProfileISWV3 },
- { 5, OMX_VIDEO_H263ProfileHighCompression },
- { 6, OMX_VIDEO_H263ProfileInternet },
- { 7, OMX_VIDEO_H263ProfileInterlace },
- { 8, OMX_VIDEO_H263ProfileHighLatency },
+ const static ALookup<uint8_t, int32_t> profiles {
+ { 0, H263ProfileBaseline },
+ { 1, H263ProfileH320Coding },
+ { 2, H263ProfileBackwardCompatible },
+ { 3, H263ProfileISWV2 },
+ { 4, H263ProfileISWV3 },
+ { 5, H263ProfileHighCompression },
+ { 6, H263ProfileInternet },
+ { 7, H263ProfileInterlace },
+ { 8, H263ProfileHighLatency },
};
- const static ALookup<uint8_t, OMX_VIDEO_H263LEVELTYPE> levels {
- { 10, OMX_VIDEO_H263Level10 },
- { 20, OMX_VIDEO_H263Level20 },
- { 30, OMX_VIDEO_H263Level30 },
- { 40, OMX_VIDEO_H263Level40 },
- { 45, OMX_VIDEO_H263Level45 },
- { 50, OMX_VIDEO_H263Level50 },
- { 60, OMX_VIDEO_H263Level60 },
- { 70, OMX_VIDEO_H263Level70 },
+ const static ALookup<uint8_t, int32_t> levels {
+ { 10, H263Level10 },
+ { 20, H263Level20 },
+ { 30, H263Level30 },
+ { 40, H263Level40 },
+ { 45, H263Level45 },
+ { 50, H263Level50 },
+ { 60, H263Level60 },
+ { 70, H263Level70 },
};
// set profile & level if they are recognized
- OMX_VIDEO_H263PROFILETYPE codecProfile;
- OMX_VIDEO_H263LEVELTYPE codecLevel;
+ int32_t codecProfile;
+ int32_t codecLevel;
if (profiles.map(profile, &codecProfile)) {
format->setInt32("profile", codecProfile);
if (levels.map(level, &codecLevel)) {
@@ -350,59 +359,59 @@
const uint8_t tier = (ptr[1] & 0x20) >> 5;
const uint8_t level = ptr[12];
- const static ALookup<std::pair<uint8_t, uint8_t>, OMX_VIDEO_HEVCLEVELTYPE> levels {
- { { 0, 30 }, OMX_VIDEO_HEVCMainTierLevel1 },
- { { 0, 60 }, OMX_VIDEO_HEVCMainTierLevel2 },
- { { 0, 63 }, OMX_VIDEO_HEVCMainTierLevel21 },
- { { 0, 90 }, OMX_VIDEO_HEVCMainTierLevel3 },
- { { 0, 93 }, OMX_VIDEO_HEVCMainTierLevel31 },
- { { 0, 120 }, OMX_VIDEO_HEVCMainTierLevel4 },
- { { 0, 123 }, OMX_VIDEO_HEVCMainTierLevel41 },
- { { 0, 150 }, OMX_VIDEO_HEVCMainTierLevel5 },
- { { 0, 153 }, OMX_VIDEO_HEVCMainTierLevel51 },
- { { 0, 156 }, OMX_VIDEO_HEVCMainTierLevel52 },
- { { 0, 180 }, OMX_VIDEO_HEVCMainTierLevel6 },
- { { 0, 183 }, OMX_VIDEO_HEVCMainTierLevel61 },
- { { 0, 186 }, OMX_VIDEO_HEVCMainTierLevel62 },
- { { 1, 30 }, OMX_VIDEO_HEVCHighTierLevel1 },
- { { 1, 60 }, OMX_VIDEO_HEVCHighTierLevel2 },
- { { 1, 63 }, OMX_VIDEO_HEVCHighTierLevel21 },
- { { 1, 90 }, OMX_VIDEO_HEVCHighTierLevel3 },
- { { 1, 93 }, OMX_VIDEO_HEVCHighTierLevel31 },
- { { 1, 120 }, OMX_VIDEO_HEVCHighTierLevel4 },
- { { 1, 123 }, OMX_VIDEO_HEVCHighTierLevel41 },
- { { 1, 150 }, OMX_VIDEO_HEVCHighTierLevel5 },
- { { 1, 153 }, OMX_VIDEO_HEVCHighTierLevel51 },
- { { 1, 156 }, OMX_VIDEO_HEVCHighTierLevel52 },
- { { 1, 180 }, OMX_VIDEO_HEVCHighTierLevel6 },
- { { 1, 183 }, OMX_VIDEO_HEVCHighTierLevel61 },
- { { 1, 186 }, OMX_VIDEO_HEVCHighTierLevel62 },
+ const static ALookup<std::pair<uint8_t, uint8_t>, int32_t> levels {
+ { { 0, 30 }, HEVCMainTierLevel1 },
+ { { 0, 60 }, HEVCMainTierLevel2 },
+ { { 0, 63 }, HEVCMainTierLevel21 },
+ { { 0, 90 }, HEVCMainTierLevel3 },
+ { { 0, 93 }, HEVCMainTierLevel31 },
+ { { 0, 120 }, HEVCMainTierLevel4 },
+ { { 0, 123 }, HEVCMainTierLevel41 },
+ { { 0, 150 }, HEVCMainTierLevel5 },
+ { { 0, 153 }, HEVCMainTierLevel51 },
+ { { 0, 156 }, HEVCMainTierLevel52 },
+ { { 0, 180 }, HEVCMainTierLevel6 },
+ { { 0, 183 }, HEVCMainTierLevel61 },
+ { { 0, 186 }, HEVCMainTierLevel62 },
+ { { 1, 30 }, HEVCHighTierLevel1 },
+ { { 1, 60 }, HEVCHighTierLevel2 },
+ { { 1, 63 }, HEVCHighTierLevel21 },
+ { { 1, 90 }, HEVCHighTierLevel3 },
+ { { 1, 93 }, HEVCHighTierLevel31 },
+ { { 1, 120 }, HEVCHighTierLevel4 },
+ { { 1, 123 }, HEVCHighTierLevel41 },
+ { { 1, 150 }, HEVCHighTierLevel5 },
+ { { 1, 153 }, HEVCHighTierLevel51 },
+ { { 1, 156 }, HEVCHighTierLevel52 },
+ { { 1, 180 }, HEVCHighTierLevel6 },
+ { { 1, 183 }, HEVCHighTierLevel61 },
+ { { 1, 186 }, HEVCHighTierLevel62 },
};
- const static ALookup<uint8_t, OMX_VIDEO_HEVCPROFILETYPE> profiles {
- { 1, OMX_VIDEO_HEVCProfileMain },
- { 2, OMX_VIDEO_HEVCProfileMain10 },
+ const static ALookup<uint8_t, int32_t> profiles {
+ { 1, HEVCProfileMain },
+ { 2, HEVCProfileMain10 },
// use Main for Main Still Picture decoding
- { 3, OMX_VIDEO_HEVCProfileMain },
+ { 3, HEVCProfileMain },
};
// set profile & level if they are recognized
- OMX_VIDEO_HEVCPROFILETYPE codecProfile;
- OMX_VIDEO_HEVCLEVELTYPE codecLevel;
+ int32_t codecProfile;
+ int32_t codecLevel;
if (!profiles.map(profile, &codecProfile)) {
if (ptr[2] & 0x40 /* general compatibility flag 1 */) {
// Note that this case covers Main Still Picture too
- codecProfile = OMX_VIDEO_HEVCProfileMain;
+ codecProfile = HEVCProfileMain;
} else if (ptr[2] & 0x20 /* general compatibility flag 2 */) {
- codecProfile = OMX_VIDEO_HEVCProfileMain10;
+ codecProfile = HEVCProfileMain10;
} else {
return;
}
}
// bump to HDR profile
- if (isHdr(format) && codecProfile == OMX_VIDEO_HEVCProfileMain10) {
- codecProfile = OMX_VIDEO_HEVCProfileMain10HDR10;
+ if (isHdr(format) && codecProfile == HEVCProfileMain10) {
+ codecProfile = HEVCProfileMain10HDR10;
}
format->setInt32("profile", codecProfile);
@@ -422,36 +431,36 @@
}
const uint8_t indication = ((seq[4] & 0xF) << 4) | ((seq[5] & 0xF0) >> 4);
- const static ALookup<uint8_t, OMX_VIDEO_MPEG2PROFILETYPE> profiles {
- { 0x50, OMX_VIDEO_MPEG2ProfileSimple },
- { 0x40, OMX_VIDEO_MPEG2ProfileMain },
- { 0x30, OMX_VIDEO_MPEG2ProfileSNR },
- { 0x20, OMX_VIDEO_MPEG2ProfileSpatial },
- { 0x10, OMX_VIDEO_MPEG2ProfileHigh },
+ const static ALookup<uint8_t, int32_t> profiles {
+ { 0x50, MPEG2ProfileSimple },
+ { 0x40, MPEG2ProfileMain },
+ { 0x30, MPEG2ProfileSNR },
+ { 0x20, MPEG2ProfileSpatial },
+ { 0x10, MPEG2ProfileHigh },
};
- const static ALookup<uint8_t, OMX_VIDEO_MPEG2LEVELTYPE> levels {
- { 0x0A, OMX_VIDEO_MPEG2LevelLL },
- { 0x08, OMX_VIDEO_MPEG2LevelML },
- { 0x06, OMX_VIDEO_MPEG2LevelH14 },
- { 0x04, OMX_VIDEO_MPEG2LevelHL },
- { 0x02, OMX_VIDEO_MPEG2LevelHP },
+ const static ALookup<uint8_t, int32_t> levels {
+ { 0x0A, MPEG2LevelLL },
+ { 0x08, MPEG2LevelML },
+ { 0x06, MPEG2LevelH14 },
+ { 0x04, MPEG2LevelHL },
+ { 0x02, MPEG2LevelHP },
};
const static ALookup<uint8_t,
- std::pair<OMX_VIDEO_MPEG2PROFILETYPE, OMX_VIDEO_MPEG2LEVELTYPE>> escapes {
+ std::pair<int32_t, int32_t>> escapes {
/* unsupported
- { 0x8E, { XXX_MPEG2ProfileMultiView, OMX_VIDEO_MPEG2LevelLL } },
- { 0x8D, { XXX_MPEG2ProfileMultiView, OMX_VIDEO_MPEG2LevelML } },
- { 0x8B, { XXX_MPEG2ProfileMultiView, OMX_VIDEO_MPEG2LevelH14 } },
- { 0x8A, { XXX_MPEG2ProfileMultiView, OMX_VIDEO_MPEG2LevelHL } }, */
- { 0x85, { OMX_VIDEO_MPEG2Profile422, OMX_VIDEO_MPEG2LevelML } },
- { 0x82, { OMX_VIDEO_MPEG2Profile422, OMX_VIDEO_MPEG2LevelHL } },
+ { 0x8E, { XXX_MPEG2ProfileMultiView, MPEG2LevelLL } },
+ { 0x8D, { XXX_MPEG2ProfileMultiView, MPEG2LevelML } },
+ { 0x8B, { XXX_MPEG2ProfileMultiView, MPEG2LevelH14 } },
+ { 0x8A, { XXX_MPEG2ProfileMultiView, MPEG2LevelHL } }, */
+ { 0x85, { MPEG2Profile422, MPEG2LevelML } },
+ { 0x82, { MPEG2Profile422, MPEG2LevelHL } },
};
- OMX_VIDEO_MPEG2PROFILETYPE profile;
- OMX_VIDEO_MPEG2LEVELTYPE level;
- std::pair<OMX_VIDEO_MPEG2PROFILETYPE, OMX_VIDEO_MPEG2LEVELTYPE> profileLevel;
+ int32_t profile;
+ int32_t level;
+ std::pair<int32_t, int32_t> profileLevel;
if (escapes.map(indication, &profileLevel)) {
format->setInt32("profile", profileLevel.first);
format->setInt32("level", profileLevel.second);
@@ -468,16 +477,16 @@
// esds seems to only contain the profile for MPEG-2
uint8_t objType;
if (esds.getObjectTypeIndication(&objType) == OK) {
- const static ALookup<uint8_t, OMX_VIDEO_MPEG2PROFILETYPE> profiles{
- { 0x60, OMX_VIDEO_MPEG2ProfileSimple },
- { 0x61, OMX_VIDEO_MPEG2ProfileMain },
- { 0x62, OMX_VIDEO_MPEG2ProfileSNR },
- { 0x63, OMX_VIDEO_MPEG2ProfileSpatial },
- { 0x64, OMX_VIDEO_MPEG2ProfileHigh },
- { 0x65, OMX_VIDEO_MPEG2Profile422 },
+ const static ALookup<uint8_t, int32_t> profiles{
+ { 0x60, MPEG2ProfileSimple },
+ { 0x61, MPEG2ProfileMain },
+ { 0x62, MPEG2ProfileSNR },
+ { 0x63, MPEG2ProfileSpatial },
+ { 0x64, MPEG2ProfileHigh },
+ { 0x65, MPEG2Profile422 },
};
- OMX_VIDEO_MPEG2PROFILETYPE profile;
+ int32_t profile;
if (profiles.map(objType, &profile)) {
format->setInt32("profile", profile);
}
@@ -492,82 +501,82 @@
const uint8_t indication = seq[4];
const static ALookup<uint8_t,
- std::pair<OMX_VIDEO_MPEG4PROFILETYPE, OMX_VIDEO_MPEG4LEVELTYPE>> table {
- { 0b00000001, { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level1 } },
- { 0b00000010, { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level2 } },
- { 0b00000011, { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level3 } },
- { 0b00000100, { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level4a } },
- { 0b00000101, { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level5 } },
- { 0b00000110, { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level6 } },
- { 0b00001000, { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level0 } },
- { 0b00001001, { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level0b } },
- { 0b00010000, { OMX_VIDEO_MPEG4ProfileSimpleScalable, OMX_VIDEO_MPEG4Level0 } },
- { 0b00010001, { OMX_VIDEO_MPEG4ProfileSimpleScalable, OMX_VIDEO_MPEG4Level1 } },
- { 0b00010010, { OMX_VIDEO_MPEG4ProfileSimpleScalable, OMX_VIDEO_MPEG4Level2 } },
+ std::pair<int32_t, int32_t>> table {
+ { 0b00000001, { MPEG4ProfileSimple, MPEG4Level1 } },
+ { 0b00000010, { MPEG4ProfileSimple, MPEG4Level2 } },
+ { 0b00000011, { MPEG4ProfileSimple, MPEG4Level3 } },
+ { 0b00000100, { MPEG4ProfileSimple, MPEG4Level4a } },
+ { 0b00000101, { MPEG4ProfileSimple, MPEG4Level5 } },
+ { 0b00000110, { MPEG4ProfileSimple, MPEG4Level6 } },
+ { 0b00001000, { MPEG4ProfileSimple, MPEG4Level0 } },
+ { 0b00001001, { MPEG4ProfileSimple, MPEG4Level0b } },
+ { 0b00010000, { MPEG4ProfileSimpleScalable, MPEG4Level0 } },
+ { 0b00010001, { MPEG4ProfileSimpleScalable, MPEG4Level1 } },
+ { 0b00010010, { MPEG4ProfileSimpleScalable, MPEG4Level2 } },
/* unsupported
- { 0b00011101, { XXX_MPEG4ProfileSimpleScalableER, OMX_VIDEO_MPEG4Level0 } },
- { 0b00011110, { XXX_MPEG4ProfileSimpleScalableER, OMX_VIDEO_MPEG4Level1 } },
- { 0b00011111, { XXX_MPEG4ProfileSimpleScalableER, OMX_VIDEO_MPEG4Level2 } }, */
- { 0b00100001, { OMX_VIDEO_MPEG4ProfileCore, OMX_VIDEO_MPEG4Level1 } },
- { 0b00100010, { OMX_VIDEO_MPEG4ProfileCore, OMX_VIDEO_MPEG4Level2 } },
- { 0b00110010, { OMX_VIDEO_MPEG4ProfileMain, OMX_VIDEO_MPEG4Level2 } },
- { 0b00110011, { OMX_VIDEO_MPEG4ProfileMain, OMX_VIDEO_MPEG4Level3 } },
- { 0b00110100, { OMX_VIDEO_MPEG4ProfileMain, OMX_VIDEO_MPEG4Level4 } },
+ { 0b00011101, { XXX_MPEG4ProfileSimpleScalableER, MPEG4Level0 } },
+ { 0b00011110, { XXX_MPEG4ProfileSimpleScalableER, MPEG4Level1 } },
+ { 0b00011111, { XXX_MPEG4ProfileSimpleScalableER, MPEG4Level2 } }, */
+ { 0b00100001, { MPEG4ProfileCore, MPEG4Level1 } },
+ { 0b00100010, { MPEG4ProfileCore, MPEG4Level2 } },
+ { 0b00110010, { MPEG4ProfileMain, MPEG4Level2 } },
+ { 0b00110011, { MPEG4ProfileMain, MPEG4Level3 } },
+ { 0b00110100, { MPEG4ProfileMain, MPEG4Level4 } },
/* deprecated
- { 0b01000010, { OMX_VIDEO_MPEG4ProfileNbit, OMX_VIDEO_MPEG4Level2 } }, */
- { 0b01010001, { OMX_VIDEO_MPEG4ProfileScalableTexture, OMX_VIDEO_MPEG4Level1 } },
- { 0b01100001, { OMX_VIDEO_MPEG4ProfileSimpleFace, OMX_VIDEO_MPEG4Level1 } },
- { 0b01100010, { OMX_VIDEO_MPEG4ProfileSimpleFace, OMX_VIDEO_MPEG4Level2 } },
- { 0b01100011, { OMX_VIDEO_MPEG4ProfileSimpleFBA, OMX_VIDEO_MPEG4Level1 } },
- { 0b01100100, { OMX_VIDEO_MPEG4ProfileSimpleFBA, OMX_VIDEO_MPEG4Level2 } },
- { 0b01110001, { OMX_VIDEO_MPEG4ProfileBasicAnimated, OMX_VIDEO_MPEG4Level1 } },
- { 0b01110010, { OMX_VIDEO_MPEG4ProfileBasicAnimated, OMX_VIDEO_MPEG4Level2 } },
- { 0b10000001, { OMX_VIDEO_MPEG4ProfileHybrid, OMX_VIDEO_MPEG4Level1 } },
- { 0b10000010, { OMX_VIDEO_MPEG4ProfileHybrid, OMX_VIDEO_MPEG4Level2 } },
- { 0b10010001, { OMX_VIDEO_MPEG4ProfileAdvancedRealTime, OMX_VIDEO_MPEG4Level1 } },
- { 0b10010010, { OMX_VIDEO_MPEG4ProfileAdvancedRealTime, OMX_VIDEO_MPEG4Level2 } },
- { 0b10010011, { OMX_VIDEO_MPEG4ProfileAdvancedRealTime, OMX_VIDEO_MPEG4Level3 } },
- { 0b10010100, { OMX_VIDEO_MPEG4ProfileAdvancedRealTime, OMX_VIDEO_MPEG4Level4 } },
- { 0b10100001, { OMX_VIDEO_MPEG4ProfileCoreScalable, OMX_VIDEO_MPEG4Level1 } },
- { 0b10100010, { OMX_VIDEO_MPEG4ProfileCoreScalable, OMX_VIDEO_MPEG4Level2 } },
- { 0b10100011, { OMX_VIDEO_MPEG4ProfileCoreScalable, OMX_VIDEO_MPEG4Level3 } },
- { 0b10110001, { OMX_VIDEO_MPEG4ProfileAdvancedCoding, OMX_VIDEO_MPEG4Level1 } },
- { 0b10110010, { OMX_VIDEO_MPEG4ProfileAdvancedCoding, OMX_VIDEO_MPEG4Level2 } },
- { 0b10110011, { OMX_VIDEO_MPEG4ProfileAdvancedCoding, OMX_VIDEO_MPEG4Level3 } },
- { 0b10110100, { OMX_VIDEO_MPEG4ProfileAdvancedCoding, OMX_VIDEO_MPEG4Level4 } },
- { 0b11000001, { OMX_VIDEO_MPEG4ProfileAdvancedCore, OMX_VIDEO_MPEG4Level1 } },
- { 0b11000010, { OMX_VIDEO_MPEG4ProfileAdvancedCore, OMX_VIDEO_MPEG4Level2 } },
- { 0b11010001, { OMX_VIDEO_MPEG4ProfileAdvancedScalable, OMX_VIDEO_MPEG4Level1 } },
- { 0b11010010, { OMX_VIDEO_MPEG4ProfileAdvancedScalable, OMX_VIDEO_MPEG4Level2 } },
- { 0b11010011, { OMX_VIDEO_MPEG4ProfileAdvancedScalable, OMX_VIDEO_MPEG4Level3 } },
+ { 0b01000010, { MPEG4ProfileNbit, MPEG4Level2 } }, */
+ { 0b01010001, { MPEG4ProfileScalableTexture, MPEG4Level1 } },
+ { 0b01100001, { MPEG4ProfileSimpleFace, MPEG4Level1 } },
+ { 0b01100010, { MPEG4ProfileSimpleFace, MPEG4Level2 } },
+ { 0b01100011, { MPEG4ProfileSimpleFBA, MPEG4Level1 } },
+ { 0b01100100, { MPEG4ProfileSimpleFBA, MPEG4Level2 } },
+ { 0b01110001, { MPEG4ProfileBasicAnimated, MPEG4Level1 } },
+ { 0b01110010, { MPEG4ProfileBasicAnimated, MPEG4Level2 } },
+ { 0b10000001, { MPEG4ProfileHybrid, MPEG4Level1 } },
+ { 0b10000010, { MPEG4ProfileHybrid, MPEG4Level2 } },
+ { 0b10010001, { MPEG4ProfileAdvancedRealTime, MPEG4Level1 } },
+ { 0b10010010, { MPEG4ProfileAdvancedRealTime, MPEG4Level2 } },
+ { 0b10010011, { MPEG4ProfileAdvancedRealTime, MPEG4Level3 } },
+ { 0b10010100, { MPEG4ProfileAdvancedRealTime, MPEG4Level4 } },
+ { 0b10100001, { MPEG4ProfileCoreScalable, MPEG4Level1 } },
+ { 0b10100010, { MPEG4ProfileCoreScalable, MPEG4Level2 } },
+ { 0b10100011, { MPEG4ProfileCoreScalable, MPEG4Level3 } },
+ { 0b10110001, { MPEG4ProfileAdvancedCoding, MPEG4Level1 } },
+ { 0b10110010, { MPEG4ProfileAdvancedCoding, MPEG4Level2 } },
+ { 0b10110011, { MPEG4ProfileAdvancedCoding, MPEG4Level3 } },
+ { 0b10110100, { MPEG4ProfileAdvancedCoding, MPEG4Level4 } },
+ { 0b11000001, { MPEG4ProfileAdvancedCore, MPEG4Level1 } },
+ { 0b11000010, { MPEG4ProfileAdvancedCore, MPEG4Level2 } },
+ { 0b11010001, { MPEG4ProfileAdvancedScalable, MPEG4Level1 } },
+ { 0b11010010, { MPEG4ProfileAdvancedScalable, MPEG4Level2 } },
+ { 0b11010011, { MPEG4ProfileAdvancedScalable, MPEG4Level3 } },
/* unsupported
- { 0b11100001, { XXX_MPEG4ProfileSimpleStudio, OMX_VIDEO_MPEG4Level1 } },
- { 0b11100010, { XXX_MPEG4ProfileSimpleStudio, OMX_VIDEO_MPEG4Level2 } },
- { 0b11100011, { XXX_MPEG4ProfileSimpleStudio, OMX_VIDEO_MPEG4Level3 } },
- { 0b11100100, { XXX_MPEG4ProfileSimpleStudio, OMX_VIDEO_MPEG4Level4 } },
- { 0b11100101, { XXX_MPEG4ProfileCoreStudio, OMX_VIDEO_MPEG4Level1 } },
- { 0b11100110, { XXX_MPEG4ProfileCoreStudio, OMX_VIDEO_MPEG4Level2 } },
- { 0b11100111, { XXX_MPEG4ProfileCoreStudio, OMX_VIDEO_MPEG4Level3 } },
- { 0b11101000, { XXX_MPEG4ProfileCoreStudio, OMX_VIDEO_MPEG4Level4 } },
- { 0b11101011, { XXX_MPEG4ProfileSimpleStudio, OMX_VIDEO_MPEG4Level5 } },
- { 0b11101100, { XXX_MPEG4ProfileSimpleStudio, OMX_VIDEO_MPEG4Level6 } }, */
- { 0b11110000, { OMX_VIDEO_MPEG4ProfileAdvancedSimple, OMX_VIDEO_MPEG4Level0 } },
- { 0b11110001, { OMX_VIDEO_MPEG4ProfileAdvancedSimple, OMX_VIDEO_MPEG4Level1 } },
- { 0b11110010, { OMX_VIDEO_MPEG4ProfileAdvancedSimple, OMX_VIDEO_MPEG4Level2 } },
- { 0b11110011, { OMX_VIDEO_MPEG4ProfileAdvancedSimple, OMX_VIDEO_MPEG4Level3 } },
- { 0b11110100, { OMX_VIDEO_MPEG4ProfileAdvancedSimple, OMX_VIDEO_MPEG4Level4 } },
- { 0b11110101, { OMX_VIDEO_MPEG4ProfileAdvancedSimple, OMX_VIDEO_MPEG4Level5 } },
- { 0b11110111, { OMX_VIDEO_MPEG4ProfileAdvancedSimple, OMX_VIDEO_MPEG4Level3b } },
+ { 0b11100001, { XXX_MPEG4ProfileSimpleStudio, MPEG4Level1 } },
+ { 0b11100010, { XXX_MPEG4ProfileSimpleStudio, MPEG4Level2 } },
+ { 0b11100011, { XXX_MPEG4ProfileSimpleStudio, MPEG4Level3 } },
+ { 0b11100100, { XXX_MPEG4ProfileSimpleStudio, MPEG4Level4 } },
+ { 0b11100101, { XXX_MPEG4ProfileCoreStudio, MPEG4Level1 } },
+ { 0b11100110, { XXX_MPEG4ProfileCoreStudio, MPEG4Level2 } },
+ { 0b11100111, { XXX_MPEG4ProfileCoreStudio, MPEG4Level3 } },
+ { 0b11101000, { XXX_MPEG4ProfileCoreStudio, MPEG4Level4 } },
+ { 0b11101011, { XXX_MPEG4ProfileSimpleStudio, MPEG4Level5 } },
+ { 0b11101100, { XXX_MPEG4ProfileSimpleStudio, MPEG4Level6 } }, */
+ { 0b11110000, { MPEG4ProfileAdvancedSimple, MPEG4Level0 } },
+ { 0b11110001, { MPEG4ProfileAdvancedSimple, MPEG4Level1 } },
+ { 0b11110010, { MPEG4ProfileAdvancedSimple, MPEG4Level2 } },
+ { 0b11110011, { MPEG4ProfileAdvancedSimple, MPEG4Level3 } },
+ { 0b11110100, { MPEG4ProfileAdvancedSimple, MPEG4Level4 } },
+ { 0b11110101, { MPEG4ProfileAdvancedSimple, MPEG4Level5 } },
+ { 0b11110111, { MPEG4ProfileAdvancedSimple, MPEG4Level3b } },
/* deprecated
- { 0b11111000, { XXX_MPEG4ProfileFineGranularityScalable, OMX_VIDEO_MPEG4Level0 } },
- { 0b11111001, { XXX_MPEG4ProfileFineGranularityScalable, OMX_VIDEO_MPEG4Level1 } },
- { 0b11111010, { XXX_MPEG4ProfileFineGranularityScalable, OMX_VIDEO_MPEG4Level2 } },
- { 0b11111011, { XXX_MPEG4ProfileFineGranularityScalable, OMX_VIDEO_MPEG4Level3 } },
- { 0b11111100, { XXX_MPEG4ProfileFineGranularityScalable, OMX_VIDEO_MPEG4Level4 } },
- { 0b11111101, { XXX_MPEG4ProfileFineGranularityScalable, OMX_VIDEO_MPEG4Level5 } }, */
+ { 0b11111000, { XXX_MPEG4ProfileFineGranularityScalable, MPEG4Level0 } },
+ { 0b11111001, { XXX_MPEG4ProfileFineGranularityScalable, MPEG4Level1 } },
+ { 0b11111010, { XXX_MPEG4ProfileFineGranularityScalable, MPEG4Level2 } },
+ { 0b11111011, { XXX_MPEG4ProfileFineGranularityScalable, MPEG4Level3 } },
+ { 0b11111100, { XXX_MPEG4ProfileFineGranularityScalable, MPEG4Level4 } },
+ { 0b11111101, { XXX_MPEG4ProfileFineGranularityScalable, MPEG4Level5 } }, */
};
- std::pair<OMX_VIDEO_MPEG4PROFILETYPE, OMX_VIDEO_MPEG4LEVELTYPE> profileLevel;
+ std::pair<int32_t, int32_t> profileLevel;
if (table.map(indication, &profileLevel)) {
format->setInt32("profile", profileLevel.first);
format->setInt32("level", profileLevel.second);
@@ -590,19 +599,19 @@
switch (id) {
case 1 /* profileId */:
if (length >= 1) {
- const static ALookup<uint8_t, OMX_VIDEO_VP9PROFILETYPE> profiles {
- { 0, OMX_VIDEO_VP9Profile0 },
- { 1, OMX_VIDEO_VP9Profile1 },
- { 2, OMX_VIDEO_VP9Profile2 },
- { 3, OMX_VIDEO_VP9Profile3 },
+ const static ALookup<uint8_t, int32_t> profiles {
+ { 0, VP9Profile0 },
+ { 1, VP9Profile1 },
+ { 2, VP9Profile2 },
+ { 3, VP9Profile3 },
};
- const static ALookup<OMX_VIDEO_VP9PROFILETYPE, OMX_VIDEO_VP9PROFILETYPE> toHdr {
- { OMX_VIDEO_VP9Profile2, OMX_VIDEO_VP9Profile2HDR },
- { OMX_VIDEO_VP9Profile3, OMX_VIDEO_VP9Profile3HDR },
+ const static ALookup<int32_t, int32_t> toHdr {
+ { VP9Profile2, VP9Profile2HDR },
+ { VP9Profile3, VP9Profile3HDR },
};
- OMX_VIDEO_VP9PROFILETYPE profile;
+ int32_t profile;
if (profiles.map(data[0], &profile)) {
// convert to HDR profile
if (isHdr(format)) {
@@ -615,24 +624,24 @@
break;
case 2 /* levelId */:
if (length >= 1) {
- const static ALookup<uint8_t, OMX_VIDEO_VP9LEVELTYPE> levels {
- { 10, OMX_VIDEO_VP9Level1 },
- { 11, OMX_VIDEO_VP9Level11 },
- { 20, OMX_VIDEO_VP9Level2 },
- { 21, OMX_VIDEO_VP9Level21 },
- { 30, OMX_VIDEO_VP9Level3 },
- { 31, OMX_VIDEO_VP9Level31 },
- { 40, OMX_VIDEO_VP9Level4 },
- { 41, OMX_VIDEO_VP9Level41 },
- { 50, OMX_VIDEO_VP9Level5 },
- { 51, OMX_VIDEO_VP9Level51 },
- { 52, OMX_VIDEO_VP9Level52 },
- { 60, OMX_VIDEO_VP9Level6 },
- { 61, OMX_VIDEO_VP9Level61 },
- { 62, OMX_VIDEO_VP9Level62 },
+ const static ALookup<uint8_t, int32_t> levels {
+ { 10, VP9Level1 },
+ { 11, VP9Level11 },
+ { 20, VP9Level2 },
+ { 21, VP9Level21 },
+ { 30, VP9Level3 },
+ { 31, VP9Level31 },
+ { 40, VP9Level4 },
+ { 41, VP9Level41 },
+ { 50, VP9Level5 },
+ { 51, VP9Level51 },
+ { 52, VP9Level52 },
+ { 60, VP9Level6 },
+ { 61, VP9Level61 },
+ { 62, VP9Level62 },
};
- OMX_VIDEO_VP9LEVELTYPE level;
+ int32_t level;
if (levels.map(data[0], &level)) {
format->setInt32("level", level);
}
@@ -1504,7 +1513,30 @@
msg->setBuffer("csd-0", buffer);
}
- if (meta->findData(kKeyDVCC, &type, &data, &size)) {
+ if (meta->findData(kKeyDVCC, &type, &data, &size)
+ || meta->findData(kKeyDVVC, &type, &data, &size)
+ || meta->findData(kKeyDVWC, &type, &data, &size)) {
+ sp<ABuffer> buffer, csdOrg;
+ if (msg->findBuffer("csd-0", &csdOrg)) {
+ buffer = new (std::nothrow) ABuffer(size + csdOrg->size());
+ if (buffer.get() == NULL || buffer->base() == NULL) {
+ return NO_MEMORY;
+ }
+
+ memcpy(buffer->data(), csdOrg->data(), csdOrg->size());
+ memcpy(buffer->data() + csdOrg->size(), data, size);
+ } else {
+ buffer = new (std::nothrow) ABuffer(size);
+ if (buffer.get() == NULL || buffer->base() == NULL) {
+ return NO_MEMORY;
+ }
+ memcpy(buffer->data(), data, size);
+ }
+
+ buffer->meta()->setInt32("csd", true);
+ buffer->meta()->setInt64("timeUs", 0);
+ msg->setBuffer("csd-0", buffer);
+
const uint8_t *ptr = (const uint8_t *)data;
ALOGV("DV: calling parseDolbyVisionProfileLevelFromDvcc with data size %zu", size);
parseDolbyVisionProfileLevelFromDvcc(ptr, size, msg);
@@ -2009,30 +2041,134 @@
mime == MEDIA_MIMETYPE_IMAGE_AVIF) {
meta->setData(kKeyAV1C, 0, csd0->data(), csd0->size());
} else if (mime == MEDIA_MIMETYPE_VIDEO_DOLBY_VISION) {
- if (msg->findBuffer("csd-2", &csd2)) {
- //dvcc should be 24
- if (csd2->size() == 24) {
- meta->setData(kKeyDVCC, kTypeDVCC, csd2->data(), csd2->size());
- uint8_t *dvcc = csd2->data();
- const uint8_t profile = dvcc[2] >> 1;
- if (profile > 1 && profile < 9) {
+ int32_t needCreateDoviCSD = 0;
+ int32_t profile = 0;
+ uint8_t bl_compatibility = 0;
+ if (msg->findInt32("profile", &profile)) {
+ if (profile == DolbyVisionProfileDvheSt) {
+ profile = 8;
+ bl_compatibility = 4;
+ } else if (profile == DolbyVisionProfileDvavSe) {
+ profile = 9;
+ bl_compatibility = 2;
+ }
+ if (profile == 8 || profile == 9) {
+ needCreateDoviCSD = 1;
+ }
+ } else {
+ ALOGW("did not find dolby vision profile");
+ }
+ // No dovi csd data, need to create it
+ if (needCreateDoviCSD) {
+ uint8_t dvcc[24];
+ int32_t level = 0;
+ uint8_t level_val = 0;
+
+ if (msg->findInt32("level", &level)) {
+ const static ALookup<int32_t, uint8_t> levels {
+ {DolbyVisionLevelUnknown, 0},
+ {DolbyVisionLevelHd24, 1},
+ {DolbyVisionLevelHd30, 2},
+ {DolbyVisionLevelFhd24, 3},
+ {DolbyVisionLevelFhd30, 4},
+ {DolbyVisionLevelFhd60, 5},
+ {DolbyVisionLevelUhd24, 6},
+ {DolbyVisionLevelUhd30, 7},
+ {DolbyVisionLevelUhd48, 8},
+ {DolbyVisionLevelUhd60, 9},
+ {DolbyVisionLevelUhd120, 10},
+ {DolbyVisionLevel8k30, 11},
+ {DolbyVisionLevel8k60, 12},
+ };
+ levels.map(level, &level_val);
+ ALOGV("found dolby vision level: %d, value: %d", level, level_val);
+ }
+
+ dvcc[0] = 1; // major version
+ dvcc[1] = 0; // minor version
+ dvcc[2] = (uint8_t)((profile & 0x7f) << 1);// dolby vision profile
+ dvcc[2] = (uint8_t)((dvcc[2] | (uint8_t)((level_val >> 5) & 0x1)) & 0xff);
+ dvcc[3] = (uint8_t)((level_val & 0x1f) << 3); // dolby vision level
+ dvcc[3] = (uint8_t)(dvcc[3] | (1 << 2)); // rpu_present_flag
+ dvcc[3] = (uint8_t)(dvcc[3] | (1)); // bl_present_flag
+ dvcc[4] = (uint8_t)(bl_compatibility << 4);// bl_compatibility id
+
+ std::vector<uint8_t> dvcc_data(24);
+ memcpy(dvcc_data.data(), dvcc, 24);
+ if (profile > 10) {
+ meta->setData(kKeyDVWC, kTypeDVWC, dvcc_data.data(), 24);
+ } else if (profile > 7) {
+ meta->setData(kKeyDVVC, kTypeDVVC, dvcc_data.data(), 24);
+ } else {
+ meta->setData(kKeyDVCC, kTypeDVCC, dvcc_data.data(), 24);
+ }
+ } else if (csd0size >= 24) { // have dovi csd, just send it out...
+ uint8_t *dvconfig = csd0->data() + (csd0size -24);
+ profile = dvconfig[2] >> 1;
+ if (profile > 10) {
+ meta->setData(kKeyDVWC, kTypeDVWC, dvconfig, 24);
+ } else if (profile > 7) {
+ meta->setData(kKeyDVVC, kTypeDVVC, dvconfig, 24);
+ } else {
+ meta->setData(kKeyDVCC, kTypeDVCC, dvconfig, 24);
+ }
+ } else {
+ return BAD_VALUE;
+ }
+
+ // Send the avc/hevc/av1 csd data...
+ if (csd0size >= 24) {
+ sp<ABuffer> csd;
+ if ( profile > 1 && profile < 9) {
+ if (msg->findBuffer("csd-hevc", &csd)) {
+ meta->setData(kKeyHVCC, kTypeHVCC, csd->data(), csd->size());
+ } else if (csd0size > 24) {
std::vector<uint8_t> hvcc(csd0size + 1024);
size_t outsize = reassembleHVCC(csd0, hvcc.data(), hvcc.size(), 4);
meta->setData(kKeyHVCC, kTypeHVCC, hvcc.data(), outsize);
- } else if (DolbyVisionProfileDvav110 == profile) {
- meta->setData(kKeyAV1C, 0, csd0->data(), csd0->size());
- } else {
- sp<ABuffer> csd1;
- if (msg->findBuffer("csd-1", &csd1)) {
- std::vector<char> avcc(csd0size + csd1->size() + 1024);
- size_t outsize = reassembleAVCC(csd0, csd1, avcc.data());
- meta->setData(kKeyAVCC, kTypeAVCC, avcc.data(), outsize);
- }
}
+ } else if (profile == 9) {
+ sp<ABuffer> csd1;
+ if (msg->findBuffer("csd-avc", &csd)) {
+ meta->setData(kKeyAVCC, kTypeAVCC, csd->data(), csd->size());
+ } else if (msg->findBuffer("csd-1", &csd1)) {
+ std::vector<char> avcc(csd0size + csd1->size() + 1024);
+ size_t outsize = reassembleAVCC(csd0, csd1, avcc.data());
+ meta->setData(kKeyAVCC, kTypeAVCC, avcc.data(), outsize);
+ } else { // for dolby vision avc, csd0 also holds csd1
+ size_t i = 0;
+ int csd0realsize = 0;
+ do {
+ i = findNextNalStartCode(csd0->data() + i,
+ csd0->size() - i) - csd0->data();
+ if (i > 0) {
+ csd0realsize = i;
+ break;
+ }
+ i += 4;
+ } while(i < csd0->size());
+ // buffer0 -> csd0
+ sp<ABuffer> buffer0 = new (std::nothrow) ABuffer(csd0realsize);
+ if (buffer0.get() == NULL || buffer0->base() == NULL) {
+ return NO_MEMORY;
+ }
+ memcpy(buffer0->data(), csd0->data(), csd0realsize);
+ // buffer1 -> csd1
+ sp<ABuffer> buffer1 = new (std::nothrow)
+ ABuffer(csd0->size() - csd0realsize);
+ if (buffer1.get() == NULL || buffer1->base() == NULL) {
+ return NO_MEMORY;
+ }
+ memcpy(buffer1->data(), csd0->data()+csd0realsize,
+ csd0->size() - csd0realsize);
+
+ std::vector<char> avcc(csd0->size() + 1024);
+ size_t outsize = reassembleAVCC(buffer0, buffer1, avcc.data());
+ meta->setData(kKeyAVCC, kTypeAVCC, avcc.data(), outsize);
+ }
+ } else if (profile == 10) {
+ meta->setData(kKeyAV1C, 0, csd0->data(), csd0->size() - 24);
}
- } else {
- ALOGE("We need csd-2!!. %s", msg->debugString().c_str());
- return BAD_VALUE;
}
} else if (mime == MEDIA_MIMETYPE_VIDEO_VP9) {
meta->setData(kKeyVp9CodecPrivate, 0, csd0->data(), csd0->size());
@@ -2080,17 +2216,6 @@
meta->setData(kKeyStreamHeader, 'mdat', csd0->data(), csd0->size());
} else if (msg->findBuffer("d263", &csd0)) {
meta->setData(kKeyD263, kTypeD263, csd0->data(), csd0->size());
- } else if (mime == MEDIA_MIMETYPE_VIDEO_DOLBY_VISION && msg->findBuffer("csd-2", &csd2)) {
- meta->setData(kKeyDVCC, kTypeDVCC, csd2->data(), csd2->size());
-
- // Remove CSD-2 from the data here to avoid duplicate data in meta
- meta->remove(kKeyOpaqueCSD2);
-
- if (msg->findBuffer("csd-avc", &csd0)) {
- meta->setData(kKeyAVCC, kTypeAVCC, csd0->data(), csd0->size());
- } else if (msg->findBuffer("csd-hevc", &csd0)) {
- meta->setData(kKeyHVCC, kTypeHVCC, csd0->data(), csd0->size());
- }
}
// XXX TODO add whatever other keys there are
@@ -2173,29 +2298,29 @@
}
struct aac_format_conv_t {
- OMX_AUDIO_AACPROFILETYPE eAacProfileType;
+ int32_t eAacProfileType;
audio_format_t format;
};
static const struct aac_format_conv_t profileLookup[] = {
- { OMX_AUDIO_AACObjectMain, AUDIO_FORMAT_AAC_MAIN},
- { OMX_AUDIO_AACObjectLC, AUDIO_FORMAT_AAC_LC},
- { OMX_AUDIO_AACObjectSSR, AUDIO_FORMAT_AAC_SSR},
- { OMX_AUDIO_AACObjectLTP, AUDIO_FORMAT_AAC_LTP},
- { OMX_AUDIO_AACObjectHE, AUDIO_FORMAT_AAC_HE_V1},
- { OMX_AUDIO_AACObjectScalable, AUDIO_FORMAT_AAC_SCALABLE},
- { OMX_AUDIO_AACObjectERLC, AUDIO_FORMAT_AAC_ERLC},
- { OMX_AUDIO_AACObjectLD, AUDIO_FORMAT_AAC_LD},
- { OMX_AUDIO_AACObjectHE_PS, AUDIO_FORMAT_AAC_HE_V2},
- { OMX_AUDIO_AACObjectELD, AUDIO_FORMAT_AAC_ELD},
- { OMX_AUDIO_AACObjectXHE, AUDIO_FORMAT_AAC_XHE},
- { OMX_AUDIO_AACObjectNull, AUDIO_FORMAT_AAC},
+ { AACObjectMain, AUDIO_FORMAT_AAC_MAIN},
+ { AACObjectLC, AUDIO_FORMAT_AAC_LC},
+ { AACObjectSSR, AUDIO_FORMAT_AAC_SSR},
+ { AACObjectLTP, AUDIO_FORMAT_AAC_LTP},
+ { AACObjectHE, AUDIO_FORMAT_AAC_HE_V1},
+ { AACObjectScalable, AUDIO_FORMAT_AAC_SCALABLE},
+ { AACObjectERLC, AUDIO_FORMAT_AAC_ERLC},
+ { AACObjectLD, AUDIO_FORMAT_AAC_LD},
+ { AACObjectHE_PS, AUDIO_FORMAT_AAC_HE_V2},
+ { AACObjectELD, AUDIO_FORMAT_AAC_ELD},
+ { AACObjectXHE, AUDIO_FORMAT_AAC_XHE},
+ { AACObjectNull, AUDIO_FORMAT_AAC},
};
void mapAACProfileToAudioFormat( audio_format_t& format, uint64_t eAacProfile)
{
-const struct aac_format_conv_t* p = &profileLookup[0];
- while (p->eAacProfileType != OMX_AUDIO_AACObjectNull) {
+ const struct aac_format_conv_t* p = &profileLookup[0];
+ while (p->eAacProfileType != AACObjectNull) {
if (eAacProfile == p->eAacProfileType) {
format = p->format;
return;
@@ -2235,7 +2360,7 @@
// Offloading depends on audio DSP capabilities.
int32_t aacaot = -1;
if (meta->findInt32(kKeyAACAOT, &aacaot)) {
- mapAACProfileToAudioFormat(info->format,(OMX_AUDIO_AACPROFILETYPE) aacaot);
+ mapAACProfileToAudioFormat(info->format, aacaot);
}
int32_t srate = -1;
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
index a3fa6e8..fa9dc8b 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
@@ -540,6 +540,9 @@
constexpr int32_t DolbyVisionLevelUhd30 = 0x40;
constexpr int32_t DolbyVisionLevelUhd48 = 0x80;
constexpr int32_t DolbyVisionLevelUhd60 = 0x100;
+constexpr int32_t DolbyVisionLevelUhd120 = 0x200;
+constexpr int32_t DolbyVisionLevel8k30 = 0x400;
+constexpr int32_t DolbyVisionLevel8k60 = 0x800;
inline static const char *asString_DolbyVisionLevel(int32_t i, const char *def = "??") {
switch (i) {
@@ -552,6 +555,9 @@
case DolbyVisionLevelUhd30: return "Uhd30";
case DolbyVisionLevelUhd48: return "Uhd48";
case DolbyVisionLevelUhd60: return "Uhd60";
+ case DolbyVisionLevelUhd120: return "Uhd120";
+ case DolbyVisionLevel8k30: return "8k30";
+ case DolbyVisionLevel8k60: return "8k60";
default: return def;
}
}
@@ -689,6 +695,7 @@
}
constexpr char FEATURE_AdaptivePlayback[] = "adaptive-playback";
+constexpr char FEATURE_EncodingStatistics[] = "encoding-statistics";
constexpr char FEATURE_IntraRefresh[] = "intra-refresh";
constexpr char FEATURE_PartialFrame[] = "partial-frame";
constexpr char FEATURE_QpBounds[] = "qp-bounds";
@@ -742,6 +749,14 @@
constexpr int32_t COLOR_TRANSFER_SDR_VIDEO = 3;
constexpr int32_t COLOR_TRANSFER_ST2084 = 6;
+constexpr int32_t PICTURE_TYPE_I = 1;
+constexpr int32_t PICTURE_TYPE_P = 2;
+constexpr int32_t PICTURE_TYPE_B = 3;
+constexpr int32_t PICTURE_TYPE_UNKNOWN = 0;
+
+constexpr int32_t VIDEO_ENCODING_STATISTICS_LEVEL_1 = 1;
+constexpr int32_t VIDEO_ENCODING_STATISTICS_LEVEL_NONE = 0;
+
constexpr char KEY_AAC_DRC_ALBUM_MODE[] = "aac-drc-album-mode";
constexpr char KEY_AAC_DRC_ATTENUATION_FACTOR[] = "aac-drc-cut-level";
constexpr char KEY_AAC_DRC_BOOST_FACTOR[] = "aac-drc-boost-level";
@@ -800,6 +815,7 @@
constexpr char KEY_OPERATING_RATE[] = "operating-rate";
constexpr char KEY_OUTPUT_REORDER_DEPTH[] = "output-reorder-depth";
constexpr char KEY_PCM_ENCODING[] = "pcm-encoding";
+constexpr char KEY_PICTURE_TYPE[] = "picture_type";
constexpr char KEY_PIXEL_ASPECT_RATIO_HEIGHT[] = "sar-height";
constexpr char KEY_PIXEL_ASPECT_RATIO_WIDTH[] = "sar-width";
constexpr char KEY_PREPEND_HEADER_TO_SYNC_FRAMES[] = "prepend-sps-pps-to-idr-frames";
@@ -816,6 +832,8 @@
constexpr char KEY_TILE_HEIGHT[] = "tile-height";
constexpr char KEY_TILE_WIDTH[] = "tile-width";
constexpr char KEY_TRACK_ID[] = "track-id";
+constexpr char KEY_VIDEO_ENCODING_STATISTICS_LEVEL[] = "video-encoding-statistics-level";
+constexpr char KEY_VIDEO_QP_AVERAGE[] = "video-qp-average";
constexpr char KEY_VIDEO_QP_B_MAX[] = "video-qp-b-max";
constexpr char KEY_VIDEO_QP_B_MIN[] = "video-qp-b-min";
constexpr char KEY_VIDEO_QP_I_MAX[] = "video-qp-i-max";
diff --git a/media/libstagefright/include/media/stagefright/MetaDataBase.h b/media/libstagefright/include/media/stagefright/MetaDataBase.h
index c80012e..88c1f3f 100644
--- a/media/libstagefright/include/media/stagefright/MetaDataBase.h
+++ b/media/libstagefright/include/media/stagefright/MetaDataBase.h
@@ -60,6 +60,8 @@
kKeyAVCC = 'avcc', // raw data
kKeyHVCC = 'hvcc', // raw data
kKeyDVCC = 'dvcc', // raw data
+ kKeyDVVC = 'dvvc', // raw data
+ kKeyDVWC = 'dvwc', // raw data
kKeyAV1C = 'av1c', // raw data
kKeyThumbnailHVCC = 'thvc', // raw data
kKeyThumbnailAV1C = 'tav1', // raw data
@@ -283,6 +285,8 @@
kTypeHVCC = 'hvcc',
kTypeAV1C = 'av1c',
kTypeDVCC = 'dvcc',
+ kTypeDVVC = 'dvvc',
+ kTypeDVWC = 'dvwc',
kTypeD263 = 'd263',
kTypeHCOS = 'hcos',
};
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index 51f6c78..f2f9a66 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -356,6 +356,7 @@
EXPORT const char* AMEDIAFORMAT_KEY_MPEG2_STREAM_HEADER = "mpeg2-stream-header";
EXPORT const char* AMEDIAFORMAT_KEY_OPERATING_RATE = "operating-rate";
EXPORT const char* AMEDIAFORMAT_KEY_PCM_ENCODING = "pcm-encoding";
+EXPORT const char* AMEDIAFORMAT_KEY_PICTURE_TYPE = "picture-type";
EXPORT const char* AMEDIAFORMAT_KEY_PRIORITY = "priority";
EXPORT const char* AMEDIAFORMAT_KEY_PROFILE = "profile";
EXPORT const char* AMEDIAFORMAT_KEY_PCM_BIG_ENDIAN = "pcm-big-endian";
@@ -389,6 +390,9 @@
EXPORT const char* AMEDIAFORMAT_KEY_TRACK_ID = "track-id";
EXPORT const char* AMEDIAFORMAT_KEY_TRACK_INDEX = "track-index";
EXPORT const char* AMEDIAFORMAT_KEY_VALID_SAMPLES = "valid-samples";
+EXPORT const char* AMEDIAFORMAT_KEY_VIDEO_ENCODING_STATISTICS_LEVEL =
+ "video-encoding-statistics-level";
+EXPORT const char* AMEDIAFORMAT_KEY_VIDEO_QP_AVERAGE = "video-qp-average";
EXPORT const char* AMEDIAFORMAT_VIDEO_QP_B_MAX = "video-qp-b-max";
EXPORT const char* AMEDIAFORMAT_VIDEO_QP_B_MIN = "video-qp-b-min";
EXPORT const char* AMEDIAFORMAT_VIDEO_QP_I_MAX = "video-qp-i-max";
diff --git a/media/ndk/include/media/NdkMediaFormat.h b/media/ndk/include/media/NdkMediaFormat.h
index fbd855d..204134a 100644
--- a/media/ndk/include/media/NdkMediaFormat.h
+++ b/media/ndk/include/media/NdkMediaFormat.h
@@ -311,6 +311,10 @@
extern const char* AMEDIAFORMAT_KEY_LAST_SAMPLE_INDEX_IN_CHUNK __INTRODUCED_IN(31);
extern const char* AMEDIAFORMAT_KEY_SAMPLE_TIME_BEFORE_APPEND __INTRODUCED_IN(31);
+extern const char* AMEDIAFORMAT_KEY_PICTURE_TYPE __INTRODUCED_IN(33);
+extern const char* AMEDIAFORMAT_KEY_VIDEO_ENCODING_STATISTICS_LEVEL __INTRODUCED_IN(33);
+extern const char* AMEDIAFORMAT_KEY_VIDEO_QP_AVERAGE __INTRODUCED_IN(33);
+
extern const char* AMEDIAFORMAT_VIDEO_QP_B_MAX __INTRODUCED_IN(31);
extern const char* AMEDIAFORMAT_VIDEO_QP_B_MIN __INTRODUCED_IN(31);
extern const char* AMEDIAFORMAT_VIDEO_QP_I_MAX __INTRODUCED_IN(31);
diff --git a/services/audioflinger/OWNERS b/services/audioflinger/OWNERS
index 034d161..17d4c37 100644
--- a/services/audioflinger/OWNERS
+++ b/services/audioflinger/OWNERS
@@ -1,4 +1,4 @@
-gkasten@google.com
hunga@google.com
jmtrivi@google.com
mnaganov@google.com
+philburk@google.com
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 746d875..4398edd 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -5626,6 +5626,20 @@
return trackCount;
}
+bool AudioFlinger::PlaybackThread::checkRunningTimestamp()
+{
+ uint64_t position = 0;
+ struct timespec unused;
+ const status_t ret = mOutput->getPresentationPosition(&position, &unused);
+ if (ret == NO_ERROR) {
+ if (position != mLastCheckedTimestampPosition) {
+ mLastCheckedTimestampPosition = position;
+ return true;
+ }
+ }
+ return false;
+}
+
// isTrackAllowed_l() must be called with ThreadBase::mLock held
bool AudioFlinger::MixerThread::isTrackAllowed_l(
audio_channel_mask_t channelMask, audio_format_t format,
@@ -6054,19 +6068,24 @@
// fill a buffer, then remove it from active list.
// Only consider last track started for mixer state control
if (--(track->mRetryCount) <= 0) {
- ALOGV("BUFFER TIMEOUT: remove track(%d) from active list", trackId);
- tracksToRemove->add(track);
- // indicate to client process that the track was disabled because of underrun;
- // it will then automatically call start() when data is available
- track->disable();
- // only do hw pause when track is going to be removed due to BUFFER TIMEOUT.
- // unlike mixerthread, HAL can be paused for direct output
- ALOGW("pause because of UNDERRUN, framesReady = %zu,"
- "minFrames = %u, mFormat = %#x",
- framesReady, minFrames, mFormat);
- if (last && mHwSupportsPause && !mHwPaused && !mStandby) {
- doHwPause = true;
- mHwPaused = true;
+ const bool running = checkRunningTimestamp();
+ if (running) { // still running, give us more time.
+ track->mRetryCount = kMaxTrackRetriesOffload;
+ } else {
+ ALOGV("BUFFER TIMEOUT: remove track(%d) from active list", trackId);
+ tracksToRemove->add(track);
+ // indicate to client process that the track was disabled because of
+ // underrun; it will then automatically call start() when data is available
+ track->disable();
+ // only do hw pause when track is going to be removed due to BUFFER TIMEOUT.
+ // unlike mixerthread, HAL can be paused for direct output
+ ALOGW("pause because of UNDERRUN, framesReady = %zu,"
+ "minFrames = %u, mFormat = %#x",
+ framesReady, minFrames, mFormat);
+ if (last && mHwSupportsPause && !mHwPaused && !mStandby) {
+ doHwPause = true;
+ mHwPaused = true;
+ }
}
} else if (last) {
mixerStatus = MIXER_TRACKS_ENABLED;
@@ -6277,6 +6296,7 @@
void AudioFlinger::DirectOutputThread::flushHw_l()
{
+ PlaybackThread::flushHw_l();
mOutput->flush();
mHwPaused = false;
mFlushPending = false;
@@ -6412,8 +6432,7 @@
AudioFlinger::OffloadThread::OffloadThread(const sp<AudioFlinger>& audioFlinger,
AudioStreamOut* output, audio_io_handle_t id, bool systemReady)
: DirectOutputThread(audioFlinger, output, id, OFFLOAD, systemReady),
- mPausedWriteLength(0), mPausedBytesRemaining(0), mKeepWakeLock(true),
- mOffloadUnderrunPosition(~0LL)
+ mPausedWriteLength(0), mPausedBytesRemaining(0), mKeepWakeLock(true)
{
//FIXME: mStandby should be set to true by ThreadBase constructo
mStandby = true;
@@ -6630,19 +6649,7 @@
// No buffers for this track. Give it a few chances to
// fill a buffer, then remove it from active list.
if (--(track->mRetryCount) <= 0) {
- bool running = false;
- uint64_t position = 0;
- struct timespec unused;
- // The running check restarts the retry counter at least once.
- status_t ret = mOutput->stream->getPresentationPosition(&position, &unused);
- if (ret == NO_ERROR && position != mOffloadUnderrunPosition) {
- running = true;
- mOffloadUnderrunPosition = position;
- }
- if (ret == NO_ERROR) {
- ALOGVV("underrun counter, running(%d): %lld vs %lld", running,
- (long long)position, (long long)mOffloadUnderrunPosition);
- }
+ const bool running = checkRunningTimestamp();
if (running) { // still running, give us more time.
track->mRetryCount = kMaxTrackRetriesOffload;
} else {
@@ -6713,7 +6720,6 @@
mPausedBytesRemaining = 0;
// reset bytes written count to reflect that DSP buffers are empty after flush.
mBytesWritten = 0;
- mOffloadUnderrunPosition = ~0LL;
if (mUseAsyncWrite) {
// discard any pending drain or write ack by incrementing sequence
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 16082a9..4ab684f 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1314,6 +1314,14 @@
// audio patch used by the downstream software patch.
// Only used if ThreadBase::mIsMsdDevice is true.
struct audio_patch mDownStreamPatch;
+
+ // A differential check on the timestamps to see if there is a change in the
+ // timestamp frame position between the last call to checkRunningTimestamp.
+ uint64_t mLastCheckedTimestampPosition = ~0LL;
+
+ bool checkRunningTimestamp();
+
+ virtual void flushHw_l() { mLastCheckedTimestampPosition = ~0LL; }
};
class MixerThread : public PlaybackThread {
@@ -1430,7 +1438,7 @@
virtual bool checkForNewParameter_l(const String8& keyValuePair,
status_t& status);
- virtual void flushHw_l();
+ void flushHw_l() override;
void setMasterBalance(float balance) override;
@@ -1495,7 +1503,7 @@
OffloadThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
audio_io_handle_t id, bool systemReady);
virtual ~OffloadThread() {};
- virtual void flushHw_l();
+ void flushHw_l() override;
protected:
// threadLoop snippets
@@ -1512,10 +1520,6 @@
size_t mPausedWriteLength; // length in bytes of write interrupted by pause
size_t mPausedBytesRemaining; // bytes still waiting in mixbuffer after resume
bool mKeepWakeLock; // keep wake lock while waiting for write callback
- uint64_t mOffloadUnderrunPosition; // Current frame position for offloaded playback
- // used and valid only during underrun. ~0 if
- // no underrun has occurred during playback and
- // is not reset on standby.
};
class AsyncCallbackThread : public Thread {
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
index 5a97f4b..b261b52 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
@@ -469,7 +469,7 @@
// Note down the just completed frame number
if (request.hasInputBuffer) {
states.lastCompletedReprocessFrameNumber = frameNumber;
- } else if (request.zslCapture) {
+ } else if (request.zslCapture && request.stillCapture) {
states.lastCompletedZslFrameNumber = frameNumber;
} else {
states.lastCompletedRegularFrameNumber = frameNumber;
@@ -941,7 +941,8 @@
void returnAndRemovePendingOutputBuffers(bool useHalBufManager,
sp<NotificationListener> listener, InFlightRequest& request,
SessionStatsBuilder& sessionStatsBuilder) {
- bool timestampIncreasing = !(request.zslCapture || request.hasInputBuffer);
+ bool timestampIncreasing =
+ !((request.zslCapture && request.stillCapture) || request.hasInputBuffer);
returnOutputBuffers(useHalBufManager, listener,
request.pendingOutputBuffers.array(),
request.pendingOutputBuffers.size(),