Merge "Allow Descrambler.add/removePid to pass a nullable optional filter" into sc-dev
diff --git a/drm/libmediadrm/interface/mediadrm/DrmUtils.h b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
index 988cda9..ec0b878 100644
--- a/drm/libmediadrm/interface/mediadrm/DrmUtils.h
+++ b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
@@ -211,7 +211,7 @@
}
auto allLogs(gLogBuf.getLogs());
- LOG2BI("framework logs size %zu; plugin logs size %zu",
+ LOG2BD("framework logs size %zu; plugin logs size %zu",
allLogs.size(), pluginLogs.size());
std::copy(pluginLogs.begin(), pluginLogs.end(), std::back_inserter(allLogs));
std::sort(allLogs.begin(), allLogs.end(),
diff --git a/media/codec2/components/avc/C2SoftAvcDec.cpp b/media/codec2/components/avc/C2SoftAvcDec.cpp
index e8287f9..f4a6e17 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.cpp
+++ b/media/codec2/components/avc/C2SoftAvcDec.cpp
@@ -22,6 +22,7 @@
#include <C2Debug.h>
#include <C2PlatformSupport.h>
+#include <Codec2BufferUtils.h>
#include <Codec2Mapper.h>
#include <SimpleC2Interface.h>
@@ -331,6 +332,14 @@
free(mem);
}
+static IV_COLOR_FORMAT_T GetIvColorFormat() {
+ static IV_COLOR_FORMAT_T sColorFormat =
+ (GetYuv420FlexibleLayout() == FLEX_LAYOUT_SEMIPLANAR_UV) ? IV_YUV_420SP_UV :
+ (GetYuv420FlexibleLayout() == FLEX_LAYOUT_SEMIPLANAR_VU) ? IV_YUV_420SP_VU :
+ IV_YUV_420P;
+ return sColorFormat;
+}
+
C2SoftAvcDec::C2SoftAvcDec(
const char *name,
c2_node_id_t id,
@@ -339,7 +348,6 @@
mIntf(intfImpl),
mDecHandle(nullptr),
mOutBufferFlush(nullptr),
- mIvColorFormat(IV_YUV_420P),
mOutputDelay(kDefaultOutputDelay),
mWidth(320),
mHeight(240),
@@ -418,7 +426,13 @@
s_create_ip.s_ivd_create_ip_t.u4_size = sizeof(ivdext_create_ip_t);
s_create_ip.s_ivd_create_ip_t.e_cmd = IVD_CMD_CREATE;
s_create_ip.s_ivd_create_ip_t.u4_share_disp_buf = 0;
- s_create_ip.s_ivd_create_ip_t.e_output_format = mIvColorFormat;
+ s_create_ip.s_ivd_create_ip_t.e_output_format = GetIvColorFormat();
+ switch (s_create_ip.s_ivd_create_ip_t.e_output_format) {
+ case IV_YUV_420P: ALOGD("Flex Planar"); break;
+ case IV_YUV_420SP_UV: ALOGD("Flex Semi-planar UV"); break;
+ case IV_YUV_420SP_VU: ALOGD("Flex Semi-planar VU"); break;
+ default: ALOGD("Unknown"); break;
+ }
s_create_ip.s_ivd_create_ip_t.pf_aligned_alloc = ivd_aligned_malloc;
s_create_ip.s_ivd_create_ip_t.pf_aligned_free = ivd_aligned_free;
s_create_ip.s_ivd_create_ip_t.pv_mem_ctxt = nullptr;
@@ -555,8 +569,12 @@
ps_decode_ip->u4_num_Bytes = 0;
}
ps_decode_ip->s_out_buffer.u4_min_out_buf_size[0] = lumaSize;
- ps_decode_ip->s_out_buffer.u4_min_out_buf_size[1] = chromaSize;
- ps_decode_ip->s_out_buffer.u4_min_out_buf_size[2] = chromaSize;
+ if (GetIvColorFormat() == IV_YUV_420P) {
+ ps_decode_ip->s_out_buffer.u4_min_out_buf_size[1] = chromaSize;
+ ps_decode_ip->s_out_buffer.u4_min_out_buf_size[2] = chromaSize;
+ } else {
+ ps_decode_ip->s_out_buffer.u4_min_out_buf_size[1] = chromaSize * 2;
+ }
if (outBuffer) {
if (outBuffer->height() < displayHeight) {
ALOGE("Output buffer too small: provided (%dx%d) required (%ux%u)",
@@ -565,13 +583,23 @@
}
ps_decode_ip->s_out_buffer.pu1_bufs[0] = outBuffer->data()[C2PlanarLayout::PLANE_Y];
ps_decode_ip->s_out_buffer.pu1_bufs[1] = outBuffer->data()[C2PlanarLayout::PLANE_U];
- ps_decode_ip->s_out_buffer.pu1_bufs[2] = outBuffer->data()[C2PlanarLayout::PLANE_V];
+ if (GetIvColorFormat() == IV_YUV_420P) {
+ ps_decode_ip->s_out_buffer.pu1_bufs[2] = outBuffer->data()[C2PlanarLayout::PLANE_V];
+ } else if (GetIvColorFormat() == IV_YUV_420SP_VU) {
+ ps_decode_ip->s_out_buffer.pu1_bufs[1] = outBuffer->data()[C2PlanarLayout::PLANE_V];
+ }
} else {
ps_decode_ip->s_out_buffer.pu1_bufs[0] = mOutBufferFlush;
ps_decode_ip->s_out_buffer.pu1_bufs[1] = mOutBufferFlush + lumaSize;
- ps_decode_ip->s_out_buffer.pu1_bufs[2] = mOutBufferFlush + lumaSize + chromaSize;
+ if (GetIvColorFormat() == IV_YUV_420P) {
+ ps_decode_ip->s_out_buffer.pu1_bufs[2] = mOutBufferFlush + lumaSize + chromaSize;
+ }
}
- ps_decode_ip->s_out_buffer.u4_num_bufs = 3;
+ if (GetIvColorFormat() == IV_YUV_420P) {
+ ps_decode_ip->s_out_buffer.u4_num_bufs = 3;
+ } else {
+ ps_decode_ip->s_out_buffer.u4_num_bufs = 2;
+ }
ps_decode_op->u4_size = sizeof(ih264d_video_decode_op_t);
return true;
@@ -781,7 +809,7 @@
mOutBlock.reset();
}
if (!mOutBlock) {
- uint32_t format = HAL_PIXEL_FORMAT_YV12;
+ uint32_t format = HAL_PIXEL_FORMAT_YCBCR_420_888;
C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
c2_status_t err =
pool->fetchGraphicBlock(ALIGN32(mWidth), mHeight, format, usage, &mOutBlock);
@@ -797,8 +825,6 @@
}
// TODO: can overall error checking be improved?
-// TODO: allow configuration of color format and usage for graphic buffers instead
-// of hard coding them to HAL_PIXEL_FORMAT_YV12
// TODO: pass coloraspects information to surface
// TODO: test support for dynamic change in resolution
// TODO: verify if the decoder sent back all frames
diff --git a/media/codec2/components/avc/C2SoftAvcDec.h b/media/codec2/components/avc/C2SoftAvcDec.h
index 5c07d29..ed99ad1 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.h
+++ b/media/codec2/components/avc/C2SoftAvcDec.h
@@ -155,7 +155,6 @@
uint8_t *mOutBufferFlush;
size_t mNumCores;
- IV_COLOR_FORMAT_T mIvColorFormat;
uint32_t mOutputDelay;
uint32_t mWidth;
uint32_t mHeight;
diff --git a/media/codec2/components/avc/C2SoftAvcEnc.cpp b/media/codec2/components/avc/C2SoftAvcEnc.cpp
index bab651f..fc5b75d 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.cpp
+++ b/media/codec2/components/avc/C2SoftAvcEnc.cpp
@@ -454,11 +454,19 @@
} // namespace
+static IV_COLOR_FORMAT_T GetIvColorFormat() {
+ static IV_COLOR_FORMAT_T sColorFormat =
+ (GetYuv420FlexibleLayout() == FLEX_LAYOUT_SEMIPLANAR_UV) ? IV_YUV_420SP_UV :
+ (GetYuv420FlexibleLayout() == FLEX_LAYOUT_SEMIPLANAR_VU) ? IV_YUV_420SP_VU :
+ IV_YUV_420P;
+ return sColorFormat;
+}
+
C2SoftAvcEnc::C2SoftAvcEnc(
const char *name, c2_node_id_t id, const std::shared_ptr<IntfImpl> &intfImpl)
: SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
mIntf(intfImpl),
- mIvVideoColorFormat(IV_YUV_420P),
+ mIvVideoColorFormat(GetIvColorFormat()),
mAVCEncProfile(IV_PROFILE_BASE),
mAVCEncLevel(41),
mStarted(false),
@@ -1026,8 +1034,7 @@
// Assume worst case output buffer size to be equal to number of bytes in input
mOutBufferSize = std::max(width * height * 3 / 2, kMinOutBufferSize);
- // TODO
- mIvVideoColorFormat = IV_YUV_420P;
+ mIvVideoColorFormat = GetIvColorFormat();
ALOGD("Params width %d height %d level %d colorFormat %d bframes %d", width,
height, mAVCEncLevel, mIvVideoColorFormat, mBframes);
@@ -1325,7 +1332,6 @@
mSize->width, input->height(), mSize->height);
return C2_BAD_VALUE;
}
- ALOGV("width = %d, height = %d", input->width(), input->height());
const C2PlanarLayout &layout = input->layout();
uint8_t *yPlane = const_cast<uint8_t *>(input->data()[C2PlanarLayout::PLANE_Y]);
uint8_t *uPlane = const_cast<uint8_t *>(input->data()[C2PlanarLayout::PLANE_U]);
@@ -1362,7 +1368,8 @@
return C2_BAD_VALUE;
}
- if (layout.planes[layout.PLANE_Y].colInc == 1
+ if (mIvVideoColorFormat == IV_YUV_420P
+ && layout.planes[layout.PLANE_Y].colInc == 1
&& layout.planes[layout.PLANE_U].colInc == 1
&& layout.planes[layout.PLANE_V].colInc == 1
&& uStride == vStride
@@ -1370,21 +1377,61 @@
// I420 compatible - already set up above
break;
}
+ if (mIvVideoColorFormat == IV_YUV_420SP_UV
+ && layout.planes[layout.PLANE_Y].colInc == 1
+ && layout.planes[layout.PLANE_U].colInc == 2
+ && layout.planes[layout.PLANE_V].colInc == 2
+ && uStride == vStride
+ && yStride == vStride
+ && uPlane + 1 == vPlane) {
+ // NV12 compatible - already set up above
+ break;
+ }
+ if (mIvVideoColorFormat == IV_YUV_420SP_VU
+ && layout.planes[layout.PLANE_Y].colInc == 1
+ && layout.planes[layout.PLANE_U].colInc == 2
+ && layout.planes[layout.PLANE_V].colInc == 2
+ && uStride == vStride
+ && yStride == vStride
+ && uPlane == vPlane + 1) {
+ // NV21 compatible - already set up above
+ break;
+ }
// copy to I420
yStride = width;
uStride = vStride = yStride / 2;
MemoryBlock conversionBuffer = mConversionBuffers.fetch(yPlaneSize * 3 / 2);
mConversionBuffersInUse.emplace(conversionBuffer.data(), conversionBuffer);
- MediaImage2 img = CreateYUV420PlanarMediaImage2(width, height, yStride, height);
+ MediaImage2 img;
+ switch (mIvVideoColorFormat) {
+ case IV_YUV_420P:
+ img = CreateYUV420PlanarMediaImage2(width, height, yStride, height);
+ yPlane = conversionBuffer.data();
+ uPlane = yPlane + yPlaneSize;
+ vPlane = uPlane + yPlaneSize / 4;
+ break;
+ case IV_YUV_420SP_VU:
+ img = CreateYUV420SemiPlanarMediaImage2(width, height, yStride, height);
+ img.mPlane[MediaImage2::U].mOffset++;
+ img.mPlane[MediaImage2::V].mOffset--;
+ yPlane = conversionBuffer.data();
+ vPlane = yPlane + yPlaneSize;
+ uPlane = vPlane + 1;
+ break;
+ case IV_YUV_420SP_UV:
+ default:
+ img = CreateYUV420SemiPlanarMediaImage2(width, height, yStride, height);
+ yPlane = conversionBuffer.data();
+ uPlane = yPlane + yPlaneSize;
+ vPlane = uPlane + 1;
+ break;
+ }
status_t err = ImageCopy(conversionBuffer.data(), &img, *input);
if (err != OK) {
ALOGE("Buffer conversion failed: %d", err);
return C2_BAD_VALUE;
}
- yPlane = conversionBuffer.data();
- uPlane = yPlane + yPlaneSize;
- vPlane = uPlane + yPlaneSize / 4;
break;
}
@@ -1430,15 +1477,17 @@
break;
}
- case IV_YUV_420SP_UV:
case IV_YUV_420SP_VU:
+ uPlane = vPlane;
+ [[fallthrough]];
+ case IV_YUV_420SP_UV:
default:
{
ps_inp_raw_buf->apv_bufs[0] = yPlane;
ps_inp_raw_buf->apv_bufs[1] = uPlane;
ps_inp_raw_buf->au4_wd[0] = mSize->width;
- ps_inp_raw_buf->au4_wd[1] = mSize->width;
+ ps_inp_raw_buf->au4_wd[1] = mSize->width / 2;
ps_inp_raw_buf->au4_ht[0] = mSize->height;
ps_inp_raw_buf->au4_ht[1] = mSize->height / 2;
diff --git a/media/codec2/hidl/plugin/FilterWrapper.cpp b/media/codec2/hidl/plugin/FilterWrapper.cpp
index 0b38bc1..bed8aeb 100644
--- a/media/codec2/hidl/plugin/FilterWrapper.cpp
+++ b/media/codec2/hidl/plugin/FilterWrapper.cpp
@@ -19,7 +19,6 @@
#include <android-base/logging.h>
#include <set>
-#include <sstream>
#include <dlfcn.h>
@@ -383,6 +382,9 @@
// Configure the next interface with the params.
std::vector<C2Param *> configParams;
for (size_t i = 0; i < heapParams.size(); ++i) {
+ if (!heapParams[i]) {
+ continue;
+ }
if (heapParams[i]->forStream()) {
heapParams[i] = C2Param::CopyAsStream(
*heapParams[i], false /* output */, heapParams[i]->stream());
@@ -782,10 +784,7 @@
if (C2_OK != mStore->createComponent(filter.traits.name, &comp)) {
return {};
}
- if (C2_OK != mStore->createInterface(filter.traits.name, &intf)) {
- return {};
- }
- filters.push_back({comp, intf, filter.traits, filter.desc});
+ filters.push_back({comp, comp->intf(), filter.traits, filter.desc});
}
return filters;
}
@@ -869,7 +868,7 @@
}
std::vector<Component> filters = createFilters();
std::shared_ptr wrapped = std::make_shared<WrappedDecoder>(
- comp, std::move(filters), weak_from_this());
+ comp, std::vector(filters), weak_from_this());
{
std::unique_lock lock(mWrappedComponentsMutex);
std::vector<std::weak_ptr<const C2Component>> &components =
diff --git a/media/codec2/sfplugin/utils/Android.bp b/media/codec2/sfplugin/utils/Android.bp
index 74e7ef1..2f4d6b1 100644
--- a/media/codec2/sfplugin/utils/Android.bp
+++ b/media/codec2/sfplugin/utils/Android.bp
@@ -33,11 +33,13 @@
"libcodec2_vndk",
"libcutils",
"liblog",
+ "libnativewindow",
"libstagefright_foundation",
"libutils",
],
static_libs: [
+ "libarect",
"libyuv_static",
],
diff --git a/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp b/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
index a54af83..a78d811 100644
--- a/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
+++ b/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
@@ -23,6 +23,7 @@
#include <list>
#include <mutex>
+#include <android/hardware_buffer.h>
#include <media/hardware/HardwareAPI.h>
#include <media/stagefright/foundation/AUtils.h>
@@ -136,31 +137,56 @@
int width = view.crop().width;
int height = view.crop().height;
- if ((IsNV12(view) && IsI420(img)) || (IsI420(view) && IsNV12(img))) {
- // Take shortcuts to use libyuv functions between NV12 and I420 conversion.
- if (IsNV12(view) && IsI420(img)) {
+ if (IsNV12(view)) {
+ if (IsNV12(img)) {
+ libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
+ libyuv::CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width, height / 2);
+ return OK;
+ } else if (IsNV21(img)) {
+ if (!libyuv::NV21ToNV12(src_y, src_stride_y, src_u, src_stride_u,
+ dst_y, dst_stride_y, dst_v, dst_stride_v, width, height)) {
+ return OK;
+ }
+ } else if (IsI420(img)) {
if (!libyuv::NV12ToI420(src_y, src_stride_y, src_u, src_stride_u, dst_y, dst_stride_y,
dst_u, dst_stride_u, dst_v, dst_stride_v, width, height)) {
return OK;
}
- } else {
+ }
+ } else if (IsNV21(view)) {
+ if (IsNV12(img)) {
+ if (!libyuv::NV21ToNV12(src_y, src_stride_y, src_v, src_stride_v,
+ dst_y, dst_stride_y, dst_u, dst_stride_u, width, height)) {
+ return OK;
+ }
+ } else if (IsNV21(img)) {
+ libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
+ libyuv::CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, width, height / 2);
+ return OK;
+ } else if (IsI420(img)) {
+ if (!libyuv::NV21ToI420(src_y, src_stride_y, src_v, src_stride_v, dst_y, dst_stride_y,
+ dst_u, dst_stride_u, dst_v, dst_stride_v, width, height)) {
+ return OK;
+ }
+ }
+ } else if (IsI420(view)) {
+ if (IsNV12(img)) {
if (!libyuv::I420ToNV12(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
dst_y, dst_stride_y, dst_u, dst_stride_u, width, height)) {
return OK;
}
+ } else if (IsNV21(img)) {
+ if (!libyuv::I420ToNV21(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
+ dst_y, dst_stride_y, dst_v, dst_stride_v, width, height)) {
+ return OK;
+ }
+ } else if (IsI420(img)) {
+ libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
+ libyuv::CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width / 2, height / 2);
+ libyuv::CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, width / 2, height / 2);
+ return OK;
}
}
- if (IsNV12(view) && IsNV12(img)) {
- libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
- libyuv::CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width, height / 2);
- return OK;
- }
- if (IsI420(view) && IsI420(img)) {
- libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
- libyuv::CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width / 2, height / 2);
- libyuv::CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, width / 2, height / 2);
- return OK;
- }
return _ImageCopy<true>(view, img, imgBase);
}
@@ -182,33 +208,56 @@
int32_t dst_stride_v = view.layout().planes[2].rowInc;
int width = view.crop().width;
int height = view.crop().height;
- if ((IsNV12(img) && IsI420(view)) || (IsI420(img) && IsNV12(view))) {
- // Take shortcuts to use libyuv functions between NV12 and I420 conversion.
- if (IsNV12(img) && IsI420(view)) {
+ if (IsNV12(img)) {
+ if (IsNV12(view)) {
+ libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
+ libyuv::CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width, height / 2);
+ return OK;
+ } else if (IsNV21(view)) {
+ if (!libyuv::NV21ToNV12(src_y, src_stride_y, src_u, src_stride_u,
+ dst_y, dst_stride_y, dst_v, dst_stride_v, width, height)) {
+ return OK;
+ }
+ } else if (IsI420(view)) {
if (!libyuv::NV12ToI420(src_y, src_stride_y, src_u, src_stride_u, dst_y, dst_stride_y,
dst_u, dst_stride_u, dst_v, dst_stride_v, width, height)) {
return OK;
}
- } else {
+ }
+ } else if (IsNV21(img)) {
+ if (IsNV12(view)) {
+ if (!libyuv::NV21ToNV12(src_y, src_stride_y, src_v, src_stride_v,
+ dst_y, dst_stride_y, dst_u, dst_stride_u, width, height)) {
+ return OK;
+ }
+ } else if (IsNV21(view)) {
+ libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
+ libyuv::CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, width, height / 2);
+ return OK;
+ } else if (IsI420(view)) {
+ if (!libyuv::NV21ToI420(src_y, src_stride_y, src_v, src_stride_v, dst_y, dst_stride_y,
+ dst_u, dst_stride_u, dst_v, dst_stride_v, width, height)) {
+ return OK;
+ }
+ }
+ } else if (IsI420(img)) {
+ if (IsNV12(view)) {
if (!libyuv::I420ToNV12(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
dst_y, dst_stride_y, dst_u, dst_stride_u, width, height)) {
return OK;
}
+ } else if (IsNV21(view)) {
+ if (!libyuv::I420ToNV21(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
+ dst_y, dst_stride_y, dst_v, dst_stride_v, width, height)) {
+ return OK;
+ }
+ } else if (IsI420(view)) {
+ libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
+ libyuv::CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width / 2, height / 2);
+ libyuv::CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, width / 2, height / 2);
+ return OK;
}
}
- if (IsNV12(img) && IsNV12(view)) {
- // For NV12, copy Y and UV plane
- libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
- libyuv::CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width, height / 2);
- return OK;
- }
- if (IsI420(img) && IsI420(view)) {
- // For I420, copy Y, U and V plane.
- libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
- libyuv::CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width / 2, height / 2);
- libyuv::CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, width / 2, height / 2);
- return OK;
- }
return _ImageCopy<false>(view, img, imgBase);
}
@@ -250,6 +299,20 @@
&& layout.planes[layout.PLANE_V].offset == 1);
}
+bool IsNV21(const C2GraphicView &view) {
+ if (!IsYUV420(view)) {
+ return false;
+ }
+ const C2PlanarLayout &layout = view.layout();
+ return (layout.rootPlanes == 2
+ && layout.planes[layout.PLANE_U].colInc == 2
+ && layout.planes[layout.PLANE_U].rootIx == layout.PLANE_V
+ && layout.planes[layout.PLANE_U].offset == 1
+ && layout.planes[layout.PLANE_V].colInc == 2
+ && layout.planes[layout.PLANE_V].rootIx == layout.PLANE_V
+ && layout.planes[layout.PLANE_V].offset == 0);
+}
+
bool IsI420(const C2GraphicView &view) {
if (!IsYUV420(view)) {
return false;
@@ -286,6 +349,15 @@
&& (img->mPlane[2].mOffset - img->mPlane[1].mOffset == 1));
}
+bool IsNV21(const MediaImage2 *img) {
+ if (!IsYUV420(img)) {
+ return false;
+ }
+ return (img->mPlane[1].mColInc == 2
+ && img->mPlane[2].mColInc == 2
+ && (img->mPlane[1].mOffset - img->mPlane[2].mOffset == 1));
+}
+
bool IsI420(const MediaImage2 *img) {
if (!IsYUV420(img)) {
return false;
@@ -295,6 +367,76 @@
&& img->mPlane[2].mOffset > img->mPlane[1].mOffset);
}
+FlexLayout GetYuv420FlexibleLayout() {
+ static FlexLayout sLayout = []{
+ AHardwareBuffer_Desc desc = {
+ 16, // width
+ 16, // height
+ 1, // layers
+ AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420,
+ AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN,
+ 0, // stride
+ 0, // rfu0
+ 0, // rfu1
+ };
+ AHardwareBuffer *buffer = nullptr;
+ int ret = AHardwareBuffer_allocate(&desc, &buffer);
+ if (ret != 0) {
+ return FLEX_LAYOUT_UNKNOWN;
+ }
+ class AutoCloser {
+ public:
+ AutoCloser(AHardwareBuffer *buffer) : mBuffer(buffer), mLocked(false) {}
+ ~AutoCloser() {
+ if (mLocked) {
+ AHardwareBuffer_unlock(mBuffer, nullptr);
+ }
+ AHardwareBuffer_release(mBuffer);
+ }
+
+ void setLocked() { mLocked = true; }
+
+ private:
+ AHardwareBuffer *mBuffer;
+ bool mLocked;
+ } autoCloser(buffer);
+ AHardwareBuffer_Planes planes;
+ ret = AHardwareBuffer_lockPlanes(
+ buffer,
+ AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN,
+ -1, // fence
+ nullptr, // rect
+ &planes);
+ if (ret != 0) {
+ AHardwareBuffer_release(buffer);
+ return FLEX_LAYOUT_UNKNOWN;
+ }
+ autoCloser.setLocked();
+ if (planes.planeCount != 3) {
+ return FLEX_LAYOUT_UNKNOWN;
+ }
+ if (planes.planes[0].pixelStride != 1) {
+ return FLEX_LAYOUT_UNKNOWN;
+ }
+ if (planes.planes[1].pixelStride == 1 && planes.planes[2].pixelStride == 1) {
+ return FLEX_LAYOUT_PLANAR;
+ }
+ if (planes.planes[1].pixelStride == 2 && planes.planes[2].pixelStride == 2) {
+ ssize_t uvDist =
+ static_cast<uint8_t *>(planes.planes[2].data) -
+ static_cast<uint8_t *>(planes.planes[1].data);
+ if (uvDist == 1) {
+ return FLEX_LAYOUT_SEMIPLANAR_UV;
+ } else if (uvDist == -1) {
+ return FLEX_LAYOUT_SEMIPLANAR_VU;
+ }
+ return FLEX_LAYOUT_UNKNOWN;
+ }
+ return FLEX_LAYOUT_UNKNOWN;
+ }();
+ return sLayout;
+}
+
MediaImage2 CreateYUV420PlanarMediaImage2(
uint32_t width, uint32_t height, uint32_t stride, uint32_t vstride) {
return MediaImage2 {
diff --git a/media/codec2/sfplugin/utils/Codec2BufferUtils.h b/media/codec2/sfplugin/utils/Codec2BufferUtils.h
index afadf00..af29e81 100644
--- a/media/codec2/sfplugin/utils/Codec2BufferUtils.h
+++ b/media/codec2/sfplugin/utils/Codec2BufferUtils.h
@@ -96,6 +96,11 @@
bool IsNV12(const C2GraphicView &view);
/**
+ * Returns true iff a view has a NV21 layout.
+ */
+bool IsNV21(const C2GraphicView &view);
+
+/**
* Returns true iff a view has a I420 layout.
*/
bool IsI420(const C2GraphicView &view);
@@ -111,10 +116,26 @@
bool IsNV12(const MediaImage2 *img);
/**
+ * Returns true iff a MediaImage2 has a NV21 layout.
+ */
+bool IsNV21(const MediaImage2 *img);
+
+/**
* Returns true iff a MediaImage2 has a I420 layout.
*/
bool IsI420(const MediaImage2 *img);
+enum FlexLayout {
+ FLEX_LAYOUT_UNKNOWN,
+ FLEX_LAYOUT_PLANAR,
+ FLEX_LAYOUT_SEMIPLANAR_UV,
+ FLEX_LAYOUT_SEMIPLANAR_VU,
+};
+/**
+ * Returns layout of YCBCR_420_888 pixel format.
+ */
+FlexLayout GetYuv420FlexibleLayout();
+
/**
* A raw memory block to use for internal buffers.
*
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 6385bac..b1d72e8 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -2345,7 +2345,7 @@
if (mLastTrack == NULL)
return ERROR_MALFORMED;
- AMediaFormat_setBuffer(mLastTrack->meta,
+ AMediaFormat_setBuffer(mLastTrack->meta,
AMEDIAFORMAT_KEY_ESDS, &buffer[4], chunk_data_size - 4);
if (mPath.size() >= 2
@@ -2427,7 +2427,7 @@
if (mLastTrack == NULL)
return ERROR_MALFORMED;
- AMediaFormat_setBuffer(mLastTrack->meta,
+ AMediaFormat_setBuffer(mLastTrack->meta,
AMEDIAFORMAT_KEY_CSD_AVC, buffer.get(), chunk_data_size);
break;
@@ -2449,7 +2449,7 @@
if (mLastTrack == NULL)
return ERROR_MALFORMED;
- AMediaFormat_setBuffer(mLastTrack->meta,
+ AMediaFormat_setBuffer(mLastTrack->meta,
AMEDIAFORMAT_KEY_CSD_HEVC, buffer.get(), chunk_data_size);
*offset += chunk_size;
@@ -4021,13 +4021,13 @@
// custom genre string
buffer[size] = '\0';
- AMediaFormat_setString(mFileMetaData,
+ AMediaFormat_setString(mFileMetaData,
metadataKey, (const char *)buffer + 8);
}
} else {
buffer[size] = '\0';
- AMediaFormat_setString(mFileMetaData,
+ AMediaFormat_setString(mFileMetaData,
metadataKey, (const char *)buffer + 8);
}
}
@@ -6194,9 +6194,13 @@
if (newBuffer) {
if (mIsPcm) {
// The twos' PCM block reader assumes that all samples has the same size.
-
- uint32_t samplesToRead = mSampleTable->getLastSampleIndexInChunk()
- - mCurrentSampleIndex + 1;
+ uint32_t lastSampleIndexInChunk = mSampleTable->getLastSampleIndexInChunk();
+ if (lastSampleIndexInChunk < mCurrentSampleIndex) {
+ mBuffer->release();
+ mBuffer = nullptr;
+ return AMEDIA_ERROR_UNKNOWN;
+ }
+ uint32_t samplesToRead = lastSampleIndexInChunk - mCurrentSampleIndex + 1;
if (samplesToRead > kMaxPcmFrameSize) {
samplesToRead = kMaxPcmFrameSize;
}
@@ -6205,13 +6209,17 @@
samplesToRead, size, mCurrentSampleIndex,
mSampleTable->getLastSampleIndexInChunk());
- size_t totalSize = samplesToRead * size;
+ size_t totalSize = samplesToRead * size;
+ if (mBuffer->size() < totalSize) {
+ mBuffer->release();
+ mBuffer = nullptr;
+ return AMEDIA_ERROR_UNKNOWN;
+ }
uint8_t* buf = (uint8_t *)mBuffer->data();
ssize_t bytesRead = mDataSource->readAt(offset, buf, totalSize);
if (bytesRead < (ssize_t)totalSize) {
mBuffer->release();
mBuffer = NULL;
-
return AMEDIA_ERROR_IO;
}
diff --git a/media/libmediaformatshaper/CodecProperties.cpp b/media/libmediaformatshaper/CodecProperties.cpp
index 961f676..e6b3c46 100644
--- a/media/libmediaformatshaper/CodecProperties.cpp
+++ b/media/libmediaformatshaper/CodecProperties.cpp
@@ -23,6 +23,10 @@
#include <media/formatshaper/CodecProperties.h>
+
+// we aren't going to mess with shaping points dimensions beyond this
+static const int32_t DIMENSION_LIMIT = 16384;
+
namespace android {
namespace mediaformatshaper {
@@ -113,7 +117,13 @@
setBpp(bpp);
legal = true;
}
+ } else if (!strncmp(key.c_str(), "vq-target-bpp-", strlen("vq-target-bpp-"))) {
+ std::string resolution = key.substr(strlen("vq-target-bpp-"));
+ if (bppPoint(resolution, value)) {
+ legal = true;
+ }
} else if (!strcmp(key.c_str(), "vq-target-bppx100")) {
+ // legacy, prototyping
const char *p = value.c_str();
char *q;
int32_t iValue = strtol(p, &q, 0);
@@ -143,6 +153,119 @@
return false;
}
+bool CodecProperties::bppPoint(std::string resolution, std::string value) {
+
+ int32_t width = 0;
+ int32_t height = 0;
+ double bpp = -1;
+
+ // resolution is "WxH", "W*H" or a standard name like "720p"
+ if (resolution == "1080p") {
+ width = 1080; height = 1920;
+ } else if (resolution == "720p") {
+ width = 720; height = 1280;
+ } else if (resolution == "540p") {
+ width = 540; height = 960;
+ } else if (resolution == "480p") {
+ width = 480; height = 854;
+ } else {
+ size_t sep = resolution.find('x');
+ if (sep == std::string::npos) {
+ sep = resolution.find('*');
+ }
+ if (sep == std::string::npos) {
+ ALOGW("unable to parse resolution: '%s'", resolution.c_str());
+ return false;
+ }
+ std::string w = resolution.substr(0, sep);
+ std::string h = resolution.substr(sep+1);
+
+ char *q;
+ const char *p = w.c_str();
+ width = strtol(p, &q, 0);
+ if (q == p) {
+ width = -1;
+ }
+ p = h.c_str();
+ height = strtol(p, &q, 0);
+ if (q == p) {
+ height = -1;
+ }
+ if (width <= 0 || height <= 0 || width > DIMENSION_LIMIT || height > DIMENSION_LIMIT) {
+ ALOGW("unparseable: width, height '%s'", resolution.c_str());
+ return false;
+ }
+ }
+
+ const char *p = value.c_str();
+ char *q;
+ bpp = strtod(p, &q);
+ if (q == p) {
+ ALOGW("unparseable bpp '%s'", value.c_str());
+ return false;
+ }
+
+ struct bpp_point *point = (struct bpp_point*) malloc(sizeof(*point));
+ if (point == nullptr) {
+ ALOGW("unable to allocate memory for bpp point");
+ return false;
+ }
+
+ point->pixels = width * height;
+ point->width = width;
+ point->height = height;
+ point->bpp = bpp;
+
+ if (mBppPoints == nullptr) {
+ point->next = nullptr;
+ mBppPoints = point;
+ } else if (point->pixels < mBppPoints->pixels) {
+ // at the front
+ point->next = mBppPoints;
+ mBppPoints = point;
+ } else {
+ struct bpp_point *after = mBppPoints;
+ while (after->next) {
+ if (point->pixels > after->next->pixels) {
+ after = after->next;
+ continue;
+ }
+
+ // insert before after->next
+ point->next = after->next;
+ after->next = point;
+ break;
+ }
+ if (after->next == nullptr) {
+ // hasn't gone in yet
+ point->next = nullptr;
+ after->next = point;
+ }
+ }
+
+ return true;
+}
+
+double CodecProperties::getBpp(int32_t width, int32_t height) {
+ // look in the per-resolution list
+
+ int32_t pixels = width * height;
+
+ if (mBppPoints) {
+ struct bpp_point *point = mBppPoints;
+ while (point && point->pixels < pixels) {
+ point = point->next;
+ }
+ if (point) {
+ ALOGV("getBpp(w=%d,h=%d) returns %f from bpppoint w=%d h=%d",
+ width, height, point->bpp, point->width, point->height);
+ return point->bpp;
+ }
+ }
+
+ ALOGV("defaulting to %f bpp", mBpp);
+ return mBpp;
+}
std::string CodecProperties::getMapping(std::string key, std::string kind) {
ALOGV("getMapping(key %s, kind %s )", key.c_str(), kind.c_str());
diff --git a/media/libmediaformatshaper/CodecSeeding.cpp b/media/libmediaformatshaper/CodecSeeding.cpp
index fde7833..a7fcc66 100644
--- a/media/libmediaformatshaper/CodecSeeding.cpp
+++ b/media/libmediaformatshaper/CodecSeeding.cpp
@@ -50,13 +50,16 @@
static preloadTuning_t featuresAvc[] = {
{true, "vq-target-bpp", "2.45"},
- {true, "vq-target-qpmax", "41"},
+ {true, "vq-target-bpp-1080p", "2.40"},
+ {true, "vq-target-bpp-540p", "2.60"},
+ {true, "vq-target-bpp-480p", "3.00"},
+ {true, "vq-target-qpmax", "40"},
{true, nullptr, 0}
};
static preloadTuning_t featuresHevc[] = {
{true, "vq-target-bpp", "2.30"},
- {true, "vq-target-qpmax", "42"}, // nop, since hevc codecs don't declare qp support
+ {true, "vq-target-qpmax", "40"}, // nop, since hevc codecs don't declare qp support
{true, nullptr, 0}
};
diff --git a/media/libmediaformatshaper/VQApply.cpp b/media/libmediaformatshaper/VQApply.cpp
index 39a5e19..08e23cc 100644
--- a/media/libmediaformatshaper/VQApply.cpp
+++ b/media/libmediaformatshaper/VQApply.cpp
@@ -48,6 +48,15 @@
//
static const int BITRATE_MODE_VBR = 1;
+
+// constants we use within the calculations
+//
+constexpr double BITRATE_LEAVE_UNTOUCHED = 2.0;
+constexpr double BITRATE_QP_UNAVAILABLE = 1.20;
+// 10% didn't work so hot on bonito (with no QP support)
+// 15% is next.. still leaves a few short
+// 20% ? this is on the edge of what I want do do
+
//
// Caller retains ownership of and responsibility for inFormat
//
@@ -69,69 +78,82 @@
}
//
- // apply any and all tools that we have.
+ // consider any and all tools available
// -- qp
// -- minimum bits-per-pixel
//
- if (!codec->supportsQp()) {
- ALOGD("minquality: no qp bounding in codec %s", codec->getName().c_str());
- } else {
- // use a (configurable) QP value to force better quality
- //
+ int64_t bitrateChosen = 0;
+ int32_t qpChosen = INT32_MAX;
+
+ int64_t bitrateConfigured = 0;
+ int32_t bitrateConfiguredTmp = 0;
+ (void) AMediaFormat_getInt32(inFormat, AMEDIAFORMAT_KEY_BIT_RATE, &bitrateConfiguredTmp);
+ bitrateConfigured = bitrateConfiguredTmp;
+ bitrateChosen = bitrateConfigured;
+
+ int32_t width = 0;
+ (void) AMediaFormat_getInt32(inFormat, AMEDIAFORMAT_KEY_WIDTH, &width);
+ int32_t height = 0;
+ (void) AMediaFormat_getInt32(inFormat, AMEDIAFORMAT_KEY_HEIGHT, &height);
+ int64_t pixels = ((int64_t)width) * height;
+ double minimumBpp = codec->getBpp(width, height);
+
+ int64_t bitrateFloor = pixels * minimumBpp;
+ if (bitrateFloor > INT32_MAX) bitrateFloor = INT32_MAX;
+
+ // if we are far enough above the target bpp, leave it alone
+ //
+ ALOGV("bitrate: configured %" PRId64 " floor %" PRId64, bitrateConfigured, bitrateFloor);
+ if (bitrateConfigured >= BITRATE_LEAVE_UNTOUCHED * bitrateFloor) {
+ ALOGV("high enough bitrate: configured %" PRId64 " >= %f * floor %" PRId64,
+ bitrateConfigured, BITRATE_LEAVE_UNTOUCHED, bitrateFloor);
+ return 0;
+ }
+
+ // raise anything below the bitrate floor
+ if (bitrateConfigured < bitrateFloor) {
+ ALOGD("raise bitrate: configured %" PRId64 " to floor %" PRId64,
+ bitrateConfigured, bitrateFloor);
+ bitrateChosen = bitrateFloor;
+ }
+
+ bool qpPresent = hasQp(inFormat);
+
+ // add QP, if not already present
+ if (!qpPresent) {
int32_t qpmax = codec->targetQpMax();
- int32_t qpmaxUser = INT32_MAX;
- if (hasQp(inFormat)) {
- (void) AMediaFormat_getInt32(inFormat, AMEDIAFORMAT_VIDEO_QP_MAX, &qpmaxUser);
- ALOGD("minquality by QP: format already sets QP");
- }
-
- // if the system didn't do one, use what the user provided
- if (qpmax == 0 && qpmaxUser != INT32_MAX) {
- qpmax = qpmaxUser;
- }
- // XXX: if both said something, how do we want to reconcile that
-
- if (qpmax > 0) {
- ALOGD("minquality by QP: inject %s=%d", AMEDIAFORMAT_VIDEO_QP_MAX, qpmax);
- AMediaFormat_setInt32(inFormat, AMEDIAFORMAT_VIDEO_QP_MAX, qpmax);
-
- // force spreading the QP across frame types, since we imposing a value
- qpSpreadMaxPerFrameType(inFormat, info->qpDelta, info->qpMax, /* override */ true);
+ if (qpmax != INT32_MAX) {
+ ALOGV("choosing qp=%d", qpmax);
+ qpChosen = qpmax;
}
}
- double bpp = codec->getBpp();
- if (bpp > 0.0) {
- // if we've decided to use bits-per-pixel (per second) to drive the quality
- //
- // (properly phrased as 'bits per second per pixel' so that it's resolution
- // and framerate agnostic
- //
- // all of these is structured so that a missing value cleanly gets us to a
- // non-faulting value of '0' for the minimum bits-per-pixel.
- //
- int32_t width = 0;
- (void) AMediaFormat_getInt32(inFormat, AMEDIAFORMAT_KEY_WIDTH, &width);
- int32_t height = 0;
- (void) AMediaFormat_getInt32(inFormat, AMEDIAFORMAT_KEY_HEIGHT, &height);
- int32_t bitrateConfigured = 0;
- (void) AMediaFormat_getInt32(inFormat, AMEDIAFORMAT_KEY_BIT_RATE, &bitrateConfigured);
-
- int64_t pixels = ((int64_t)width) * height;
- int64_t bitrateFloor = pixels * bpp;
-
- if (bitrateFloor > INT32_MAX) bitrateFloor = INT32_MAX;
-
- ALOGD("minquality/bitrate: target %d floor %" PRId64 "(%.3f bpp * (%d w * %d h)",
- bitrateConfigured, bitrateFloor, codec->getBpp(), height, width);
-
- if (bitrateConfigured < bitrateFloor) {
- ALOGD("minquality/target bitrate raised from %d to %" PRId64 " bps",
- bitrateConfigured, bitrateFloor);
- AMediaFormat_setInt32(inFormat, AMEDIAFORMAT_KEY_BIT_RATE, (int32_t)bitrateFloor);
+ // if QP is desired but not supported, compensate with additional bits
+ if (!codec->supportsQp()) {
+ if (qpPresent || qpChosen != INT32_MAX) {
+ ALOGD("minquality: desired QP, but unsupported, boost bitrate %" PRId64 " to %" PRId64,
+ bitrateChosen, (int64_t)(bitrateChosen * BITRATE_QP_UNAVAILABLE));
+ bitrateChosen = bitrateChosen * BITRATE_QP_UNAVAILABLE;
+ qpChosen = INT32_MAX;
}
}
+ // apply our chosen values
+ //
+ if (qpChosen != INT32_MAX) {
+ ALOGD("minquality by QP: inject %s=%d", AMEDIAFORMAT_VIDEO_QP_MAX, qpChosen);
+ AMediaFormat_setInt32(inFormat, AMEDIAFORMAT_VIDEO_QP_MAX, qpChosen);
+
+ // force spreading the QP across frame types, since we are imposing a value
+ qpSpreadMaxPerFrameType(inFormat, info->qpDelta, info->qpMax, /* override */ true);
+ }
+
+ if (bitrateChosen != bitrateConfigured) {
+ ALOGD("minquality/target bitrate raised from %" PRId64 " to %" PRId64 " bps",
+ bitrateConfigured, bitrateChosen);
+ AMediaFormat_setInt32(inFormat, AMEDIAFORMAT_KEY_BIT_RATE, (int32_t)bitrateChosen);
+ }
+
return 0;
}
diff --git a/media/libmediaformatshaper/include/media/formatshaper/CodecProperties.h b/media/libmediaformatshaper/include/media/formatshaper/CodecProperties.h
index 84268b9..ff7051f 100644
--- a/media/libmediaformatshaper/include/media/formatshaper/CodecProperties.h
+++ b/media/libmediaformatshaper/include/media/formatshaper/CodecProperties.h
@@ -21,6 +21,8 @@
#include <mutex>
#include <string>
+#include <inttypes.h>
+
#include <utils/RefBase.h>
namespace android {
@@ -73,7 +75,7 @@
// This is used to calculate a minimum bitrate for any particular resolution.
// A 1080p (1920*1080 = 2073600 pixels) to be encoded at 5Mbps has a bpp == 2.41
void setBpp(double bpp) { mBpp = bpp;}
- double getBpp() {return mBpp;}
+ double getBpp(int32_t width, int32_t height);
// Does this codec support QP bounding
// The getMapping() methods provide any needed mapping to non-standard keys.
@@ -92,10 +94,22 @@
std::string mMediaType;
int mApi = 0;
int mMinimumQuality = 0;
- int mTargetQpMax = 0;
+ int mTargetQpMax = INT32_MAX;
bool mSupportsQp = false;
double mBpp = 0.0;
+ // allow different target bits-per-pixel based on resolution
+ // similar to codec 'performance points'
+ // uses 'next largest' (by pixel count) point as minimum bpp
+ struct bpp_point {
+ struct bpp_point *next;
+ int32_t pixels;
+ int32_t width, height;
+ double bpp;
+ };
+ struct bpp_point *mBppPoints = nullptr;
+ bool bppPoint(std::string resolution, std::string value);
+
std::mutex mMappingLock;
// XXX figure out why I'm having problems getting compiler to like GUARDED_BY
std::map<std::string, std::string> mMappings /*GUARDED_BY(mMappingLock)*/ ;
diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp
index d250976..287317d 100644
--- a/media/libmediaplayerservice/Android.bp
+++ b/media/libmediaplayerservice/Android.bp
@@ -38,6 +38,7 @@
"media_permission-aidl-cpp",
"libaudioclient_aidl_conversion",
"libbase",
+ "libactivitymanager_aidl",
"libandroid_net",
"libaudioclient",
"libbinder",
diff --git a/media/libmediatranscoding/TranscodingClientManager.cpp b/media/libmediatranscoding/TranscodingClientManager.cpp
index 086c658..6dbcaf9 100644
--- a/media/libmediatranscoding/TranscodingClientManager.cpp
+++ b/media/libmediatranscoding/TranscodingClientManager.cpp
@@ -97,8 +97,8 @@
Status addClientUid(int32_t /*in_sessionId*/, int32_t /*in_clientUid*/,
bool* /*_aidl_return*/) override;
- Status getClientUids(int32_t /*in_sessionId*/, std::vector<int32_t>* /*out_clientUids*/,
- bool* /*_aidl_return*/) override;
+ Status getClientUids(int32_t /*in_sessionId*/,
+ std::optional<std::vector<int32_t>>* /*_aidl_return*/) override;
Status unregister() override;
};
@@ -259,10 +259,9 @@
return Status::ok();
}
-Status TranscodingClientManager::ClientImpl::getClientUids(int32_t in_sessionId,
- std::vector<int32_t>* out_clientUids,
- bool* _aidl_return) {
- *_aidl_return = false;
+Status TranscodingClientManager::ClientImpl::getClientUids(
+ int32_t in_sessionId, std::optional<std::vector<int32_t>>* _aidl_return) {
+ *_aidl_return = std::nullopt;
std::shared_ptr<TranscodingClientManager> owner;
if (mAbandoned || (owner = mOwner.lock()) == nullptr) {
@@ -273,8 +272,11 @@
return Status::ok();
}
- *_aidl_return =
- owner->mSessionController->getClientUids(mClientId, in_sessionId, out_clientUids);
+ std::vector<int32_t> result;
+
+ if (owner->mSessionController->getClientUids(mClientId, in_sessionId, &result)) {
+ *_aidl_return = result;
+ }
return Status::ok();
}
diff --git a/media/libmediatranscoding/aidl/android/media/ITranscodingClient.aidl b/media/libmediatranscoding/aidl/android/media/ITranscodingClient.aidl
index c6fa57f..9ef9052 100644
--- a/media/libmediatranscoding/aidl/android/media/ITranscodingClient.aidl
+++ b/media/libmediatranscoding/aidl/android/media/ITranscodingClient.aidl
@@ -77,7 +77,8 @@
* @clientUids array to hold the retrieved client uid list.
* @return false if the session doesn't exist, true otherwise.
*/
- boolean getClientUids(in int sessionId, out int[] clientUids);
+ @nullable
+ int[] getClientUids(in int sessionId);
/**
* Unregister the client with the MediaTranscodingService.
diff --git a/media/libmediatranscoding/tests/TranscodingClientManager_tests.cpp b/media/libmediatranscoding/tests/TranscodingClientManager_tests.cpp
index b7b1279..9233410 100644
--- a/media/libmediatranscoding/tests/TranscodingClientManager_tests.cpp
+++ b/media/libmediatranscoding/tests/TranscodingClientManager_tests.cpp
@@ -577,7 +577,7 @@
addMultipleClients();
bool result;
- std::vector<int32_t> clientUids;
+ std::optional<std::vector<int32_t>> clientUids;
TranscodingRequestParcel request;
TranscodingSessionParcel session;
uid_t ownUid = ::getuid();
@@ -587,10 +587,10 @@
EXPECT_FALSE(result);
EXPECT_TRUE(mClient1->addClientUid(SESSION(0), ownUid, &result).isOk());
EXPECT_FALSE(result);
- EXPECT_TRUE(mClient1->getClientUids(-1, &clientUids, &result).isOk());
- EXPECT_FALSE(result);
- EXPECT_TRUE(mClient1->getClientUids(SESSION(0), &clientUids, &result).isOk());
- EXPECT_FALSE(result);
+ EXPECT_TRUE(mClient1->getClientUids(-1, &clientUids).isOk());
+ EXPECT_EQ(clientUids, std::nullopt);
+ EXPECT_TRUE(mClient1->getClientUids(SESSION(0), &clientUids).isOk());
+ EXPECT_EQ(clientUids, std::nullopt);
unregisterMultipleClients();
}
@@ -599,7 +599,7 @@
addMultipleClients();
bool result;
- std::vector<int32_t> clientUids;
+ std::optional<std::vector<int32_t>> clientUids;
TranscodingRequestParcel request;
TranscodingSessionParcel session;
uid_t ownUid = ::getuid();
@@ -612,10 +612,10 @@
EXPECT_TRUE(result);
// Should have own uid in client uid list.
- EXPECT_TRUE(mClient1->getClientUids(SESSION(0), &clientUids, &result).isOk());
- EXPECT_TRUE(result);
- EXPECT_EQ(clientUids.size(), 1);
- EXPECT_EQ(clientUids[0], ownUid);
+ EXPECT_TRUE(mClient1->getClientUids(SESSION(0), &clientUids).isOk());
+ EXPECT_NE(clientUids, std::nullopt);
+ EXPECT_EQ(clientUids->size(), 1);
+ EXPECT_EQ((*clientUids)[0], ownUid);
// Adding invalid client uid should fail.
EXPECT_TRUE(mClient1->addClientUid(SESSION(0), kInvalidClientUid, &result).isOk());
@@ -633,28 +633,28 @@
EXPECT_TRUE(result);
// Should not have own uid in client uid list.
- EXPECT_TRUE(mClient1->getClientUids(SESSION(1), &clientUids, &result).isOk());
- EXPECT_TRUE(result);
- EXPECT_EQ(clientUids.size(), 0);
+ EXPECT_TRUE(mClient1->getClientUids(SESSION(1), &clientUids).isOk());
+ EXPECT_NE(clientUids, std::nullopt);
+ EXPECT_EQ(clientUids->size(), 0);
// Add own uid (with IMediaTranscodingService::USE_CALLING_UID) again, should succeed.
EXPECT_TRUE(
mClient1->addClientUid(SESSION(1), IMediaTranscodingService::USE_CALLING_UID, &result)
.isOk());
EXPECT_TRUE(result);
- EXPECT_TRUE(mClient1->getClientUids(SESSION(1), &clientUids, &result).isOk());
- EXPECT_TRUE(result);
- EXPECT_EQ(clientUids.size(), 1);
- EXPECT_EQ(clientUids[0], ownUid);
+ EXPECT_TRUE(mClient1->getClientUids(SESSION(1), &clientUids).isOk());
+ EXPECT_NE(clientUids, std::nullopt);
+ EXPECT_EQ(clientUids->size(), 1);
+ EXPECT_EQ((*clientUids)[0], ownUid);
// Add more uids, should succeed.
int32_t kFakeUid = ::getuid() ^ 0x1;
EXPECT_TRUE(mClient1->addClientUid(SESSION(1), kFakeUid, &result).isOk());
EXPECT_TRUE(result);
- EXPECT_TRUE(mClient1->getClientUids(SESSION(1), &clientUids, &result).isOk());
- EXPECT_TRUE(result);
+ EXPECT_TRUE(mClient1->getClientUids(SESSION(1), &clientUids).isOk());
+ EXPECT_NE(clientUids, std::nullopt);
std::unordered_set<uid_t> uidSet;
- uidSet.insert(clientUids.begin(), clientUids.end());
+ uidSet.insert(clientUids->begin(), clientUids->end());
EXPECT_EQ(uidSet.size(), 2);
EXPECT_EQ(uidSet.count(ownUid), 1);
EXPECT_EQ(uidSet.count(kFakeUid), 1);
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index ad67379..c21ea8f 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -1422,6 +1422,7 @@
* MediaFormat Shaping forward declarations
* including the property name we use for control.
*/
+static int enableMediaFormatShapingDefault = 1;
static const char enableMediaFormatShapingProperty[] = "debug.stagefright.enableshaping";
static void mapFormat(AString componentName, const sp<AMessage> &format, const char *kind,
bool reverse);
@@ -1497,7 +1498,8 @@
}
if (flags & CONFIGURE_FLAG_ENCODE) {
- int8_t enableShaping = property_get_bool(enableMediaFormatShapingProperty, 0);
+ int8_t enableShaping = property_get_bool(enableMediaFormatShapingProperty,
+ enableMediaFormatShapingDefault);
if (!enableShaping) {
ALOGI("format shaping disabled, property '%s'", enableMediaFormatShapingProperty);
} else {
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index 05ec69e..20b4044 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -226,7 +226,9 @@
add(devices);
return size();
}
- return SortedVector::merge(devices);
+ ssize_t ret = SortedVector::merge(devices);
+ refreshTypes();
+ return ret;
}
/**
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
index 9bef97c..0f8b0a5 100644
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -170,11 +170,13 @@
status_t getMediaDevicesForRole(device_role_t role, const DeviceVector& availableDevices,
DeviceVector& devices) const;
+ void dumpCapturePresetDevicesRoleMap(String8 *dst, int spaces) const;
+
AudioPolicyManagerObserver *mApmObserver = nullptr;
ProductStrategyMap mProductStrategies;
- ProductStrategyPreferredRoutingMap mProductStrategyPreferredDevices;
- CapturePresetDevicesRoleMap mCapturePresetDevicesRole;
+ ProductStrategyDevicesRoleMap mProductStrategyDeviceRoleMap;
+ CapturePresetDevicesRoleMap mCapturePresetDevicesRoleMap;
VolumeGroupMap mVolumeGroups;
LastRemovableMediaDevices mLastRemovableMediaDevices;
audio_mode_t mPhoneState = AUDIO_MODE_NORMAL; /**< current phone state. */
diff --git a/services/audiopolicy/engine/common/include/ProductStrategy.h b/services/audiopolicy/engine/common/include/ProductStrategy.h
index 54625ea..2aa2f9a 100644
--- a/services/audiopolicy/engine/common/include/ProductStrategy.h
+++ b/services/audiopolicy/engine/common/include/ProductStrategy.h
@@ -18,20 +18,20 @@
#include "VolumeGroup.h"
-#include <system/audio.h>
-#include <utils/RefBase.h>
-#include <HandleGenerator.h>
-#include <string>
-#include <vector>
#include <map>
-#include <utils/Errors.h>
-#include <utils/String8.h>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <HandleGenerator.h>
#include <media/AudioAttributes.h>
#include <media/AudioContainers.h>
#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioPolicy.h>
-
-#include <vector>
+#include <system/audio.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
namespace android {
@@ -170,11 +170,12 @@
product_strategy_t mDefaultStrategy = PRODUCT_STRATEGY_NONE;
};
-class ProductStrategyPreferredRoutingMap : public std::map<product_strategy_t,
- AudioDeviceTypeAddrVector>
-{
-public:
- void dump(String8 *dst, int spaces = 0) const;
-};
+using ProductStrategyDevicesRoleMap =
+ std::map<std::pair<product_strategy_t, device_role_t>, AudioDeviceTypeAddrVector>;
+
+void dumpProductStrategyDevicesRoleMap(
+ const ProductStrategyDevicesRoleMap& productStrategyDeviceRoleMap,
+ String8 *dst,
+ int spaces);
} // namespace android
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index aa43691..150a9a8 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -17,6 +17,8 @@
#define LOG_TAG "APM::AudioPolicyEngine/Base"
//#define LOG_NDEBUG 0
+#include <functional>
+#include <string>
#include <sys/stat.h>
#include "EngineBase.h"
@@ -349,23 +351,33 @@
return NO_ERROR;
}
-status_t EngineBase::setDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role,
- const AudioDeviceTypeAddrVector &devices)
-{
- // verify strategy exists
- if (mProductStrategies.find(strategy) == mProductStrategies.end()) {
- ALOGE("%s invalid strategy %u", __func__, strategy);
+namespace {
+template <typename T>
+status_t setDevicesRoleForT(
+ std::map<std::pair<T, device_role_t>, AudioDeviceTypeAddrVector>& tDevicesRoleMap,
+ T t, device_role_t role, const AudioDeviceTypeAddrVector &devices,
+ const std::string& logStr, std::function<bool(T)> p) {
+ if (!p(t)) {
+ ALOGE("%s invalid %s %u", __func__, logStr.c_str(), t);
return BAD_VALUE;
}
switch (role) {
case DEVICE_ROLE_PREFERRED:
- mProductStrategyPreferredDevices[strategy] = devices;
- break;
- case DEVICE_ROLE_DISABLED:
- // TODO (b/184065221): support set devices role as disabled for strategy.
- ALOGI("%s no implemented for role as %d", __func__, role);
- break;
+ case DEVICE_ROLE_DISABLED: {
+ tDevicesRoleMap[std::make_pair(t, role)] = devices;
+ // The preferred devices and disabled devices are mutually exclusive. Once a device is added
+ // the a list, it must be removed from the other one.
+ const device_role_t roleToRemove = role == DEVICE_ROLE_PREFERRED ? DEVICE_ROLE_DISABLED
+ : DEVICE_ROLE_PREFERRED;
+ auto it = tDevicesRoleMap.find(std::make_pair(t, roleToRemove));
+ if (it != tDevicesRoleMap.end()) {
+ it->second = excludeDeviceTypeAddrsFrom(it->second, devices);
+ if (it->second.empty()) {
+ tDevicesRoleMap.erase(it);
+ }
+ }
+ } break;
case DEVICE_ROLE_NONE:
// Intentionally fall-through as it is no need to set device role as none for a strategy.
default:
@@ -375,28 +387,26 @@
return NO_ERROR;
}
-status_t EngineBase::removeDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role)
-{
- // verify strategy exists
- if (mProductStrategies.find(strategy) == mProductStrategies.end()) {
- ALOGE("%s invalid strategy %u", __func__, strategy);
+template <typename T>
+status_t removeAllDevicesRoleForT(
+ std::map<std::pair<T, device_role_t>, AudioDeviceTypeAddrVector>& tDevicesRoleMap,
+ T t, device_role_t role, const std::string& logStr, std::function<bool(T)> p) {
+ if (!p(t)) {
+ ALOGE("%s invalid %s %u", __func__, logStr.c_str(), t);
return BAD_VALUE;
}
switch (role) {
case DEVICE_ROLE_PREFERRED:
- if (mProductStrategyPreferredDevices.erase(strategy) == 0) {
- // no preferred device was set
+ case DEVICE_ROLE_DISABLED:
+ if (tDevicesRoleMap.erase(std::make_pair(t, role)) == 0) {
+ // no preferred/disabled device was set
return NAME_NOT_FOUND;
}
break;
- case DEVICE_ROLE_DISABLED:
- // TODO (b/184065221): support remove devices role as disabled for strategy.
- ALOGI("%s no implemented for role as %d", __func__, role);
- break;
case DEVICE_ROLE_NONE:
// Intentionally fall-through as it makes no sense to remove devices with
- // role as DEVICE_ROLE_NONE for a strategy
+ // role as DEVICE_ROLE_NONE
default:
ALOGE("%s invalid role %d", __func__, role);
return BAD_VALUE;
@@ -404,30 +414,27 @@
return NO_ERROR;
}
-status_t EngineBase::getDevicesForRoleAndStrategy(product_strategy_t strategy, device_role_t role,
- AudioDeviceTypeAddrVector &devices) const
-{
- // verify strategy exists
- if (mProductStrategies.find(strategy) == mProductStrategies.end()) {
- ALOGE("%s unknown strategy %u", __func__, strategy);
+template <typename T>
+status_t getDevicesRoleForT(
+ const std::map<std::pair<T, device_role_t>, AudioDeviceTypeAddrVector>& tDevicesRoleMap,
+ T t, device_role_t role, AudioDeviceTypeAddrVector &devices, const std::string& logStr,
+ std::function<bool(T)> p) {
+ if (!p(t)) {
+ ALOGE("%s invalid %s %u", __func__, logStr.c_str(), t);
return BAD_VALUE;
}
switch (role) {
- case DEVICE_ROLE_PREFERRED: {
- // preferred device for this strategy?
- auto devIt = mProductStrategyPreferredDevices.find(strategy);
- if (devIt == mProductStrategyPreferredDevices.end()) {
- ALOGV("%s no preferred device for strategy %u", __func__, strategy);
+ case DEVICE_ROLE_PREFERRED:
+ case DEVICE_ROLE_DISABLED: {
+ auto it = tDevicesRoleMap.find(std::make_pair(t, role));
+ if (it == tDevicesRoleMap.end()) {
+ ALOGV("%s no device as role %u for %s %u", __func__, role, logStr.c_str(), t);
return NAME_NOT_FOUND;
}
- devices = devIt->second;
+ devices = it->second;
} break;
- case DEVICE_ROLE_DISABLED:
- // TODO (b/184065221): support devices role as disabled for strategy.
- ALOGV("%s no implemented for role as %d", __func__, role);
- break;
case DEVICE_ROLE_NONE:
// Intentionally fall-through as the DEVICE_ROLE_NONE is never set
default:
@@ -437,32 +444,45 @@
return NO_ERROR;
}
+} // namespace
+
+status_t EngineBase::setDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role,
+ const AudioDeviceTypeAddrVector &devices)
+{
+ std::function<bool(product_strategy_t)> p = [this](product_strategy_t strategy) {
+ return mProductStrategies.find(strategy) != mProductStrategies.end();
+ };
+ return setDevicesRoleForT(
+ mProductStrategyDeviceRoleMap, strategy, role, devices, "strategy" /*logStr*/, p);
+}
+
+status_t EngineBase::removeDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role)
+{
+ std::function<bool(product_strategy_t)> p = [this](product_strategy_t strategy) {
+ return mProductStrategies.find(strategy) != mProductStrategies.end();
+ };
+ return removeAllDevicesRoleForT(
+ mProductStrategyDeviceRoleMap, strategy, role, "strategy" /*logStr*/, p);
+}
+
+status_t EngineBase::getDevicesForRoleAndStrategy(product_strategy_t strategy, device_role_t role,
+ AudioDeviceTypeAddrVector &devices) const
+{
+ std::function<bool(product_strategy_t)> p = [this](product_strategy_t strategy) {
+ return mProductStrategies.find(strategy) != mProductStrategies.end();
+ };
+ return getDevicesRoleForT(
+ mProductStrategyDeviceRoleMap, strategy, role, devices, "strategy" /*logStr*/, p);
+}
+
status_t EngineBase::setDevicesRoleForCapturePreset(audio_source_t audioSource, device_role_t role,
const AudioDeviceTypeAddrVector &devices)
{
- // verify if the audio source is valid
- if (!audio_is_valid_audio_source(audioSource)) {
- ALOGE("%s unknown audio source %u", __func__, audioSource);
- }
-
- switch (role) {
- case DEVICE_ROLE_PREFERRED:
- mCapturePresetDevicesRole[audioSource][role] = devices;
- // When the devices are set as preferred devices, remove them from the disabled devices.
- doRemoveDevicesRoleForCapturePreset(
- audioSource, DEVICE_ROLE_DISABLED, devices, false /*forceMatched*/);
- break;
- case DEVICE_ROLE_DISABLED:
- // TODO: support setting devices role as disabled for capture preset.
- ALOGI("%s no implemented for role as %d", __func__, role);
- break;
- case DEVICE_ROLE_NONE:
- // Intentionally fall-through as it is no need to set device role as none
- default:
- ALOGE("%s invalid role %d", __func__, role);
- return BAD_VALUE;
- }
- return NO_ERROR;
+ std::function<bool(audio_source_t)> p = [](audio_source_t audioSource) {
+ return audio_is_valid_audio_source(audioSource);
+ };
+ return setDevicesRoleForT(
+ mCapturePresetDevicesRoleMap, audioSource, role, devices, "audio source" /*logStr*/, p);
}
status_t EngineBase::addDevicesRoleForCapturePreset(audio_source_t audioSource, device_role_t role,
@@ -475,19 +495,20 @@
switch (role) {
case DEVICE_ROLE_PREFERRED:
- mCapturePresetDevicesRole[audioSource][role] = excludeDeviceTypeAddrsFrom(
- mCapturePresetDevicesRole[audioSource][role], devices);
- for (const auto& device : devices) {
- mCapturePresetDevicesRole[audioSource][role].push_back(device);
+ case DEVICE_ROLE_DISABLED: {
+ const auto audioSourceRole = std::make_pair(audioSource, role);
+ mCapturePresetDevicesRoleMap[audioSourceRole] = excludeDeviceTypeAddrsFrom(
+ mCapturePresetDevicesRoleMap[audioSourceRole], devices);
+ for (const auto &device : devices) {
+ mCapturePresetDevicesRoleMap[audioSourceRole].push_back(device);
}
// When the devices are set as preferred devices, remove them from the disabled devices.
doRemoveDevicesRoleForCapturePreset(
- audioSource, DEVICE_ROLE_DISABLED, devices, false /*forceMatched*/);
- break;
- case DEVICE_ROLE_DISABLED:
- // TODO: support setting devices role as disabled for capture preset.
- ALOGI("%s no implemented for role as %d", __func__, role);
- break;
+ audioSource,
+ role == DEVICE_ROLE_PREFERRED ? DEVICE_ROLE_DISABLED : DEVICE_ROLE_PREFERRED,
+ devices,
+ false /*forceMatched*/);
+ } break;
case DEVICE_ROLE_NONE:
// Intentionally fall-through as it is no need to set device role as none
default:
@@ -513,21 +534,22 @@
switch (role) {
case DEVICE_ROLE_PREFERRED:
case DEVICE_ROLE_DISABLED: {
- if (mCapturePresetDevicesRole.count(audioSource) == 0 ||
- mCapturePresetDevicesRole[audioSource].count(role) == 0) {
+ const auto audioSourceRole = std::make_pair(audioSource, role);
+ if (mCapturePresetDevicesRoleMap.find(audioSourceRole) ==
+ mCapturePresetDevicesRoleMap.end()) {
return NAME_NOT_FOUND;
}
AudioDeviceTypeAddrVector remainingDevices = excludeDeviceTypeAddrsFrom(
- mCapturePresetDevicesRole[audioSource][role], devices);
+ mCapturePresetDevicesRoleMap[audioSourceRole], devices);
if (forceMatched && remainingDevices.size() !=
- mCapturePresetDevicesRole[audioSource][role].size() - devices.size()) {
+ mCapturePresetDevicesRoleMap[audioSourceRole].size() - devices.size()) {
// There are some devices from `devicesToRemove` that are not shown in the cached record
return BAD_VALUE;
}
- mCapturePresetDevicesRole[audioSource][role] = remainingDevices;
- if (mCapturePresetDevicesRole[audioSource][role].empty()) {
+ mCapturePresetDevicesRoleMap[audioSourceRole] = remainingDevices;
+ if (mCapturePresetDevicesRoleMap[audioSourceRole].empty()) {
// Remove the role when device list is empty
- mCapturePresetDevicesRole[audioSource].erase(role);
+ mCapturePresetDevicesRoleMap.erase(audioSourceRole);
}
} break;
case DEVICE_ROLE_NONE:
@@ -543,63 +565,21 @@
status_t EngineBase::clearDevicesRoleForCapturePreset(audio_source_t audioSource,
device_role_t role)
{
- // verify if the audio source is valid
- if (!audio_is_valid_audio_source(audioSource)) {
- ALOGE("%s unknown audio source %u", __func__, audioSource);
- }
-
- switch (role) {
- case DEVICE_ROLE_PREFERRED:
- if (mCapturePresetDevicesRole.count(audioSource) == 0 ||
- mCapturePresetDevicesRole[audioSource].erase(role) == 0) {
- // no preferred device for the given audio source
- return NAME_NOT_FOUND;
- }
- break;
- case DEVICE_ROLE_DISABLED:
- // TODO: support remove devices role as disabled for strategy.
- ALOGI("%s no implemented for role as %d", __func__, role);
- break;
- case DEVICE_ROLE_NONE:
- // Intentionally fall-through as it makes no sense to remove devices with
- // role as DEVICE_ROLE_NONE for a strategy
- default:
- ALOGE("%s invalid role %d", __func__, role);
- return BAD_VALUE;
- }
- return NO_ERROR;
+ std::function<bool(audio_source_t)> p = [](audio_source_t audioSource) {
+ return audio_is_valid_audio_source(audioSource);
+ };
+ return removeAllDevicesRoleForT(
+ mCapturePresetDevicesRoleMap, audioSource, role, "audio source" /*logStr*/, p);
}
status_t EngineBase::getDevicesForRoleAndCapturePreset(audio_source_t audioSource,
device_role_t role, AudioDeviceTypeAddrVector &devices) const
{
- // verify if the audio source is valid
- if (!audio_is_valid_audio_source(audioSource)) {
- ALOGE("%s unknown audio source %u", __func__, audioSource);
- return BAD_VALUE;
- }
-
- switch (role) {
- case DEVICE_ROLE_PREFERRED:
- case DEVICE_ROLE_DISABLED: {
- if (mCapturePresetDevicesRole.count(audioSource) == 0) {
- return NAME_NOT_FOUND;
- }
- auto devIt = mCapturePresetDevicesRole.at(audioSource).find(role);
- if (devIt == mCapturePresetDevicesRole.at(audioSource).end()) {
- ALOGV("%s no devices role(%d) for capture preset %u", __func__, role, audioSource);
- return NAME_NOT_FOUND;
- }
-
- devices = devIt->second;
- } break;
- case DEVICE_ROLE_NONE:
- // Intentionally fall-through as the DEVICE_ROLE_NONE is never set
- default:
- ALOGE("%s invalid role %d", __func__, role);
- return BAD_VALUE;
- }
- return NO_ERROR;
+ std::function<bool(audio_source_t)> p = [](audio_source_t audioSource) {
+ return audio_is_valid_audio_source(audioSource);
+ };
+ return getDevicesRoleForT(
+ mCapturePresetDevicesRoleMap, audioSource, role, devices, "audio source" /*logStr*/, p);
}
status_t EngineBase::getMediaDevicesForRole(device_role_t role,
@@ -641,10 +621,22 @@
return activeDevices;
}
+void EngineBase::dumpCapturePresetDevicesRoleMap(String8 *dst, int spaces) const
+{
+ dst->appendFormat("\n%*sDevice role per capture preset dump:", spaces, "");
+ for (const auto& [capturePresetRolePair, devices] : mCapturePresetDevicesRoleMap) {
+ dst->appendFormat("\n%*sCapture preset(%u) Device Role(%u) Devices(%s)", spaces + 2, "",
+ capturePresetRolePair.first, capturePresetRolePair.second,
+ dumpAudioDeviceTypeAddrVector(devices, true /*includeSensitiveInfo*/).c_str());
+ }
+ dst->appendFormat("\n");
+}
+
void EngineBase::dump(String8 *dst) const
{
mProductStrategies.dump(dst, 2);
- mProductStrategyPreferredDevices.dump(dst, 2);
+ dumpProductStrategyDevicesRoleMap(mProductStrategyDeviceRoleMap, dst, 2);
+ dumpCapturePresetDevicesRoleMap(dst, 2);
mVolumeGroups.dump(dst, 2);
}
diff --git a/services/audiopolicy/engine/common/src/ProductStrategy.cpp b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
index d4cea5a..b3d144f 100644
--- a/services/audiopolicy/engine/common/src/ProductStrategy.cpp
+++ b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
@@ -320,14 +320,15 @@
}
}
-void ProductStrategyPreferredRoutingMap::dump(android::String8* dst, int spaces) const {
- dst->appendFormat("\n%*sPreferred devices per product strategy dump:", spaces, "");
- for (const auto& iter : *this) {
- dst->appendFormat("\n%*sStrategy %u %s",
- spaces + 2, "",
- (uint32_t) iter.first,
- dumpAudioDeviceTypeAddrVector(iter.second, true /*includeSensitiveInfo*/)
- .c_str());
+void dumpProductStrategyDevicesRoleMap(
+ const ProductStrategyDevicesRoleMap& productStrategyDeviceRoleMap,
+ String8 *dst,
+ int spaces) {
+ dst->appendFormat("\n%*sDevice role per product strategy dump:", spaces, "");
+ for (const auto& [strategyRolePair, devices] : productStrategyDeviceRoleMap) {
+ dst->appendFormat("\n%*sStrategy(%u) Device Role(%u) Devices(%s)", spaces + 2, "",
+ strategyRolePair.first, strategyRolePair.second,
+ dumpAudioDeviceTypeAddrVector(devices, true /*includeSensitiveInfo*/).c_str());
}
dst->appendFormat("\n");
}
diff --git a/services/audiopolicy/engine/interface/EngineInterface.h b/services/audiopolicy/engine/interface/EngineInterface.h
index f0a01d3..6a1d269 100644
--- a/services/audiopolicy/engine/interface/EngineInterface.h
+++ b/services/audiopolicy/engine/interface/EngineInterface.h
@@ -16,6 +16,8 @@
#pragma once
+#include <utility>
+
#include <AudioPolicyManagerObserver.h>
#include <media/AudioProductStrategy.h>
#include <media/AudioVolumeGroup.h>
@@ -35,7 +37,7 @@
using StrategyVector = std::vector<product_strategy_t>;
using VolumeGroupVector = std::vector<volume_group_t>;
using CapturePresetDevicesRoleMap =
- std::map<audio_source_t, std::map<device_role_t, AudioDeviceTypeAddrVector>>;
+ std::map<std::pair<audio_source_t, device_role_t>, AudioDeviceTypeAddrVector>;
/**
* This interface is dedicated to the policy manager that a Policy Engine shall implement.
diff --git a/services/audiopolicy/engineconfigurable/tools/buildCommonTypesStructureFile.py b/services/audiopolicy/engineconfigurable/tools/buildCommonTypesStructureFile.py
index 5083b14..43b3dd2 100755
--- a/services/audiopolicy/engineconfigurable/tools/buildCommonTypesStructureFile.py
+++ b/services/audiopolicy/engineconfigurable/tools/buildCommonTypesStructureFile.py
@@ -172,12 +172,6 @@
logging.info("added stub input device mask")
# Transform input source in inclusive criterion
- shift = len(all_component_types['OutputDevicesMask'])
- if shift > 32:
- logging.critical("OutputDevicesMask incompatible with criterion representation on 32 bits")
- logging.info("EXIT ON FAILURE")
- exit(1)
-
for component_types in all_component_types:
values = ','.join('{}:{}'.format(value, key) for key, value in all_component_types[component_types].items())
logging.info("{}: <{}>".format(component_types, values))
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 05422aa..32c0267 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -113,6 +113,7 @@
"libutilscallstack",
"libutils",
"libbinder",
+ "libactivitymanager_aidl",
"libcutils",
"libmedia",
"libmediautils",
@@ -161,6 +162,7 @@
export_shared_lib_headers: [
"libbinder",
+ "libactivitymanager_aidl",
"libcamera_client",
"libfmq",
"libsensorprivacy",
diff --git a/services/mediatranscoding/tests/Android.bp b/services/mediatranscoding/tests/Android.bp
index 4df5a9f..cb180ec 100644
--- a/services/mediatranscoding/tests/Android.bp
+++ b/services/mediatranscoding/tests/Android.bp
@@ -25,6 +25,7 @@
],
shared_libs: [
+ "libactivitymanager_aidl",
"libbinder",
"libbinder_ndk",
"liblog",
diff --git a/services/mediatranscoding/tests/MediaTranscodingServiceTestHelper.h b/services/mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
index 4727e48..20e4bfb 100644
--- a/services/mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
+++ b/services/mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
@@ -449,13 +449,17 @@
template <bool expectation = success>
bool getClientUids(int32_t sessionId, std::vector<int32_t>* clientUids) {
constexpr bool shouldSucceed = (expectation == success);
- bool result;
- Status status = mClient->getClientUids(sessionId, clientUids, &result);
+ std::optional<std::vector<int32_t>> aidl_return;
+ Status status = mClient->getClientUids(sessionId, &aidl_return);
EXPECT_TRUE(status.isOk());
- EXPECT_EQ(result, shouldSucceed);
+ bool success = (aidl_return != std::nullopt);
+ if (success) {
+ *clientUids = *aidl_return;
+ }
+ EXPECT_EQ(success, shouldSucceed);
- return status.isOk() && (result == shouldSucceed);
+ return status.isOk() && (success == shouldSucceed);
}
int32_t mClientId;