Merge "aaudio: clip bufferSize at top of MMAP code"
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 7623d6d..c62833d 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -10,7 +10,7 @@
LOCAL_SHARED_LIBRARIES := \
libstagefright libmedia libmedia_omx libmediaextractor libutils libbinder \
libstagefright_foundation libjpeg libui libgui libcutils liblog \
- libhidlmemory \
+ libhidlbase \
android.hardware.media.omx@1.0 \
LOCAL_C_INCLUDES:= \
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 50b034a..ddc4b16 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -36,7 +36,6 @@
#include <media/MediaSource.h>
#include <media/ICrypto.h>
#include <media/IMediaHTTPService.h>
-#include <media/IMediaCodecService.h>
#include <media/IMediaPlayerService.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ALooper.h>
@@ -68,7 +67,6 @@
#include <gui/SurfaceComposerClient.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
-#include <media/omx/1.0/WOmx.h>
using namespace android;
@@ -912,37 +910,24 @@
}
if (listComponents) {
- sp<IOMX> omx;
- if (property_get_bool("persist.media.treble_omx", true)) {
- using namespace ::android::hardware::media::omx::V1_0;
- sp<IOmx> tOmx = IOmx::getService();
+ using ::android::hardware::hidl_vec;
+ using ::android::hardware::hidl_string;
+ using namespace ::android::hardware::media::omx::V1_0;
+ sp<IOmx> omx = IOmx::getService();
+ CHECK(omx.get() != nullptr);
- CHECK(tOmx.get() != NULL);
-
- omx = new utils::LWOmx(tOmx);
- } else {
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder = sm->getService(String16("media.codec"));
- sp<IMediaCodecService> service = interface_cast<IMediaCodecService>(binder);
-
- CHECK(service.get() != NULL);
-
- omx = service->getOMX();
- }
- CHECK(omx.get() != NULL);
-
- List<IOMX::ComponentInfo> list;
- omx->listNodes(&list);
-
- for (List<IOMX::ComponentInfo>::iterator it = list.begin();
- it != list.end(); ++it) {
- printf("%s\t Roles: ", (*it).mName.string());
- for (List<String8>::iterator itRoles = (*it).mRoles.begin() ;
- itRoles != (*it).mRoles.end() ; ++itRoles) {
- printf("%s\t", (*itRoles).string());
- }
- printf("\n");
- }
+ hidl_vec<IOmx::ComponentInfo> nodeList;
+ auto transStatus = omx->listNodes([](
+ const auto& status, const auto& nodeList) {
+ CHECK(status == Status::OK);
+ for (const auto& info : nodeList) {
+ printf("%s\t Roles: ", info.mName.c_str());
+ for (const auto& role : info.mRoles) {
+ printf("%s\t", role.c_str());
+ }
+ }
+ });
+ CHECK(transStatus.isOk());
}
sp<SurfaceComposerClient> composerClient;
diff --git a/include/media/AudioClient.h b/include/media/AudioClient.h
deleted file mode 100644
index 9efd76d..0000000
--- a/include/media/AudioClient.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#ifndef ANDROID_AUDIO_CLIENT_H
-#define ANDROID_AUDIO_CLIENT_H
-
-#include <system/audio.h>
-#include <utils/String16.h>
-
-namespace android {
-
-class AudioClient {
- public:
- AudioClient() :
- clientUid(-1), clientPid(-1), packageName("") {}
-
- uid_t clientUid;
- pid_t clientPid;
- String16 packageName;
-};
-
-}; // namespace android
-
-#endif // ANDROID_AUDIO_CLIENT_H
diff --git a/include/media/AudioClient.h b/include/media/AudioClient.h
new file mode 120000
index 0000000..feac9b9
--- /dev/null
+++ b/include/media/AudioClient.h
@@ -0,0 +1 @@
+media/libaudioclient/include/media/AudioClient.h
\ No newline at end of file
diff --git a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
index 1cf2c72..8d7a01e 100644
--- a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
@@ -219,8 +219,7 @@
// Data conversion.
float levelFrom;
float levelTo;
- bool ramping = mVolumeRamp.nextSegment(framesToWrite * getSamplesPerFrame(),
- &levelFrom, &levelTo);
+ bool ramping = mVolumeRamp.nextSegment(framesToWrite, &levelFrom, &levelTo);
// The formats are validated when the stream is opened so we do not have to
// check for illegal combinations here.
// TODO factor this out into a utility function
diff --git a/media/libaaudio/src/utility/LinearRamp.h b/media/libaaudio/src/utility/LinearRamp.h
index ff09dce..2b1b8e0 100644
--- a/media/libaaudio/src/utility/LinearRamp.h
+++ b/media/libaaudio/src/utility/LinearRamp.h
@@ -87,7 +87,7 @@
std::atomic<float> mTarget;
- int32_t mLengthInFrames = 48000 / 50; // 20 msec at 48000 Hz
+ int32_t mLengthInFrames = 48000 / 100; // 10 msec at 48000 Hz
int32_t mRemaining = 0;
float mLevelFrom = 0.0f;
float mLevelTo = 0.0f;
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 58330ae..c284f73 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -20,6 +20,7 @@
#include <utils/Log.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
+#include <media/AudioResamplerPublic.h>
#include <media/AudioSystem.h>
#include <media/IAudioFlinger.h>
#include <media/IAudioPolicyService.h>
@@ -253,6 +254,31 @@
return volume ? 100 - int(dBConvertInverse * log(volume) + 0.5) : 0;
}
+/* static */ size_t AudioSystem::calculateMinFrameCount(
+ uint32_t afLatencyMs, uint32_t afFrameCount, uint32_t afSampleRate,
+ uint32_t sampleRate, float speed /*, uint32_t notificationsPerBufferReq*/)
+{
+ // Ensure that buffer depth covers at least audio hardware latency
+ uint32_t minBufCount = afLatencyMs / ((1000 * afFrameCount) / afSampleRate);
+ if (minBufCount < 2) {
+ minBufCount = 2;
+ }
+#if 0
+ // The notificationsPerBufferReq parameter is not yet used for non-fast tracks,
+ // but keeping the code here to make it easier to add later.
+ if (minBufCount < notificationsPerBufferReq) {
+ minBufCount = notificationsPerBufferReq;
+ }
+#endif
+ ALOGV("calculateMinFrameCount afLatency %u afFrameCount %u afSampleRate %u "
+ "sampleRate %u speed %f minBufCount: %u" /*" notificationsPerBufferReq %u"*/,
+ afLatencyMs, afFrameCount, afSampleRate, sampleRate, speed, minBufCount
+ /*, notificationsPerBufferReq*/);
+ return minBufCount * sourceFramesNeededWithTimestretch(
+ sampleRate, afFrameCount, afSampleRate, speed);
+}
+
+
status_t AudioSystem::getOutputSamplingRate(uint32_t* samplingRate, audio_stream_type_t streamType)
{
audio_io_handle_t output;
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 356b321..36961d6 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -99,32 +99,6 @@
return kFixPitch ? AUDIO_TIMESTRETCH_PITCH_NORMAL : pitch;
}
-// Must match similar computation in createTrack_l in Threads.cpp.
-// TODO: Move to a common library
-static size_t calculateMinFrameCount(
- uint32_t afLatencyMs, uint32_t afFrameCount, uint32_t afSampleRate,
- uint32_t sampleRate, float speed /*, uint32_t notificationsPerBufferReq*/)
-{
- // Ensure that buffer depth covers at least audio hardware latency
- uint32_t minBufCount = afLatencyMs / ((1000 * afFrameCount) / afSampleRate);
- if (minBufCount < 2) {
- minBufCount = 2;
- }
-#if 0
- // The notificationsPerBufferReq parameter is not yet used for non-fast tracks,
- // but keeping the code here to make it easier to add later.
- if (minBufCount < notificationsPerBufferReq) {
- minBufCount = notificationsPerBufferReq;
- }
-#endif
- ALOGV("calculateMinFrameCount afLatency %u afFrameCount %u afSampleRate %u "
- "sampleRate %u speed %f minBufCount: %u" /*" notificationsPerBufferReq %u"*/,
- afLatencyMs, afFrameCount, afSampleRate, sampleRate, speed, minBufCount
- /*, notificationsPerBufferReq*/);
- return minBufCount * sourceFramesNeededWithTimestretch(
- sampleRate, afFrameCount, afSampleRate, speed);
-}
-
// static
status_t AudioTrack::getMinFrameCount(
size_t* frameCount,
@@ -165,8 +139,8 @@
// When called from createTrack, speed is 1.0f (normal speed).
// This is rechecked again on setting playback rate (TODO: on setting sample rate, too).
- *frameCount = calculateMinFrameCount(afLatency, afFrameCount, afSampleRate, sampleRate, 1.0f
- /*, 0 notificationsPerBufferReq*/);
+ *frameCount = AudioSystem::calculateMinFrameCount(afLatency, afFrameCount, afSampleRate,
+ sampleRate, 1.0f /*, 0 notificationsPerBufferReq*/);
// The formula above should always produce a non-zero value under normal circumstances:
// AudioTrack.SAMPLE_RATE_HZ_MIN <= sampleRate <= AudioTrack.SAMPLE_RATE_HZ_MAX.
@@ -190,8 +164,7 @@
mPreviousSchedulingGroup(SP_DEFAULT),
mPausedPosition(0),
mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
- mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE),
- mPortId(AUDIO_PORT_HANDLE_NONE)
+ mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE)
{
mAttributes.content_type = AUDIO_CONTENT_TYPE_UNKNOWN;
mAttributes.usage = AUDIO_USAGE_UNKNOWN;
@@ -222,8 +195,7 @@
mState(STATE_STOPPED),
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
mPreviousSchedulingGroup(SP_DEFAULT),
- mPausedPosition(0),
- mPortId(AUDIO_PORT_HANDLE_NONE)
+ mPausedPosition(0)
{
mStatus = set(streamType, sampleRate, format, channelMask,
frameCount, flags, cbf, user, notificationFrames,
@@ -254,8 +226,7 @@
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
mPreviousSchedulingGroup(SP_DEFAULT),
mPausedPosition(0),
- mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
- mPortId(AUDIO_PORT_HANDLE_NONE)
+ mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE)
{
mStatus = set(streamType, sampleRate, format, channelMask,
0 /*frameCount*/, flags, cbf, user, notificationFrames,
@@ -320,6 +291,7 @@
mThreadCanCallJava = threadCanCallJava;
mSelectedDeviceId = selectedDeviceId;
+ mSessionId = sessionId;
switch (transferType) {
case TRANSFER_DEFAULT:
@@ -500,11 +472,6 @@
notificationFrames, minNotificationsPerBuffer, maxNotificationsPerBuffer);
}
mNotificationFramesAct = 0;
- if (sessionId == AUDIO_SESSION_ALLOCATE) {
- mSessionId = (audio_session_t) AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
- } else {
- mSessionId = sessionId;
- }
int callingpid = IPCThreadState::self()->getCallingPid();
int mypid = getpid();
if (uid == AUDIO_UID_INVALID || (callingpid != mypid)) {
@@ -1317,70 +1284,12 @@
return NO_INIT;
}
- audio_io_handle_t output;
- audio_stream_type_t streamType = mStreamType;
- audio_attributes_t *attr = (mStreamType == AUDIO_STREAM_DEFAULT) ? &mAttributes : NULL;
+ status_t status;
bool callbackAdded = false;
+ {
// mFlags (not mOrigFlags) is modified depending on whether fast request is accepted.
// After fast request is denied, we will request again if IAudioTrack is re-created.
-
- status_t status;
- audio_config_t config = AUDIO_CONFIG_INITIALIZER;
- config.sample_rate = mSampleRate;
- config.channel_mask = mChannelMask;
- config.format = mFormat;
- config.offload_info = mOffloadInfoCopy;
- mRoutedDeviceId = mSelectedDeviceId;
- status = AudioSystem::getOutputForAttr(attr, &output,
- mSessionId, &streamType, mClientUid,
- &config,
- mFlags, &mRoutedDeviceId, &mPortId);
-
- if (status != NO_ERROR || output == AUDIO_IO_HANDLE_NONE) {
- ALOGE("Could not get audio output for session %d, stream type %d, usage %d, sample rate %u,"
- " format %#x, channel mask %#x, flags %#x",
- mSessionId, streamType, mAttributes.usage, mSampleRate, mFormat, mChannelMask,
- mFlags);
- return BAD_VALUE;
- }
- {
- // Now that we have a reference to an I/O handle and have not yet handed it off to AudioFlinger,
- // we must release it ourselves if anything goes wrong.
-
- // Not all of these values are needed under all conditions, but it is easier to get them all
- status = AudioSystem::getLatency(output, &mAfLatency);
- if (status != NO_ERROR) {
- ALOGE("getLatency(%d) failed status %d", output, status);
- goto release;
- }
- ALOGV("createTrack_l() output %d afLatency %u", output, mAfLatency);
-
- status = AudioSystem::getFrameCount(output, &mAfFrameCount);
- if (status != NO_ERROR) {
- ALOGE("getFrameCount(output=%d) status %d", output, status);
- goto release;
- }
-
- // TODO consider making this a member variable if there are other uses for it later
- size_t afFrameCountHAL;
- status = AudioSystem::getFrameCountHAL(output, &afFrameCountHAL);
- if (status != NO_ERROR) {
- ALOGE("getFrameCountHAL(output=%d) status %d", output, status);
- goto release;
- }
- ALOG_ASSERT(afFrameCountHAL > 0);
-
- status = AudioSystem::getSamplingRate(output, &mAfSampleRate);
- if (status != NO_ERROR) {
- ALOGE("getSamplingRate(output=%d) status %d", output, status);
- goto release;
- }
- if (mSampleRate == 0) {
- mSampleRate = mAfSampleRate;
- mOriginalSampleRate = mAfSampleRate;
- }
-
// Client can only express a preference for FAST. Server will perform additional tests.
if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
// either of these use cases:
@@ -1394,130 +1303,78 @@
// use case 4: synchronous write
((mTransfer == TRANSFER_SYNC) && mThreadCanCallJava);
- bool useCaseAllowed = sharedBuffer || transferAllowed;
- if (!useCaseAllowed) {
+ bool fastAllowed = sharedBuffer || transferAllowed;
+ if (!fastAllowed) {
ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by client, not shared buffer and transfer = %s",
convertTransferToText(mTransfer));
- }
-
- // sample rates must also match
- bool sampleRateAllowed = mSampleRate == mAfSampleRate;
- if (!sampleRateAllowed) {
- ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by client, sample rate %u Hz but HAL needs %u Hz",
- mSampleRate, mAfSampleRate);
- }
-
- bool fastAllowed = useCaseAllowed && sampleRateAllowed;
- if (!fastAllowed) {
mFlags = (audio_output_flags_t) (mFlags & ~AUDIO_OUTPUT_FLAG_FAST);
}
}
- mNotificationFramesAct = mNotificationFramesReq;
-
- size_t frameCount = mReqFrameCount;
- if (!audio_has_proportional_frames(mFormat)) {
-
- if (mSharedBuffer != 0) {
- // Same comment as below about ignoring frameCount parameter for set()
- frameCount = mSharedBuffer->size();
- } else if (frameCount == 0) {
- frameCount = mAfFrameCount;
- }
- if (mNotificationFramesAct != frameCount) {
- mNotificationFramesAct = frameCount;
- }
- } else if (mSharedBuffer != 0) {
- // FIXME: Ensure client side memory buffers need
- // not have additional alignment beyond sample
- // (e.g. 16 bit stereo accessed as 32 bit frame).
- size_t alignment = audio_bytes_per_sample(mFormat);
- if (alignment & 1) {
- // for AUDIO_FORMAT_PCM_24_BIT_PACKED (not exposed through Java).
- alignment = 1;
- }
- if (mChannelCount > 1) {
- // More than 2 channels does not require stronger alignment than stereo
- alignment <<= 1;
- }
- if (((uintptr_t)mSharedBuffer->pointer() & (alignment - 1)) != 0) {
- ALOGE("Invalid buffer alignment: address %p, channel count %u",
- mSharedBuffer->pointer(), mChannelCount);
- status = BAD_VALUE;
- goto release;
- }
-
- // When initializing a shared buffer AudioTrack via constructors,
- // there's no frameCount parameter.
- // But when initializing a shared buffer AudioTrack via set(),
- // there _is_ a frameCount parameter. We silently ignore it.
- frameCount = mSharedBuffer->size() / mFrameSize;
+ IAudioFlinger::CreateTrackInput input;
+ if (mStreamType != AUDIO_STREAM_DEFAULT) {
+ stream_type_to_audio_attributes(mStreamType, &input.attr);
} else {
- size_t minFrameCount = 0;
- // For fast tracks the frame count calculations and checks are mostly done by server,
- // but we try to respect the application's request for notifications per buffer.
- if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
- if (mNotificationsPerBufferReq > 0) {
- // Avoid possible arithmetic overflow during multiplication.
- // mNotificationsPerBuffer is clamped to a small integer earlier, so it is unlikely.
- if (mNotificationsPerBufferReq > SIZE_MAX / afFrameCountHAL) {
- ALOGE("Requested notificationPerBuffer=%u ignored for HAL frameCount=%zu",
- mNotificationsPerBufferReq, afFrameCountHAL);
- } else {
- minFrameCount = afFrameCountHAL * mNotificationsPerBufferReq;
- }
- }
- } else {
- // for normal tracks precompute the frame count based on speed.
- const float speed = !isPurePcmData_l() || isOffloadedOrDirect_l() ? 1.0f :
- max(mMaxRequiredSpeed, mPlaybackRate.mSpeed);
- minFrameCount = calculateMinFrameCount(
- mAfLatency, mAfFrameCount, mAfSampleRate, mSampleRate,
- speed /*, 0 mNotificationsPerBufferReq*/);
- }
- if (frameCount < minFrameCount) {
- frameCount = minFrameCount;
- }
+ input.attr = mAttributes;
}
-
- audio_output_flags_t flags = mFlags;
-
- pid_t tid = -1;
+ input.config = AUDIO_CONFIG_INITIALIZER;
+ input.config.sample_rate = mSampleRate;
+ input.config.channel_mask = mChannelMask;
+ input.config.format = mFormat;
+ input.config.offload_info = mOffloadInfoCopy;
+ input.clientInfo.clientUid = mClientUid;
+ input.clientInfo.clientPid = mClientPid;
+ input.clientInfo.clientTid = -1;
if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
// It is currently meaningless to request SCHED_FIFO for a Java thread. Even if the
// application-level code follows all non-blocking design rules, the language runtime
// doesn't also follow those rules, so the thread will not benefit overall.
if (mAudioTrackThread != 0 && !mThreadCanCallJava) {
- tid = mAudioTrackThread->getTid();
+ input.clientInfo.clientTid = mAudioTrackThread->getTid();
}
}
+ input.sharedBuffer = mSharedBuffer;
+ input.notificationsPerBuffer = mNotificationsPerBufferReq;
+ input.speed = 1.0;
+ if (audio_has_proportional_frames(mFormat) && mSharedBuffer == 0 &&
+ (mFlags & AUDIO_OUTPUT_FLAG_FAST) == 0) {
+ input.speed = !isPurePcmData_l() || isOffloadedOrDirect_l() ? 1.0f :
+ max(mMaxRequiredSpeed, mPlaybackRate.mSpeed);
+ }
+ input.flags = mFlags;
+ input.frameCount = mReqFrameCount;
+ input.notificationFrameCount = mNotificationFramesReq;
+ input.selectedDeviceId = mSelectedDeviceId;
+ input.sessionId = mSessionId;
- size_t temp = frameCount; // temp may be replaced by a revised value of frameCount,
- // but we will still need the original value also
- audio_session_t originalSessionId = mSessionId;
- sp<IAudioTrack> track = audioFlinger->createTrack(streamType,
- mSampleRate,
- mFormat,
- mChannelMask,
- &temp,
- &flags,
- mSharedBuffer,
+ IAudioFlinger::CreateTrackOutput output;
+
+ sp<IAudioTrack> track = audioFlinger->createTrack(input,
output,
- mClientPid,
- tid,
- &mSessionId,
- mClientUid,
- &status,
- mPortId);
- ALOGE_IF(originalSessionId != AUDIO_SESSION_ALLOCATE && mSessionId != originalSessionId,
- "session ID changed from %d to %d", originalSessionId, mSessionId);
+ &status);
- if (status != NO_ERROR) {
- ALOGE("AudioFlinger could not create track, status: %d", status);
- goto release;
+ if (status != NO_ERROR || output.outputId == AUDIO_IO_HANDLE_NONE) {
+ ALOGE("AudioFlinger could not create track, status: %d output %d", status, output.outputId);
+ goto error;
}
ALOG_ASSERT(track != 0);
+ mFrameCount = output.frameCount;
+ mNotificationFramesAct = (uint32_t)output.notificationFrameCount;
+ mRoutedDeviceId = output.selectedDeviceId;
+ mSessionId = output.sessionId;
+
+ mSampleRate = output.sampleRate;
+ if (mOriginalSampleRate == 0) {
+ mOriginalSampleRate = mSampleRate;
+ }
+
+ mAfFrameCount = output.afFrameCount;
+ mAfSampleRate = output.afSampleRate;
+ mAfLatency = output.afLatencyMs;
+
+ mLatency = mAfLatency + (1000LL * mFrameCount) / mSampleRate;
+
// AudioFlinger now owns the reference to the I/O handle,
// so we are no longer responsible for releasing it.
@@ -1526,13 +1383,13 @@
if (iMem == 0) {
ALOGE("Could not get control block");
status = NO_INIT;
- goto release;
+ goto error;
}
void *iMemPointer = iMem->pointer();
if (iMemPointer == NULL) {
ALOGE("Could not get control block pointer");
status = NO_INIT;
- goto release;
+ goto error;
}
// invariant that mAudioTrack != 0 is true only after set() returns successfully
if (mAudioTrack != 0) {
@@ -1545,75 +1402,33 @@
audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMemPointer);
mCblk = cblk;
- // note that temp is the (possibly revised) value of frameCount
- if (temp < frameCount || (frameCount == 0 && temp == 0)) {
- // In current design, AudioTrack client checks and ensures frame count validity before
- // passing it to AudioFlinger so AudioFlinger should not return a different value except
- // for fast track as it uses a special method of assigning frame count.
- ALOGW("Requested frameCount %zu but received frameCount %zu", frameCount, temp);
- }
- frameCount = temp;
mAwaitBoost = false;
if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
- if (flags & AUDIO_OUTPUT_FLAG_FAST) {
- ALOGI("AUDIO_OUTPUT_FLAG_FAST successful; frameCount %zu -> %zu", frameCount, temp);
+ if (output.flags & AUDIO_OUTPUT_FLAG_FAST) {
+ ALOGI("AUDIO_OUTPUT_FLAG_FAST successful; frameCount %zu -> %zu",
+ mReqFrameCount, mFrameCount);
if (!mThreadCanCallJava) {
mAwaitBoost = true;
}
} else {
- ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %zu -> %zu", frameCount,
- temp);
+ ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %zu -> %zu", mReqFrameCount,
+ mFrameCount);
}
}
- mFlags = flags;
-
- // Make sure that application is notified with sufficient margin before underrun.
- // The client can divide the AudioTrack buffer into sub-buffers,
- // and expresses its desire to server as the notification frame count.
- if (mSharedBuffer == 0 && audio_is_linear_pcm(mFormat)) {
- size_t maxNotificationFrames;
- if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
- // notify every HAL buffer, regardless of the size of the track buffer
- maxNotificationFrames = afFrameCountHAL;
- } else {
- // For normal tracks, use at least double-buffering if no sample rate conversion,
- // or at least triple-buffering if there is sample rate conversion
- const int nBuffering = mOriginalSampleRate == mAfSampleRate ? 2 : 3;
- maxNotificationFrames = frameCount / nBuffering;
- // If client requested a fast track but this was denied, then use the smaller maximum.
- // FMS_20 is the minimum task wakeup period in ms for which CFS operates reliably.
-#define FMS_20 20 // FIXME share a common declaration with the same symbol in Threads.cpp
- if (mOrigFlags & AUDIO_OUTPUT_FLAG_FAST) {
- size_t maxNotificationFramesFastDenied = FMS_20 * mSampleRate / 1000;
- if (maxNotificationFrames > maxNotificationFramesFastDenied) {
- maxNotificationFrames = maxNotificationFramesFastDenied;
- }
- }
- }
- if (mNotificationFramesAct == 0 || mNotificationFramesAct > maxNotificationFrames) {
- if (mNotificationFramesAct == 0) {
- ALOGD("Client defaulted notificationFrames to %zu for frameCount %zu",
- maxNotificationFrames, frameCount);
- } else {
- ALOGW("Client adjusted notificationFrames from %u to %zu for frameCount %zu",
- mNotificationFramesAct, maxNotificationFrames, frameCount);
- }
- mNotificationFramesAct = (uint32_t) maxNotificationFrames;
- }
- }
+ mFlags = output.flags;
//mOutput != output includes the case where mOutput == AUDIO_IO_HANDLE_NONE for first creation
- if (mDeviceCallback != 0 && mOutput != output) {
+ if (mDeviceCallback != 0 && mOutput != output.outputId) {
if (mOutput != AUDIO_IO_HANDLE_NONE) {
AudioSystem::removeAudioDeviceCallback(this, mOutput);
}
- AudioSystem::addAudioDeviceCallback(this, output);
+ AudioSystem::addAudioDeviceCallback(this, output.outputId);
callbackAdded = true;
}
// We retain a copy of the I/O handle, but don't own the reference
- mOutput = output;
+ mOutput = output.outputId;
mRefreshRemaining = true;
// Starting address of buffers in shared memory. If there is a shared buffer, buffers
@@ -1628,18 +1443,16 @@
if (buffers == NULL) {
ALOGE("Could not get buffer pointer");
status = NO_INIT;
- goto release;
+ goto error;
}
}
mAudioTrack->attachAuxEffect(mAuxEffectId);
- mFrameCount = frameCount;
- updateLatency_l(); // this refetches mAfLatency and sets mLatency
// If IAudioTrack is re-created, don't let the requested frameCount
// decrease. This can confuse clients that cache frameCount().
- if (frameCount > mReqFrameCount) {
- mReqFrameCount = frameCount;
+ if (mFrameCount > mReqFrameCount) {
+ mReqFrameCount = mFrameCount;
}
// reset server position to 0 as we have new cblk.
@@ -1648,9 +1461,9 @@
// update proxy
if (mSharedBuffer == 0) {
mStaticProxy.clear();
- mProxy = new AudioTrackClientProxy(cblk, buffers, frameCount, mFrameSize);
+ mProxy = new AudioTrackClientProxy(cblk, buffers, mFrameCount, mFrameSize);
} else {
- mStaticProxy = new StaticAudioTrackClientProxy(cblk, buffers, frameCount, mFrameSize);
+ mStaticProxy = new StaticAudioTrackClientProxy(cblk, buffers, mFrameCount, mFrameSize);
mProxy = mStaticProxy;
}
@@ -1676,8 +1489,7 @@
return NO_ERROR;
}
-release:
- AudioSystem::releaseOutput(output, streamType, mSessionId);
+error:
if (callbackAdded) {
// note: mOutput is always valid is callbackAdded is true
AudioSystem::removeAudioDeviceCallback(this, mOutput);
@@ -1685,6 +1497,8 @@
if (status == NO_ERROR) {
status = NO_INIT;
}
+
+ // sp<IAudioTrack> track destructor will cause releaseOutput() to be called by AudioFlinger
return status;
}
@@ -2420,8 +2234,8 @@
return true; // static tracks do not have issues with buffer sizing.
}
const size_t minFrameCount =
- calculateMinFrameCount(mAfLatency, mAfFrameCount, mAfSampleRate, sampleRate, speed
- /*, 0 mNotificationsPerBufferReq*/);
+ AudioSystem::calculateMinFrameCount(mAfLatency, mAfFrameCount, mAfSampleRate,
+ sampleRate, speed /*, 0 mNotificationsPerBufferReq*/);
const bool allowed = mFrameCount >= minFrameCount;
ALOGD_IF(!allowed,
"isSampleRateSpeedAllowed_l denied "
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index fc8c11a..5cf2bdb 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -95,83 +95,38 @@
{
}
- virtual sp<IAudioTrack> createTrack(
- audio_stream_type_t streamType,
- uint32_t sampleRate,
- audio_format_t format,
- audio_channel_mask_t channelMask,
- size_t *pFrameCount,
- audio_output_flags_t *flags,
- const sp<IMemory>& sharedBuffer,
- audio_io_handle_t output,
- pid_t pid,
- pid_t tid,
- audio_session_t *sessionId,
- int clientUid,
- status_t *status,
- audio_port_handle_t portId)
+ virtual sp<IAudioTrack> createTrack(const CreateTrackInput& input,
+ CreateTrackOutput& output,
+ status_t *status)
{
Parcel data, reply;
sp<IAudioTrack> track;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32((int32_t) streamType);
- data.writeInt32(sampleRate);
- data.writeInt32(format);
- data.writeInt32(channelMask);
- size_t frameCount = pFrameCount != NULL ? *pFrameCount : 0;
- data.writeInt64(frameCount);
- audio_output_flags_t lFlags = flags != NULL ? *flags : AUDIO_OUTPUT_FLAG_NONE;
- data.writeInt32(lFlags);
- // haveSharedBuffer
- if (sharedBuffer != 0) {
- data.writeInt32(true);
- data.writeStrongBinder(IInterface::asBinder(sharedBuffer));
- } else {
- data.writeInt32(false);
+
+ if (status == nullptr) {
+ return track;
}
- data.writeInt32((int32_t) output);
- data.writeInt32((int32_t) pid);
- data.writeInt32((int32_t) tid);
- audio_session_t lSessionId = AUDIO_SESSION_ALLOCATE;
- if (sessionId != NULL) {
- lSessionId = *sessionId;
- }
- data.writeInt32(lSessionId);
- data.writeInt32(clientUid);
- data.writeInt32(portId);
+
+ input.writeToParcel(&data);
+
status_t lStatus = remote()->transact(CREATE_TRACK, data, &reply);
if (lStatus != NO_ERROR) {
- ALOGE("createTrack error: %s", strerror(-lStatus));
- } else {
- frameCount = reply.readInt64();
- if (pFrameCount != NULL) {
- *pFrameCount = frameCount;
- }
- lFlags = (audio_output_flags_t)reply.readInt32();
- if (flags != NULL) {
- *flags = lFlags;
- }
- lSessionId = (audio_session_t) reply.readInt32();
- if (sessionId != NULL) {
- *sessionId = lSessionId;
- }
- lStatus = reply.readInt32();
- track = interface_cast<IAudioTrack>(reply.readStrongBinder());
- if (lStatus == NO_ERROR) {
- if (track == 0) {
- ALOGE("createTrack should have returned an IAudioTrack");
- lStatus = UNKNOWN_ERROR;
- }
- } else {
- if (track != 0) {
- ALOGE("createTrack returned an IAudioTrack but with status %d", lStatus);
- track.clear();
- }
- }
+ ALOGE("createTrack transaction error %d", lStatus);
+ *status = DEAD_OBJECT;
+ return track;
}
- if (status != NULL) {
- *status = lStatus;
+ *status = reply.readInt32();
+ if (*status != NO_ERROR) {
+ ALOGE("createTrack returned error %d", *status);
+ return track;
}
+ track = interface_cast<IAudioTrack>(reply.readStrongBinder());
+ if (track == 0) {
+ ALOGE("createTrack returned an NULL IAudioTrack with status OK");
+ *status = DEAD_OBJECT;
+ return track;
+ }
+ output.readFromParcel(&reply);
return track;
}
@@ -970,41 +925,27 @@
switch (code) {
case CREATE_TRACK: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
- int streamType = data.readInt32();
- uint32_t sampleRate = data.readInt32();
- audio_format_t format = (audio_format_t) data.readInt32();
- audio_channel_mask_t channelMask = data.readInt32();
- size_t frameCount = data.readInt64();
- audio_output_flags_t flags = (audio_output_flags_t) data.readInt32();
- bool haveSharedBuffer = data.readInt32() != 0;
- sp<IMemory> buffer;
- if (haveSharedBuffer) {
- buffer = interface_cast<IMemory>(data.readStrongBinder());
+
+ CreateTrackInput input;
+ if (input.readFromParcel((Parcel*)&data) != NO_ERROR) {
+ reply->writeInt32(DEAD_OBJECT);
+ return NO_ERROR;
}
- audio_io_handle_t output = (audio_io_handle_t) data.readInt32();
- pid_t pid = (pid_t) data.readInt32();
- pid_t tid = (pid_t) data.readInt32();
- audio_session_t sessionId = (audio_session_t) data.readInt32();
- int clientUid = data.readInt32();
- audio_port_handle_t portId = (audio_port_handle_t) data.readInt32();
- status_t status = NO_ERROR;
- sp<IAudioTrack> track;
- if ((haveSharedBuffer && (buffer == 0)) ||
- ((buffer != 0) && (buffer->pointer() == NULL))) {
- ALOGW("CREATE_TRACK: cannot retrieve shared memory");
- status = DEAD_OBJECT;
- } else {
- track = createTrack(
- (audio_stream_type_t) streamType, sampleRate, format,
- channelMask, &frameCount, &flags, buffer, output, pid, tid,
- &sessionId, clientUid, &status, portId);
- LOG_ALWAYS_FATAL_IF((track != 0) != (status == NO_ERROR));
- }
- reply->writeInt64(frameCount);
- reply->writeInt32(flags);
- reply->writeInt32(sessionId);
+
+ status_t status;
+ CreateTrackOutput output;
+
+ sp<IAudioTrack> track= createTrack(input,
+ output,
+ &status);
+
+ LOG_ALWAYS_FATAL_IF((track != 0) != (status == NO_ERROR));
reply->writeInt32(status);
+ if (status != NO_ERROR) {
+ return NO_ERROR;
+ }
reply->writeStrongBinder(IInterface::asBinder(track));
+ output.writeToParcel(reply);
return NO_ERROR;
} break;
case OPEN_RECORD: {
diff --git a/media/libaudioclient/include/media/AudioClient.h b/media/libaudioclient/include/media/AudioClient.h
index 9efd76d..108e326 100644
--- a/media/libaudioclient/include/media/AudioClient.h
+++ b/media/libaudioclient/include/media/AudioClient.h
@@ -18,6 +18,7 @@
#ifndef ANDROID_AUDIO_CLIENT_H
#define ANDROID_AUDIO_CLIENT_H
+#include <binder/Parcel.h>
#include <system/audio.h>
#include <utils/String16.h>
@@ -26,11 +27,28 @@
class AudioClient {
public:
AudioClient() :
- clientUid(-1), clientPid(-1), packageName("") {}
+ clientUid(-1), clientPid(-1), clientTid(-1), packageName("") {}
uid_t clientUid;
pid_t clientPid;
+ pid_t clientTid;
String16 packageName;
+
+ status_t readFromParcel(Parcel *parcel) {
+ clientUid = parcel->readInt32();
+ clientPid = parcel->readInt32();
+ clientTid = parcel->readInt32();
+ packageName = parcel->readString16();
+ return NO_ERROR;
+ }
+
+ status_t writeToParcel(Parcel *parcel) const {
+ parcel->writeInt32(clientUid);
+ parcel->writeInt32(clientPid);
+ parcel->writeInt32(clientTid);
+ parcel->writeString16(packageName);
+ return NO_ERROR;
+ }
};
}; // namespace android
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 327eba8..66601da 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -106,6 +106,9 @@
static float linearToLog(int volume);
static int logToLinear(float volume);
+ static size_t calculateMinFrameCount(
+ uint32_t afLatencyMs, uint32_t afFrameCount, uint32_t afSampleRate,
+ uint32_t sampleRate, float speed /*, uint32_t notificationsPerBufferReq*/);
// Returned samplingRate and frameCount output values are guaranteed
// to be non-zero if status == NO_ERROR
@@ -209,8 +212,6 @@
static status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config);
static audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);
- // Client must successfully hand off the handle reference to AudioFlinger via createTrack(),
- // or release it with releaseOutput().
static status_t getOutputForAttr(const audio_attributes_t *attr,
audio_io_handle_t *output,
audio_session_t session,
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index 8973133..9fbd04b 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -1182,7 +1182,6 @@
pid_t mClientPid;
wp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
- audio_port_handle_t mPortId; // unique ID allocated by audio policy
};
}; // namespace android
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 133d6c9..9061c26 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -24,6 +24,8 @@
#include <utils/RefBase.h>
#include <utils/Errors.h>
#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <media/AudioClient.h>
#include <media/IAudioTrack.h>
#include <media/IAudioFlingerClient.h>
#include <system/audio.h>
@@ -44,6 +46,135 @@
public:
DECLARE_META_INTERFACE(AudioFlinger);
+ /* CreateTrackInput contains all input arguments sent by AudioTrack to AudioFlinger
+ * when calling createTrack() including arguments that will be updated by AudioFlinger
+ * and returned in CreateTrackOutput object
+ */
+ class CreateTrackInput {
+ public:
+ status_t readFromParcel(Parcel *parcel) {
+ /* input arguments*/
+ memset(&attr, 0, sizeof(audio_attributes_t));
+ if (parcel->read(&attr, sizeof(audio_attributes_t)) != NO_ERROR) {
+ return DEAD_OBJECT;
+ }
+ attr.tags[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE -1] = '\0';
+ memset(&config, 0, sizeof(audio_config_t));
+ if (parcel->read(&config, sizeof(audio_config_t)) != NO_ERROR) {
+ return DEAD_OBJECT;
+ }
+ (void)clientInfo.readFromParcel(parcel);
+ if (parcel->readInt32() != 0) {
+ sharedBuffer = interface_cast<IMemory>(parcel->readStrongBinder());
+ if (sharedBuffer == 0 || sharedBuffer->pointer() == NULL) {
+ return BAD_VALUE;
+ }
+ }
+ notificationsPerBuffer = parcel->readInt32();
+ speed = parcel->readFloat();
+
+ /* input/output arguments*/
+ (void)parcel->read(&flags, sizeof(audio_output_flags_t));
+ frameCount = parcel->readInt64();
+ notificationFrameCount = parcel->readInt64();
+ (void)parcel->read(&selectedDeviceId, sizeof(audio_port_handle_t));
+ (void)parcel->read(&sessionId, sizeof(audio_session_t));
+ return NO_ERROR;
+ }
+
+ status_t writeToParcel(Parcel *parcel) const {
+ /* input arguments*/
+ (void)parcel->write(&attr, sizeof(audio_attributes_t));
+ (void)parcel->write(&config, sizeof(audio_config_t));
+ (void)clientInfo.writeToParcel(parcel);
+ if (sharedBuffer != 0) {
+ (void)parcel->writeInt32(1);
+ (void)parcel->writeStrongBinder(IInterface::asBinder(sharedBuffer));
+ } else {
+ (void)parcel->writeInt32(0);
+ }
+ (void)parcel->writeInt32(notificationsPerBuffer);
+ (void)parcel->writeFloat(speed);
+
+ /* input/output arguments*/
+ (void)parcel->write(&flags, sizeof(audio_output_flags_t));
+ (void)parcel->writeInt64(frameCount);
+ (void)parcel->writeInt64(notificationFrameCount);
+ (void)parcel->write(&selectedDeviceId, sizeof(audio_port_handle_t));
+ (void)parcel->write(&sessionId, sizeof(audio_session_t));
+ return NO_ERROR;
+ }
+
+ /* input */
+ audio_attributes_t attr;
+ audio_config_t config;
+ AudioClient clientInfo;
+ sp<IMemory> sharedBuffer;
+ uint32_t notificationsPerBuffer;
+ float speed;
+
+ /* input/output */
+ audio_output_flags_t flags;
+ size_t frameCount;
+ size_t notificationFrameCount;
+ audio_port_handle_t selectedDeviceId;
+ audio_session_t sessionId;
+ };
+
+ /* CreateTrackOutput contains all output arguments returned by AudioFlinger to AudioTrack
+ * when calling createTrack() including arguments that were passed as I/O for update by
+ * CreateTrackInput.
+ */
+ class CreateTrackOutput {
+ public:
+ status_t readFromParcel(Parcel *parcel) {
+ /* input/output arguments*/
+ (void)parcel->read(&flags, sizeof(audio_output_flags_t));
+ frameCount = parcel->readInt64();
+ notificationFrameCount = parcel->readInt64();
+ (void)parcel->read(&selectedDeviceId, sizeof(audio_port_handle_t));
+ (void)parcel->read(&sessionId, sizeof(audio_session_t));
+
+ /* output arguments*/
+ sampleRate = parcel->readUint32();
+ afFrameCount = parcel->readInt64();
+ afSampleRate = parcel->readInt64();
+ afLatencyMs = parcel->readInt32();
+ (void)parcel->read(&outputId, sizeof(audio_io_handle_t));
+ return NO_ERROR;
+ }
+
+ status_t writeToParcel(Parcel *parcel) const {
+ /* input/output arguments*/
+ (void)parcel->write(&flags, sizeof(audio_output_flags_t));
+ (void)parcel->writeInt64(frameCount);
+ (void)parcel->writeInt64(notificationFrameCount);
+ (void)parcel->write(&selectedDeviceId, sizeof(audio_port_handle_t));
+ (void)parcel->write(&sessionId, sizeof(audio_session_t));
+
+ /* output arguments*/
+ (void)parcel->writeUint32(sampleRate);
+ (void)parcel->writeInt64(afFrameCount);
+ (void)parcel->writeInt64(afSampleRate);
+ (void)parcel->writeInt32(afLatencyMs);
+ (void)parcel->write(&outputId, sizeof(audio_io_handle_t));
+ return NO_ERROR;
+ }
+
+ /* input/output */
+ audio_output_flags_t flags;
+ size_t frameCount;
+ size_t notificationFrameCount;
+ audio_port_handle_t selectedDeviceId;
+ audio_session_t sessionId;
+
+ /* output */
+ uint32_t sampleRate;
+ size_t afFrameCount;
+ uint32_t afSampleRate;
+ uint32_t afLatencyMs;
+ audio_io_handle_t outputId;
+ };
// invariant on exit for all APIs that return an sp<>:
// (return value != 0) == (*status == NO_ERROR)
@@ -51,24 +182,9 @@
/* create an audio track and registers it with AudioFlinger.
* return null if the track cannot be created.
*/
- virtual sp<IAudioTrack> createTrack(
- audio_stream_type_t streamType,
- uint32_t sampleRate,
- audio_format_t format,
- audio_channel_mask_t channelMask,
- size_t *pFrameCount,
- audio_output_flags_t *flags,
- const sp<IMemory>& sharedBuffer,
- // On successful return, AudioFlinger takes over the handle
- // reference and will release it when the track is destroyed.
- // However on failure, the client is responsible for release.
- audio_io_handle_t output,
- pid_t pid,
- pid_t tid, // -1 means unused, otherwise must be valid non-0
- audio_session_t *sessionId,
- int clientUid,
- status_t *status,
- audio_port_handle_t portId) = 0;
+ virtual sp<IAudioTrack> createTrack(const CreateTrackInput& input,
+ CreateTrackOutput& output,
+ status_t *status) = 0;
virtual sp<media::IAudioRecord> openRecord(
// On successful return, AudioFlinger takes over the handle
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 1381d27..1f4bd0a 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -45,9 +45,7 @@
"aidl/android/IOMXBufferSource.aidl",
"IMediaCodecList.cpp",
- "IMediaCodecService.cpp",
"IOMX.cpp",
- "IOMXStore.cpp",
"MediaCodecBuffer.cpp",
"MediaCodecInfo.cpp",
"OMXBuffer.cpp",
diff --git a/media/libmedia/IMediaCodecService.cpp b/media/libmedia/IMediaCodecService.cpp
deleted file mode 100644
index adfa93d..0000000
--- a/media/libmedia/IMediaCodecService.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
-**
-** Copyright 2015, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "IMediaCodecService"
-//#define LOG_NDEBUG 0
-
-#include <utils/Log.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <binder/Parcel.h>
-#include <media/IMediaCodecService.h>
-
-namespace android {
-
-enum {
- GET_OMX = IBinder::FIRST_CALL_TRANSACTION,
- GET_OMX_STORE
-};
-
-class BpMediaCodecService : public BpInterface<IMediaCodecService>
-{
-public:
- explicit BpMediaCodecService(const sp<IBinder>& impl)
- : BpInterface<IMediaCodecService>(impl)
- {
- }
-
- virtual sp<IOMX> getOMX() {
- Parcel data, reply;
- data.writeInterfaceToken(IMediaCodecService::getInterfaceDescriptor());
- remote()->transact(GET_OMX, data, &reply);
- return interface_cast<IOMX>(reply.readStrongBinder());
- }
-
- virtual sp<IOMXStore> getOMXStore() {
- Parcel data, reply;
- data.writeInterfaceToken(IMediaCodecService::getInterfaceDescriptor());
- remote()->transact(GET_OMX_STORE, data, &reply);
- return interface_cast<IOMXStore>(reply.readStrongBinder());
- }
-
-};
-
-IMPLEMENT_META_INTERFACE(MediaCodecService, "android.media.IMediaCodecService");
-
-// ----------------------------------------------------------------------
-
-status_t BnMediaCodecService::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- switch (code) {
-
- case GET_OMX: {
- CHECK_INTERFACE(IMediaCodecService, data, reply);
- sp<IOMX> omx = getOMX();
- reply->writeStrongBinder(IInterface::asBinder(omx));
- return NO_ERROR;
- }
- case GET_OMX_STORE: {
- CHECK_INTERFACE(IMediaCodecService, data, reply);
- sp<IOMXStore> omxStore = getOMXStore();
- reply->writeStrongBinder(IInterface::asBinder(omxStore));
- return NO_ERROR;
- }
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-// ----------------------------------------------------------------------------
-
-} // namespace android
diff --git a/media/libmedia/IOMXStore.cpp b/media/libmedia/IOMXStore.cpp
deleted file mode 100644
index 4948f1a..0000000
--- a/media/libmedia/IOMXStore.cpp
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Copyright (c) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "IOMXStore"
-
-#include <utils/Log.h>
-
-#include <media/IOMX.h>
-#include <media/IOMXStore.h>
-#include <android/hardware/media/omx/1.0/IOmxStore.h>
-
-#include <binder/IInterface.h>
-#include <binder/IBinder.h>
-#include <binder/Parcel.h>
-
-#include <vector>
-#include <string>
-
-namespace android {
-
-namespace {
-
-enum {
- CONNECT = IBinder::FIRST_CALL_TRANSACTION,
- LIST_SERVICE_ATTRIBUTES,
- GET_NODE_PREFIX,
- LIST_ROLES,
- GET_OMX,
-};
-
-// Forward declarations of std::vector<T> <-> Parcel conversion funcitons that
-// depend on writeToParcel() and readToParcel() for T <-> Parcel.
-
-template <typename T>
-status_t writeToParcel(const std::vector<T>& v, Parcel* p);
-
-template <typename T>
-status_t readFromParcel(std::vector<T>* v, const Parcel& p);
-
-// std::string <-> Parcel
-
-status_t writeToParcel(const std::string& s, Parcel* p) {
- if (s.size() > INT32_MAX) {
- return BAD_VALUE;
- }
- return p->writeByteArray(
- s.size(), reinterpret_cast<const uint8_t*>(s.c_str()));
-}
-
-status_t readFromParcel(std::string* s, const Parcel& p) {
- int32_t len;
- status_t status = p.readInt32(&len);
- if (status != NO_ERROR) {
- return status;
- } else if ((len < 0) || (static_cast<uint64_t>(len) > SIZE_MAX)) {
- return BAD_VALUE;
- }
- s->resize(len);
- if (len == 0) {
- return NO_ERROR;
- }
- return p.read(static_cast<void*>(&s->front()), static_cast<size_t>(len));
-}
-
-// IOMXStore::Attribute <-> Parcel
-
-status_t writeToParcel(const IOMXStore::Attribute& a, Parcel* p) {
- status_t status = writeToParcel(a.key, p);
- if (status != NO_ERROR) {
- return status;
- }
- return writeToParcel(a.value, p);
-}
-
-status_t readFromParcel(IOMXStore::Attribute* a, const Parcel& p) {
- status_t status = readFromParcel(&(a->key), p);
- if (status != NO_ERROR) {
- return status;
- }
- return readFromParcel(&(a->value), p);
-}
-
-// IOMXStore::NodeInfo <-> Parcel
-
-status_t writeToParcel(const IOMXStore::NodeInfo& n, Parcel* p) {
- status_t status = writeToParcel(n.name, p);
- if (status != NO_ERROR) {
- return status;
- }
- status = writeToParcel(n.owner, p);
- if (status != NO_ERROR) {
- return status;
- }
- return writeToParcel(n.attributes, p);
-}
-
-status_t readFromParcel(IOMXStore::NodeInfo* n, const Parcel& p) {
- status_t status = readFromParcel(&(n->name), p);
- if (status != NO_ERROR) {
- return status;
- }
- status = readFromParcel(&(n->owner), p);
- if (status != NO_ERROR) {
- return status;
- }
- return readFromParcel(&(n->attributes), p);
-}
-
-// IOMXStore::RoleInfo <-> Parcel
-
-status_t writeToParcel(const IOMXStore::RoleInfo& r, Parcel* p) {
- status_t status = writeToParcel(r.role, p);
- if (status != NO_ERROR) {
- return status;
- }
- status = writeToParcel(r.type, p);
- if (status != NO_ERROR) {
- return status;
- }
- status = p->writeBool(r.isEncoder);
- if (status != NO_ERROR) {
- return status;
- }
- status = p->writeBool(r.preferPlatformNodes);
- if (status != NO_ERROR) {
- return status;
- }
- return writeToParcel(r.nodes, p);
-}
-
-status_t readFromParcel(IOMXStore::RoleInfo* r, const Parcel& p) {
- status_t status = readFromParcel(&(r->role), p);
- if (status != NO_ERROR) {
- return status;
- }
- status = readFromParcel(&(r->type), p);
- if (status != NO_ERROR) {
- return status;
- }
- status = p.readBool(&(r->isEncoder));
- if (status != NO_ERROR) {
- return status;
- }
- status = p.readBool(&(r->preferPlatformNodes));
- if (status != NO_ERROR) {
- return status;
- }
- return readFromParcel(&(r->nodes), p);
-}
-
-// std::vector<NodeInfo> <-> Parcel
-// std::vector<RoleInfo> <-> Parcel
-
-template <typename T>
-status_t writeToParcel(const std::vector<T>& v, Parcel* p) {
- status_t status = p->writeVectorSize(v);
- if (status != NO_ERROR) {
- return status;
- }
- for (const T& x : v) {
- status = writeToParcel(x, p);
- if (status != NO_ERROR) {
- return status;
- }
- }
- return NO_ERROR;
-}
-
-template <typename T>
-status_t readFromParcel(std::vector<T>* v, const Parcel& p) {
- status_t status = p.resizeOutVector(v);
- if (status != NO_ERROR) {
- return status;
- }
- for (T& x : *v) {
- status = readFromParcel(&x, p);
- if (status != NO_ERROR) {
- return status;
- }
- }
- return NO_ERROR;
-}
-
-} // unnamed namespace
-
-////////////////////////////////////////////////////////////////////////////////
-
-class BpOMXStore : public BpInterface<IOMXStore> {
-public:
- explicit BpOMXStore(const sp<IBinder> &impl)
- : BpInterface<IOMXStore>(impl) {
- }
-
- status_t listServiceAttributes(
- std::vector<Attribute>* attributes) override {
- Parcel data, reply;
- status_t status;
- status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
- if (status != NO_ERROR) {
- return status;
- }
- status = remote()->transact(LIST_SERVICE_ATTRIBUTES, data, &reply);
- if (status != NO_ERROR) {
- return status;
- }
- return readFromParcel(attributes, reply);
- }
-
- status_t getNodePrefix(std::string* prefix) override {
- Parcel data, reply;
- status_t status;
- status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
- if (status != NO_ERROR) {
- return status;
- }
- status = remote()->transact(GET_NODE_PREFIX, data, &reply);
- if (status != NO_ERROR) {
- return status;
- }
- return readFromParcel(prefix, reply);
- }
-
- status_t listRoles(std::vector<RoleInfo>* roleList) override {
- Parcel data, reply;
- status_t status;
- status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
- if (status != NO_ERROR) {
- return status;
- }
- status = remote()->transact(LIST_ROLES, data, &reply);
- if (status != NO_ERROR) {
- return status;
- }
- return readFromParcel(roleList, reply);
- }
-
- status_t getOmx(const std::string& name, sp<IOMX>* omx) override {
- Parcel data, reply;
- status_t status;
- status = data.writeInterfaceToken(IOMXStore::getInterfaceDescriptor());
- if (status != NO_ERROR) {
- return status;
- }
- status = writeToParcel(name, &data);
- if (status != NO_ERROR) {
- return status;
- }
- status = remote()->transact(GET_OMX, data, &reply);
- if (status != NO_ERROR) {
- return status;
- }
- return reply.readStrongBinder(omx);
- }
-
-};
-
-IMPLEMENT_META_INTERFACE(OMXStore, "android.hardware.IOMXStore");
-
-////////////////////////////////////////////////////////////////////////////////
-
-#define CHECK_OMX_INTERFACE(interface, data, reply) \
- do { if (!(data).enforceInterface(interface::getInterfaceDescriptor())) { \
- ALOGW("Call incorrectly routed to " #interface); \
- return PERMISSION_DENIED; \
- } } while (0)
-
-status_t BnOMXStore::onTransact(
- uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
- switch (code) {
- case LIST_SERVICE_ATTRIBUTES: {
- CHECK_OMX_INTERFACE(IOMXStore, data, reply);
- status_t status;
- std::vector<Attribute> attributes;
-
- status = listServiceAttributes(&attributes);
- if (status != NO_ERROR) {
- ALOGE("listServiceAttributes() fails with status %d",
- static_cast<int>(status));
- return NO_ERROR;
- }
- status = writeToParcel(attributes, reply);
- if (status != NO_ERROR) {
- ALOGE("listServiceAttributes() fails to send reply");
- return NO_ERROR;
- }
- return NO_ERROR;
- }
- case GET_NODE_PREFIX: {
- CHECK_OMX_INTERFACE(IOMXStore, data, reply);
- status_t status;
- std::string prefix;
-
- status = getNodePrefix(&prefix);
- if (status != NO_ERROR) {
- ALOGE("getNodePrefix() fails with status %d",
- static_cast<int>(status));
- return NO_ERROR;
- }
- status = writeToParcel(prefix, reply);
- if (status != NO_ERROR) {
- ALOGE("getNodePrefix() fails to send reply");
- return NO_ERROR;
- }
- return NO_ERROR;
- }
- case LIST_ROLES: {
- CHECK_OMX_INTERFACE(IOMXStore, data, reply);
- status_t status;
- std::vector<RoleInfo> roleList;
-
- status = listRoles(&roleList);
- if (status != NO_ERROR) {
- ALOGE("listRoles() fails with status %d",
- static_cast<int>(status));
- return NO_ERROR;
- }
- status = writeToParcel(roleList, reply);
- if (status != NO_ERROR) {
- ALOGE("listRoles() fails to send reply");
- return NO_ERROR;
- }
- return NO_ERROR;
- }
- case GET_OMX: {
- CHECK_OMX_INTERFACE(IOMXStore, data, reply);
- status_t status;
- std::string name;
- sp<IOMX> omx;
-
- status = readFromParcel(&name, data);
- if (status != NO_ERROR) {
- ALOGE("getOmx() fails to retrieve name");
- return NO_ERROR;
- }
- status = getOmx(name, &omx);
- if (status != NO_ERROR) {
- ALOGE("getOmx() fails with status %d",
- static_cast<int>(status));
- return NO_ERROR;
- }
- status = reply->writeStrongBinder(IInterface::asBinder(omx));
- if (status != NO_ERROR) {
- ALOGE("getOmx() fails to send reply");
- return NO_ERROR;
- }
- return NO_ERROR;
- }
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-} // namespace android
diff --git a/media/libmedia/include/media/IMediaCodecService.h b/media/libmedia/include/media/IMediaCodecService.h
deleted file mode 100644
index 59fb1c0..0000000
--- a/media/libmedia/include/media/IMediaCodecService.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_IMEDIACODECSERVICE_H
-#define ANDROID_IMEDIACODECSERVICE_H
-
-#include <binder/IInterface.h>
-#include <binder/IMemory.h>
-#include <binder/Parcel.h>
-#include <media/IDataSource.h>
-#include <media/IOMX.h>
-#include <media/IOMXStore.h>
-
-namespace android {
-
-class IMediaCodecService: public IInterface
-{
-public:
- DECLARE_META_INTERFACE(MediaCodecService);
-
- virtual sp<IOMX> getOMX() = 0;
- virtual sp<IOMXStore> getOMXStore() = 0;
-};
-
-class BnMediaCodecService: public BnInterface<IMediaCodecService>
-{
-public:
- virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
- uint32_t flags = 0);
-};
-
-} // namespace android
-
-#endif // ANDROID_IMEDIACODECSERVICE_H
diff --git a/media/libmedia/include/media/IOMXStore.h b/media/libmedia/include/media/IOMXStore.h
deleted file mode 100644
index 628db70..0000000
--- a/media/libmedia/include/media/IOMXStore.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_IOMXSTORE_H_
-
-#define ANDROID_IOMXSTORE_H_
-
-#include <media/IOMX.h>
-#include <android/hardware/media/omx/1.0/IOmxStore.h>
-
-#include <binder/IInterface.h>
-#include <binder/IBinder.h>
-
-#include <vector>
-#include <string>
-
-namespace android {
-
-using hardware::media::omx::V1_0::IOmxStore;
-
-class IOMXStore : public IInterface {
-public:
- DECLARE_META_INTERFACE(OMXStore);
-
- struct Attribute {
- std::string key;
- std::string value;
- };
-
- struct NodeInfo {
- std::string name;
- std::string owner;
- std::vector<Attribute> attributes;
- };
-
- struct RoleInfo {
- std::string role;
- std::string type;
- bool isEncoder;
- bool preferPlatformNodes;
- std::vector<NodeInfo> nodes;
- };
-
- virtual status_t listServiceAttributes(
- std::vector<Attribute>* attributes) = 0;
-
- virtual status_t getNodePrefix(std::string* prefix) = 0;
-
- virtual status_t listRoles(std::vector<RoleInfo>* roleList) = 0;
-
- virtual status_t getOmx(const std::string& name, sp<IOMX>* omx) = 0;
-};
-
-
-////////////////////////////////////////////////////////////////////////////////
-
-class BnOMXStore : public BnInterface<IOMXStore> {
-public:
- virtual status_t onTransact(
- uint32_t code, const Parcel &data, Parcel *reply,
- uint32_t flags = 0);
-};
-
-} // namespace android
-
-#endif // ANDROID_IOMX_H_
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 6b2c81d..495c418 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -741,26 +741,14 @@
new ServiceDeathNotifier(binder, p, MEDIAEXTRACTOR_PROCESS_DEATH);
binder->linkToDeath(extractorDeathListener);
- sp<ServiceDeathNotifier> codecDeathListener;
- if (property_get_bool("persist.media.treble_omx", true)) {
- // Treble IOmx
- sp<IOmx> omx = IOmx::getService();
- if (omx == nullptr) {
- ALOGE("Treble IOmx not available");
- return NULL;
- }
- codecDeathListener = new ServiceDeathNotifier(omx, p, MEDIACODEC_PROCESS_DEATH);
- omx->linkToDeath(codecDeathListener, 0);
- } else {
- // Legacy IOMX
- binder = sm->getService(String16("media.codec"));
- if (binder == NULL) {
- ALOGE("codec service not available");
- return NULL;
- }
- codecDeathListener = new ServiceDeathNotifier(binder, p, MEDIACODEC_PROCESS_DEATH);
- binder->linkToDeath(codecDeathListener);
+ sp<IOmx> omx = IOmx::getService();
+ if (omx == nullptr) {
+ ALOGE("IOmx service is not available");
+ return NULL;
}
+ sp<ServiceDeathNotifier> codecDeathListener =
+ new ServiceDeathNotifier(omx, p, MEDIACODEC_PROCESS_DEATH);
+ omx->linkToDeath(codecDeathListener, 0);
Mutex::Autolock lock(mLock);
@@ -1634,6 +1622,7 @@
mFlags(AUDIO_OUTPUT_FLAG_NONE),
mVolumeHandler(new media::VolumeHandler()),
mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
+ mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE),
mDeviceCallbackEnabled(false),
mDeviceCallback(deviceCallback)
{
@@ -2380,10 +2369,10 @@
ALOGV("getRoutedDeviceId");
Mutex::Autolock lock(mLock);
if (mTrack != 0) {
- *deviceId = mTrack->getRoutedDeviceId();
- return NO_ERROR;
+ mRoutedDeviceId = mTrack->getRoutedDeviceId();
}
- return NO_INIT;
+ *deviceId = mRoutedDeviceId;
+ return NO_ERROR;
}
status_t MediaPlayerService::AudioOutput::enableAudioDeviceCallback(bool enabled)
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 71e87a0..eefdd7d 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -176,6 +176,7 @@
audio_output_flags_t mFlags;
sp<media::VolumeHandler> mVolumeHandler;
audio_port_handle_t mSelectedDeviceId;
+ audio_port_handle_t mRoutedDeviceId;
bool mDeviceCallbackEnabled;
wp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
mutable Mutex mLock;
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 9b9b3bb..a423fee 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -450,27 +450,14 @@
}
sCameraChecked = true;
- if (property_get_bool("persist.media.treble_omx", true)) {
- // Treble IOmx
- sp<IOmx> omx = IOmx::getService();
- if (omx == nullptr) {
- ALOGE("Treble IOmx not available");
- return NO_INIT;
- }
- mCodecDeathListener = new ServiceDeathNotifier(omx, listener,
- MediaPlayerService::MEDIACODEC_PROCESS_DEATH);
- omx->linkToDeath(mCodecDeathListener, 0);
- } else {
- // Legacy IOMX
- binder = sm->getService(String16("media.codec"));
- if (binder == NULL) {
- ALOGE("Unable to connect to media codec service");
- return NO_INIT;
- }
- mCodecDeathListener = new ServiceDeathNotifier(binder, listener,
- MediaPlayerService::MEDIACODEC_PROCESS_DEATH);
- binder->linkToDeath(mCodecDeathListener);
+ sp<IOmx> omx = IOmx::getService();
+ if (omx == nullptr) {
+ ALOGE("IOmx service is not available");
+ return NO_INIT;
}
+ mCodecDeathListener = new ServiceDeathNotifier(omx, listener,
+ MediaPlayerService::MEDIACODEC_PROCESS_DEATH);
+ omx->linkToDeath(mCodecDeathListener, 0);
return OK;
}
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index a7a1b05..d9fdfe3 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -28,8 +28,6 @@
#include <media/stagefright/ACodec.h>
-#include <binder/MemoryDealer.h>
-
#include <media/stagefright/foundation/avc_utils.h>
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/foundation/ABuffer.h>
@@ -575,8 +573,6 @@
memset(&mLastNativeWindowCrop, 0, sizeof(mLastNativeWindowCrop));
changeState(mUninitializedState);
-
- mTrebleFlag = false;
}
ACodec::~ACodec() {
@@ -828,11 +824,7 @@
status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
- if (getTrebleFlag()) {
- CHECK(mAllocator[portIndex] == NULL);
- } else {
- CHECK(mDealer[portIndex] == NULL);
- }
+ CHECK(mAllocator[portIndex] == NULL);
CHECK(mBuffers[portIndex].isEmpty());
status_t err;
@@ -874,7 +866,10 @@
}
}
- size_t alignment = MemoryDealer::getAllocationAlignment();
+ size_t alignment = 32; // This is the value currently returned by
+ // MemoryDealer::getAllocationAlignment().
+ // TODO: Fix this when Treble has
+ // MemoryHeap/MemoryDealer.
ALOGV("[%s] Allocating %u buffers of size %zu (from %u using %s) on %s port",
mComponentName.c_str(),
@@ -896,18 +891,15 @@
}
if (mode != IOMX::kPortModePresetSecureBuffer) {
- if (getTrebleFlag()) {
- mAllocator[portIndex] = TAllocator::getService("ashmem");
- if (mAllocator[portIndex] == nullptr) {
- ALOGE("hidl allocator on port %d is null",
- (int)portIndex);
- return NO_MEMORY;
- }
- } else {
- size_t totalSize = def.nBufferCountActual *
- (alignedSize + alignedConvSize);
- mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
+ mAllocator[portIndex] = TAllocator::getService("ashmem");
+ if (mAllocator[portIndex] == nullptr) {
+ ALOGE("hidl allocator on port %d is null",
+ (int)portIndex);
+ return NO_MEMORY;
}
+ // TODO: When Treble has MemoryHeap/MemoryDealer, we should
+ // specify the heap size to be
+ // def.nBufferCountActual * (alignedSize + alignedConvSize).
}
const sp<AMessage> &format =
@@ -936,23 +928,55 @@
: new SecureBuffer(format, native_handle, bufSize);
info.mCodecData = info.mData;
} else {
- if (getTrebleFlag()) {
+ bool success;
+ auto transStatus = mAllocator[portIndex]->allocate(
+ bufSize,
+ [&success, &hidlMemToken](
+ bool s,
+ hidl_memory const& m) {
+ success = s;
+ hidlMemToken = m;
+ });
+
+ if (!transStatus.isOk()) {
+ ALOGE("hidl's AshmemAllocator failed at the "
+ "transport: %s",
+ transStatus.description().c_str());
+ return NO_MEMORY;
+ }
+ if (!success) {
+ return NO_MEMORY;
+ }
+ hidlMem = mapMemory(hidlMemToken);
+ if (hidlMem == nullptr) {
+ return NO_MEMORY;
+ }
+ err = mOMXNode->useBuffer(
+ portIndex, hidlMemToken, &info.mBufferID);
+
+ if (mode == IOMX::kPortModeDynamicANWBuffer) {
+ VideoNativeMetadata* metaData = (VideoNativeMetadata*)(
+ (void*)hidlMem->getPointer());
+ metaData->nFenceFd = -1;
+ }
+
+ info.mCodecData = new SharedMemoryBuffer(
+ format, hidlMem);
+ info.mCodecRef = hidlMem;
+
+ // if we require conversion, allocate conversion buffer for client use;
+ // otherwise, reuse codec buffer
+ if (mConverter[portIndex] != NULL) {
+ CHECK_GT(conversionBufferSize, (size_t)0);
bool success;
- auto transStatus = mAllocator[portIndex]->allocate(
- bufSize,
+ mAllocator[portIndex]->allocate(
+ conversionBufferSize,
[&success, &hidlMemToken](
bool s,
hidl_memory const& m) {
success = s;
hidlMemToken = m;
});
-
- if (!transStatus.isOk()) {
- ALOGE("hidl's AshmemAllocator failed at the "
- "transport: %s",
- transStatus.description().c_str());
- return NO_MEMORY;
- }
if (!success) {
return NO_MEMORY;
}
@@ -960,67 +984,8 @@
if (hidlMem == nullptr) {
return NO_MEMORY;
}
- err = mOMXNode->useBuffer(
- portIndex, hidlMemToken, &info.mBufferID);
- } else {
- mem = mDealer[portIndex]->allocate(bufSize);
- if (mem == NULL || mem->pointer() == NULL) {
- return NO_MEMORY;
- }
-
- err = mOMXNode->useBuffer(
- portIndex, mem, &info.mBufferID);
- }
-
- if (mode == IOMX::kPortModeDynamicANWBuffer) {
- VideoNativeMetadata* metaData = (VideoNativeMetadata*)(
- getTrebleFlag() ?
- (void*)hidlMem->getPointer() : mem->pointer());
- metaData->nFenceFd = -1;
- }
-
- if (getTrebleFlag()) {
- info.mCodecData = new SharedMemoryBuffer(
- format, hidlMem);
- info.mCodecRef = hidlMem;
- } else {
- info.mCodecData = new SharedMemoryBuffer(
- format, mem);
- info.mCodecRef = mem;
- }
-
- // if we require conversion, allocate conversion buffer for client use;
- // otherwise, reuse codec buffer
- if (mConverter[portIndex] != NULL) {
- CHECK_GT(conversionBufferSize, (size_t)0);
- if (getTrebleFlag()) {
- bool success;
- mAllocator[portIndex]->allocate(
- conversionBufferSize,
- [&success, &hidlMemToken](
- bool s,
- hidl_memory const& m) {
- success = s;
- hidlMemToken = m;
- });
- if (!success) {
- return NO_MEMORY;
- }
- hidlMem = mapMemory(hidlMemToken);
- if (hidlMem == nullptr) {
- return NO_MEMORY;
- }
- info.mData = new SharedMemoryBuffer(format, hidlMem);
- info.mMemRef = hidlMem;
- } else {
- mem = mDealer[portIndex]->allocate(
- conversionBufferSize);
- if (mem == NULL|| mem->pointer() == NULL) {
- return NO_MEMORY;
- }
- info.mData = new SharedMemoryBuffer(format, mem);
- info.mMemRef = mem;
- }
+ info.mData = new SharedMemoryBuffer(format, hidlMem);
+ info.mMemRef = hidlMem;
} else {
info.mData = info.mCodecData;
info.mMemRef = info.mCodecRef;
@@ -1581,11 +1546,7 @@
}
}
- if (getTrebleFlag()) {
- mAllocator[portIndex].clear();
- } else {
- mDealer[portIndex].clear();
- }
+ mAllocator[portIndex].clear();
return err;
}
@@ -6251,13 +6212,8 @@
if (mDeathNotifier != NULL) {
if (mCodec->mOMXNode != NULL) {
- if (mCodec->getTrebleFlag()) {
- auto tOmxNode = mCodec->mOMXNode->getHalInterface();
- tOmxNode->unlinkToDeath(mDeathNotifier);
- } else {
- sp<IBinder> binder = IInterface::asBinder(mCodec->mOMXNode);
- binder->unlinkToDeath(mDeathNotifier);
- }
+ auto tOmxNode = mCodec->mOMXNode->getHalInterface();
+ tOmxNode->unlinkToDeath(mDeathNotifier);
}
mDeathNotifier.clear();
}
@@ -6405,8 +6361,7 @@
componentName = matchingCodecs[matchIndex];
OMXClient client;
- bool trebleFlag;
- if (client.connect(owners[matchIndex].c_str(), &trebleFlag) != OK) {
+ if (client.connect(owners[matchIndex].c_str()) != OK) {
mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
return false;
}
@@ -6419,7 +6374,6 @@
androidSetThreadPriority(tid, prevPriority);
if (err == OK) {
- mCodec->setTrebleFlag(trebleFlag);
break;
} else {
ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
@@ -6441,17 +6395,9 @@
}
mDeathNotifier = new DeathNotifier(notify);
- if (mCodec->getTrebleFlag()) {
- auto tOmxNode = omxNode->getHalInterface();
- if (!tOmxNode->linkToDeath(mDeathNotifier, 0)) {
- mDeathNotifier.clear();
- }
- } else {
- if (IInterface::asBinder(omxNode)->linkToDeath(mDeathNotifier) != OK) {
- // This was a local binder, if it dies so do we, we won't care
- // about any notifications in the afterlife.
- mDeathNotifier.clear();
- }
+ auto tOmxNode = omxNode->getHalInterface();
+ if (!tOmxNode->linkToDeath(mDeathNotifier, 0)) {
+ mDeathNotifier.clear();
}
notify = new AMessage(kWhatOMXMessageList, mCodec);
@@ -7858,11 +7804,7 @@
mCodec->mBuffers[kPortIndexOutput].size());
err = FAILED_TRANSACTION;
} else {
- if (mCodec->getTrebleFlag()) {
- mCodec->mAllocator[kPortIndexOutput].clear();
- } else {
- mCodec->mDealer[kPortIndexOutput].clear();
- }
+ mCodec->mAllocator[kPortIndexOutput].clear();
}
if (err == OK) {
@@ -8464,12 +8406,4 @@
return OK;
}
-void ACodec::setTrebleFlag(bool trebleFlag) {
- mTrebleFlag = trebleFlag;
-}
-
-bool ACodec::getTrebleFlag() const {
- return mTrebleFlag;
-}
-
} // namespace android
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 7ba4b7d..0c71487 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -100,8 +100,10 @@
"libui",
"libutils",
"libmedia_helper",
- "libstagefright_omx_utils",
"libstagefright_foundation",
+ "libstagefright_omx",
+ "libstagefright_omx_utils",
+ "libstagefright_xmlparser",
"libdl",
"libRScpp",
"libhidlbase",
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 4feba37..54265a4 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -24,7 +24,6 @@
#include <media/IMediaCodecList.h>
#include <media/IMediaPlayerService.h>
-#include <media/IMediaCodecService.h>
#include <media/MediaCodecInfo.h>
#include <media/stagefright/foundation/ADebug.h>
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index 5f50e46..9375de1 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -25,7 +25,6 @@
#include <cutils/properties.h>
#include <binder/IServiceManager.h>
-#include <media/IMediaCodecService.h>
#include <media/stagefright/OMXClient.h>
#include <media/IOMX.h>
@@ -38,70 +37,25 @@
}
status_t OMXClient::connect() {
- return connect("default", nullptr);
+ return connect("default");
}
-status_t OMXClient::connect(bool* trebleFlag) {
- if (property_get_bool("persist.media.treble_omx", true)) {
- if (trebleFlag != nullptr) {
- *trebleFlag = true;
- }
- return connectTreble();
- }
- if (trebleFlag != nullptr) {
- *trebleFlag = false;
- }
- return connectLegacy();
-}
-
-status_t OMXClient::connect(const char* name, bool* trebleFlag) {
- if (property_get_bool("persist.media.treble_omx", true)) {
- if (trebleFlag != nullptr) {
- *trebleFlag = true;
- }
- return connectTreble(name);
- }
- if (trebleFlag != nullptr) {
- *trebleFlag = false;
- }
- return connectLegacy();
-}
-
-status_t OMXClient::connectLegacy() {
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> codecbinder = sm->getService(String16("media.codec"));
- sp<IMediaCodecService> codecservice = interface_cast<IMediaCodecService>(codecbinder);
-
- if (codecservice.get() == NULL) {
- ALOGE("Cannot obtain IMediaCodecService");
- return NO_INIT;
- }
-
- mOMX = codecservice->getOMX();
- if (mOMX.get() == NULL) {
- ALOGE("Cannot obtain mediacodec IOMX");
- return NO_INIT;
- }
-
- return OK;
-}
-
-status_t OMXClient::connectTreble(const char* name) {
+status_t OMXClient::connect(const char* name) {
using namespace ::android::hardware::media::omx::V1_0;
if (name == nullptr) {
name = "default";
}
sp<IOmx> tOmx = IOmx::getService(name);
if (tOmx.get() == nullptr) {
- ALOGE("Cannot obtain Treble IOmx.");
+ ALOGE("Cannot obtain IOmx service.");
return NO_INIT;
}
if (!tOmx->isRemote()) {
- ALOGE("Treble IOmx is in passthrough mode.");
+ ALOGE("IOmx service running in passthrough mode.");
return NO_INIT;
}
mOMX = new utils::LWOmx(tOmx);
- ALOGI("Treble IOmx obtained");
+ ALOGI("IOmx service obtained");
return OK;
}
@@ -109,4 +63,8 @@
mOMX.clear();
}
+sp<IOMX> OMXClient::interface() {
+ return mOMX;
+}
+
} // namespace android
diff --git a/media/libstagefright/OmxInfoBuilder.cpp b/media/libstagefright/OmxInfoBuilder.cpp
index 063d13e..a6ebadd 100644
--- a/media/libstagefright/OmxInfoBuilder.cpp
+++ b/media/libstagefright/OmxInfoBuilder.cpp
@@ -24,8 +24,6 @@
#include <utils/Log.h>
#include <cutils/properties.h>
-#include <binder/IServiceManager.h>
-#include <media/IMediaCodecService.h>
#include <media/stagefright/foundation/MediaDefs.h>
#include <media/stagefright/OmxInfoBuilder.h>
#include <media/stagefright/ACodec.h>
@@ -35,9 +33,9 @@
#include <android/hardware/media/omx/1.0/IOmxNode.h>
#include <media/stagefright/omx/OMXUtils.h>
-#include <media/IOMXStore.h>
#include <media/IOMX.h>
#include <media/omx/1.0/WOmx.h>
+#include <media/stagefright/omx/1.0/OmxStore.h>
#include <media/openmax/OMX_Index.h>
#include <media/openmax/OMX_IndexExt.h>
@@ -48,10 +46,18 @@
namespace android {
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using namespace ::android::hardware::media::omx::V1_0;
+
namespace /* unnamed */ {
+bool hasPrefix(const hidl_string& s, const char* prefix) {
+ return strncmp(s.c_str(), prefix, strlen(prefix)) == 0;
+}
+
status_t queryCapabilities(
- const IOMXStore::NodeInfo& node, const char* mime, bool isEncoder,
+ const IOmxStore::NodeInfo& node, const char* mime, bool isEncoder,
MediaCodecInfo::CapabilitiesWriter* caps) {
sp<ACodec> codec = new ACodec();
status_t err = codec->queryCapabilities(
@@ -62,14 +68,13 @@
for (const auto& attribute : node.attributes) {
// All features have an int32 value except
// "feature-bitrate-modes", which has a string value.
- if ((attribute.key.compare(0, 8, "feature-") == 0) &&
- (attribute.key.compare(8, 15, "bitrate-modes")
- != 0)) {
- // If this attribute.key is a feature that is not a bitrate
- // control, add an int32 value.
+ if (hasPrefix(attribute.key, "feature-") &&
+ !hasPrefix(attribute.key, "feature-bitrate-modes")) {
+ // If this attribute.key is a feature that is not bitrate modes,
+ // add an int32 value.
caps->addDetail(
attribute.key.c_str(),
- attribute.value == "1" ? 1 : 0);
+ hasPrefix(attribute.value, "1") ? 1 : 0);
} else {
// Non-feature attributes
caps->addDetail(
@@ -85,138 +90,70 @@
}
status_t OmxInfoBuilder::buildMediaCodecList(MediaCodecListWriter* writer) {
- bool treble;
- sp<IOMX> omx;
- std::vector<IOMXStore::RoleInfo> roles;
+ // Obtain IOmxStore
+ sp<IOmxStore> omxStore = IOmxStore::getService();
+ if (omxStore == nullptr) {
+ ALOGE("Cannot find an IOmxStore service.");
+ return NO_INIT;
+ }
- treble = property_get_bool("persist.media.treble_omx", true);
- if (treble) {
- using namespace ::android::hardware::media::omx::V1_0;
- using ::android::hardware::hidl_vec;
- using ::android::hardware::hidl_string;
-
- // Obtain IOmxStore
- sp<IOmxStore> omxStore = IOmxStore::getService();
+ // List service attributes (global settings)
+ Status status;
+ hidl_vec<IOmxStore::RoleInfo> roles;
+ auto transStatus = omxStore->listRoles(
+ [&roles] (
+ const hidl_vec<IOmxStore::RoleInfo>& inRoleList) {
+ roles = inRoleList;
+ });
+ if (!transStatus.isOk()) {
+ ALOGE("Fail to obtain codec roles from IOmxStore.");
+ return NO_INIT;
+ } else if (roles.size() == 0) {
+ ALOGW("IOmxStore has empty implementation. "
+ "Creating a local default instance...");
+ omxStore = new implementation::OmxStore();
if (omxStore == nullptr) {
- ALOGE("Cannot connect to an IOmxStore instance.");
+ ALOGE("Cannot create a local default instance.");
return NO_INIT;
}
-
- // List service attributes (global settings)
- Status status;
- hidl_vec<IOmxStore::ServiceAttribute> serviceAttributes;
- auto transStatus = omxStore->listServiceAttributes(
- [&status, &serviceAttributes]
- (Status inStatus, const hidl_vec<IOmxStore::ServiceAttribute>&
- inAttributes) {
- status = inStatus;
- serviceAttributes = inAttributes;
- });
- if (!transStatus.isOk()) {
- ALOGE("Fail to obtain global settings from IOmxStore.");
- return NO_INIT;
- }
- if (status != Status::OK) {
- ALOGE("IOmxStore reports parsing error.");
- return NO_INIT;
- }
- for (const auto& p : serviceAttributes) {
- writer->addGlobalSetting(
- p.key.c_str(), p.value.c_str());
- }
-
- // List roles and convert to IOMXStore's format
+ ALOGI("IOmxStore local default instance created.");
transStatus = omxStore->listRoles(
- [&roles]
- (const hidl_vec<IOmxStore::RoleInfo>& inRoleList) {
- roles.reserve(inRoleList.size());
- for (const auto& inRole : inRoleList) {
- IOMXStore::RoleInfo role;
- role.role = inRole.role;
- role.type = inRole.type;
- role.isEncoder = inRole.isEncoder;
- role.preferPlatformNodes = inRole.preferPlatformNodes;
- std::vector<IOMXStore::NodeInfo>& nodes =
- role.nodes;
- nodes.reserve(inRole.nodes.size());
- for (const auto& inNode : inRole.nodes) {
- IOMXStore::NodeInfo node;
- node.name = inNode.name;
- node.owner = inNode.owner;
- std::vector<IOMXStore::Attribute>& attributes =
- node.attributes;
- attributes.reserve(inNode.attributes.size());
- for (const auto& inAttr : inNode.attributes) {
- IOMXStore::Attribute attr;
- attr.key = inAttr.key;
- attr.value = inAttr.value;
- attributes.push_back(std::move(attr));
- }
- nodes.push_back(std::move(node));
- }
- roles.push_back(std::move(role));
- }
+ [&roles] (
+ const hidl_vec<IOmxStore::RoleInfo>& inRoleList) {
+ roles = inRoleList;
});
if (!transStatus.isOk()) {
- ALOGE("Fail to obtain codec roles from IOmxStore.");
- return NO_INIT;
- }
- } else {
- // Obtain IOMXStore
- sp<IServiceManager> sm = defaultServiceManager();
- if (sm == nullptr) {
- ALOGE("Cannot obtain the default service manager.");
- return NO_INIT;
- }
- sp<IBinder> codecBinder = sm->getService(String16("media.codec"));
- if (codecBinder == nullptr) {
- ALOGE("Cannot obtain the media codec service.");
- return NO_INIT;
- }
- sp<IMediaCodecService> codecService =
- interface_cast<IMediaCodecService>(codecBinder);
- if (codecService == nullptr) {
- ALOGE("Wrong type of media codec service obtained.");
- return NO_INIT;
- }
- omx = codecService->getOMX();
- if (omx == nullptr) {
- ALOGE("Cannot connect to an IOMX instance.");
- }
- sp<IOMXStore> omxStore = codecService->getOMXStore();
- if (omxStore == nullptr) {
- ALOGE("Cannot connect to an IOMXStore instance.");
- return NO_INIT;
- }
-
- // List service attributes (global settings)
- std::vector<IOMXStore::Attribute> serviceAttributes;
- status_t status = omxStore->listServiceAttributes(&serviceAttributes);
- if (status != OK) {
- ALOGE("Fail to obtain global settings from IOMXStore.");
- return NO_INIT;
- }
- for (const auto& p : serviceAttributes) {
- writer->addGlobalSetting(
- p.key.c_str(), p.value.c_str());
- }
-
- // List roles
- status = omxStore->listRoles(&roles);
- if (status != OK) {
- ALOGE("Fail to obtain codec roles from IOMXStore.");
+ ALOGE("Fail to obtain codec roles from local IOmxStore.");
return NO_INIT;
}
}
+ hidl_vec<IOmxStore::ServiceAttribute> serviceAttributes;
+ transStatus = omxStore->listServiceAttributes(
+ [&status, &serviceAttributes] (
+ Status inStatus,
+ const hidl_vec<IOmxStore::ServiceAttribute>& inAttributes) {
+ status = inStatus;
+ serviceAttributes = inAttributes;
+ });
+ if (!transStatus.isOk()) {
+ ALOGE("Fail to obtain global settings from IOmxStore.");
+ return NO_INIT;
+ }
+ if (status != Status::OK) {
+ ALOGE("IOmxStore reports parsing error.");
+ return NO_INIT;
+ }
+ for (const auto& p : serviceAttributes) {
+ writer->addGlobalSetting(
+ p.key.c_str(), p.value.c_str());
+ }
+
// Convert roles to lists of codecs
- // codec name -> index into swCodecs
- std::map<std::string, std::unique_ptr<MediaCodecInfoWriter> >
- swCodecName2Info;
- // codec name -> index into hwCodecs
- std::map<std::string, std::unique_ptr<MediaCodecInfoWriter> >
- hwCodecName2Info;
+ // codec name -> index into swCodecs/hwCodecs
+ std::map<hidl_string, std::unique_ptr<MediaCodecInfoWriter>>
+ swCodecName2Info, hwCodecName2Info;
// owner name -> MediaCodecInfo
// This map will be used to obtain the correct IOmx service(s) needed for
// creating IOmxNode instances and querying capabilities.
@@ -230,10 +167,10 @@
// If preferPlatformNodes is true, hardware nodes must be added after
// platform (software) nodes. hwCodecs is used to hold hardware nodes
// that need to be added after software nodes for the same role.
- std::vector<const IOMXStore::NodeInfo*> hwCodecs;
+ std::vector<const IOmxStore::NodeInfo*> hwCodecs;
for (const auto& node : role.nodes) {
const auto& nodeName = node.name;
- bool isSoftware = nodeName.compare(0, 10, "OMX.google") == 0;
+ bool isSoftware = hasPrefix(nodeName, "OMX.google");
MediaCodecInfoWriter* info;
if (isSoftware) {
auto c2i = swCodecName2Info.find(nodeName);
diff --git a/media/libstagefright/codec2/Android.bp b/media/libstagefright/codec2/Android.bp
index f79e058..311a20b 100644
--- a/media/libstagefright/codec2/Android.bp
+++ b/media/libstagefright/codec2/Android.bp
@@ -17,9 +17,9 @@
"unsigned-integer-overflow",
"signed-integer-overflow",
],
- cfi: true,
+ cfi: false, // true,
diag: {
- cfi: true,
+ cfi: false, // true,
},
},
diff --git a/media/libstagefright/codec2/include/C2Buffer.h b/media/libstagefright/codec2/include/C2Buffer.h
index cb8c2d2..22e4360 100644
--- a/media/libstagefright/codec2/include/C2Buffer.h
+++ b/media/libstagefright/codec2/include/C2Buffer.h
@@ -1529,17 +1529,71 @@
class C2Allocator {
public:
/**
+ * Allocator ID type.
+ */
+ typedef uint32_t id_t;
+
+ /**
+ * Allocation types. This is a bitmask and is used in C2Allocator::Info
+ * to list the supported allocation types of an allocator.
+ */
+ enum type_t : uint32_t {
+ LINEAR = 1 << 0, //
+ GRAPHIC = 1 << 1,
+ };
+
+ /**
+ * Information about an allocator.
+ */
+ struct Info {
+ C2String name; ///< allocator name
+ id_t id; ///< allocator ID
+ type_t supportedTypes; ///< supported allocation types
+ C2MemoryUsage minimumUsage; ///< usage that is minimally required for allocations
+ C2MemoryUsage maximumUsage; ///< usage that is maximally allowed for allocations
+ };
+
+ /**
+ * Returns the unique name of this allocator.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \return the name of this allocator.
+ * \retval an empty string if there was not enough memory to allocate the actual name.
+ */
+ virtual C2String getName() const = 0;
+
+ /**
+ * Returns a unique ID for this allocator. This ID is used to get this allocator from the
+ * allocator store, and to identify this allocator across all processes.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \return a unique ID for this allocator.
+ */
+ virtual id_t getId() const = 0;
+
+ /**
+ * Returns the allocator information.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \return allocator information
+ */
+ virtual std::shared_ptr<const Info> getInfo() const = 0;
+
+ /**
* Allocates a 1D allocation of given |capacity| and |usage|. If successful, the allocation is
* stored in |allocation|. Otherwise, |allocation| is set to 'nullptr'.
*
- * \param capacity the size of requested allocation (the allocation could be slightly
+ * \param capacity the size of requested allocation (the allocation could be slightly
* larger, e.g. to account for any system-required alignment)
- * \param usage the memory usage info for the requested allocation. \note that the
+ * \param usage the memory usage info for the requested allocation. \note that the
* returned allocation may be later used/mapped with different usage.
* The allocator should layout the buffer to be optimized for this usage,
* but must support any usage. One exception: protected buffers can
* only be used in a protected scenario.
- * \param allocation pointer to where the allocation shall be stored on success. nullptr
+ * \param allocation pointer to where the allocation shall be stored on success. nullptr
* will be stored here on failure
*
* \retval C2_OK the allocation was successful
@@ -1550,7 +1604,7 @@
* \retval C2_OMITTED this allocator does not support 1D allocations
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
*/
- virtual C2Status allocateLinearBuffer(
+ virtual C2Status newLinearAllocation(
uint32_t capacity __unused, C2MemoryUsage usage __unused,
std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) {
*allocation = nullptr;
@@ -1563,7 +1617,7 @@
*
* \param handle the handle for the existing allocation
* \param allocation pointer to where the allocation shall be stored on success. nullptr
- * will be stored here on failure
+ * will be stored here on failure
*
* \retval C2_OK the allocation was recreated successfully
* \retval C2_NO_MEMORY not enough memory to recreate the allocation
@@ -1573,7 +1627,7 @@
* \retval C2_OMITTED this allocator does not support 1D allocations
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
*/
- virtual C2Status recreateLinearBuffer(
+ virtual C2Status priorLinearAllocation(
const C2Handle *handle __unused,
std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) {
*allocation = nullptr;
@@ -1584,18 +1638,18 @@
* Allocates a 2D allocation of given |width|, |height|, |format| and |usage|. If successful,
* the allocation is stored in |allocation|. Otherwise, |allocation| is set to 'nullptr'.
*
- * \param width the width of requested allocation (the allocation could be slightly
+ * \param width the width of requested allocation (the allocation could be slightly
* larger, e.g. to account for any system-required alignment)
- * \param height the height of requested allocation (the allocation could be slightly
+ * \param height the height of requested allocation (the allocation could be slightly
* larger, e.g. to account for any system-required alignment)
- * \param format the pixel format of requested allocation. This could be a vendor
+ * \param format the pixel format of requested allocation. This could be a vendor
* specific format.
- * \param usage the memory usage info for the requested allocation. \note that the
+ * \param usage the memory usage info for the requested allocation. \note that the
* returned allocation may be later used/mapped with different usage.
* The allocator should layout the buffer to be optimized for this usage,
* but must support any usage. One exception: protected buffers can
* only be used in a protected scenario.
- * \param allocation pointer to where the allocation shall be stored on success. nullptr
+ * \param allocation pointer to where the allocation shall be stored on success. nullptr
* will be stored here on failure
*
* \retval C2_OK the allocation was successful
@@ -1606,7 +1660,7 @@
* \retval C2_OMITTED this allocator does not support 2D allocations
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
*/
- virtual C2Status allocateGraphicBuffer(
+ virtual C2Status newGraphicAllocation(
uint32_t width __unused, uint32_t height __unused, uint32_t format __unused,
C2MemoryUsage usage __unused,
std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) {
@@ -1620,7 +1674,7 @@
*
* \param handle the handle for the existing allocation
* \param allocation pointer to where the allocation shall be stored on success. nullptr
- * will be stored here on failure
+ * will be stored here on failure
*
* \retval C2_OK the allocation was recreated successfully
* \retval C2_NO_MEMORY not enough memory to recreate the allocation
@@ -1630,7 +1684,7 @@
* \retval C2_OMITTED this allocator does not support 2D allocations
* \retval C2_CORRUPTED some unknown, unrecoverable error occured during recreation (unexpected)
*/
- virtual C2Status recreateGraphicBuffer(
+ virtual C2Status priorGraphicAllocation(
const C2Handle *handle __unused,
std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) {
*allocation = nullptr;
@@ -1644,37 +1698,73 @@
};
/**
- * Block allocators are used by components to allocate memory for output buffers. They can
- * support either linear (1D), circular (1D) or graphic (2D) allocations.
+ * Block pools are used by components to obtain output buffers in an efficient way. They can
+ * support either linear (1D), circular (1D) or graphic (2D) blocks.
+ *
+ * Block pools decouple the recycling of memory/allocations from the components. They are meant to
+ * be an opaque service (there are no public APIs other than obtaining blocks) provided by the
+ * platform. Block pools are also meant to decouple allocations from memory used by buffers. This
+ * is accomplished by allowing pools to allot multiple memory 'blocks' on a single allocation. As
+ * their name suggest, block pools maintain a pool of memory blocks. When a component asks for
+ * a memory block, pools will try to return a free memory block already in the pool. If no such
+ * block exists, they will allocate memory using the backing allocator and allot a block on that
+ * allocation. When blocks are no longer used in the system, they are recycled back to the block
+ * pool and are available as free blocks.
*
* Never constructed on stack.
- *
- * Block allocators are provided by the framework.
*/
-class C2BlockAllocator {
+class C2BlockPool {
public:
/**
- * Allocates a linear writeable block of given |capacity| and |usage|. If successful, the
+ * Block pool ID type.
+ */
+ typedef uint64_t local_id_t;
+
+ enum : local_id_t {
+ BASIC_LINEAR = 0, ///< ID of basic (unoptimized) block pool for fetching 1D blocks
+ BASIC_GRAPHIC = 1, ///< ID of basic (unoptimized) block pool for fetching 2D blocks
+ PLATFORM_START = 0x10,
+ };
+
+ /**
+ * Returns the ID for this block pool. This ID is used to get this block pool from the platform.
+ * It is only valid in the current process.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \return a local ID for this block pool.
+ */
+ virtual local_id_t getLocalId() const = 0;
+
+ /**
+ * Returns the ID of the backing allocator of this block pool.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \return the ID of the backing allocator of this block pool.
+ */
+ virtual C2Allocator::id_t getAllocatorId() const = 0;
+
+ /**
+ * Obtains a linear writeable block of given |capacity| and |usage|. If successful, the
* block is stored in |block|. Otherwise, |block| is set to 'nullptr'.
*
- * \param capacity the size of requested block.
- * \param usage the memory usage info for the requested allocation. \note that the
- * returned allocation may be later used/mapped with different usage.
- * The allocator shall lay out the buffer to be optimized for this usage,
- * but must support any usage. One exception: protected buffers can
- * only be used in a protected scenario.
- * \param block pointer to where the allocated block shall be stored on success. nullptr
- * will be stored here on failure
+ * \param capacity the size of requested block.
+ * \param usage the memory usage info for the requested block. Returned blocks will be
+ * optimized for this usage, but may be used with any usage. One exception:
+ * protected blocks/buffers can only be used in a protected scenario.
+ * \param block pointer to where the obtained block shall be stored on success. nullptr will
+ * be stored here on failure
*
- * \retval C2_OK the allocation was successful
- * \retval C2_NO_MEMORY not enough memory to complete the allocation
- * \retval C2_TIMED_OUT the allocation timed out
- * \retval C2_REFUSED no permission to complete the allocation
+ * \retval C2_OK the operation was successful
+ * \retval C2_NO_MEMORY not enough memory to complete any required allocation
+ * \retval C2_TIMED_OUT the operation timed out
+ * \retval C2_REFUSED no permission to complete any required allocation
* \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
- * \retval C2_OMITTED this allocator does not support linear allocations
- * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
+ * \retval C2_OMITTED this pool does not support linear blocks
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected)
*/
- virtual C2Status allocateLinearBlock(
+ virtual C2Status fetchLinearBlock(
uint32_t capacity __unused, C2MemoryUsage usage __unused,
std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
*block = nullptr;
@@ -1682,28 +1772,27 @@
}
/**
- * Allocates a circular writeable block of given |capacity| and |usage|. If successful, the
+ * Obtains a circular writeable block of given |capacity| and |usage|. If successful, the
* block is stored in |block|. Otherwise, |block| is set to 'nullptr'.
*
- * \param capacity the size of requested circular block. (the allocation could be slightly
- * larger, e.g. to account for any system-required alignment)
- * \param usage the memory usage info for the requested allocation. \note that the
- * returned allocation may be later used/mapped with different usage.
- * The allocator shall lay out the buffer to be optimized for this usage,
- * but must support any usage. One exception: protected buffers can
- * only be used in a protected scenario.
- * \param block pointer to where the allocated block shall be stored on success. nullptr
- * will be stored here on failure
+ * \param capacity the size of requested circular block. (note: the size of the obtained
+ * block could be slightly larger, e.g. to accommodate any system-required
+ * alignment)
+ * \param usage the memory usage info for the requested block. Returned blocks will be
+ * optimized for this usage, but may be used with any usage. One exception:
+ * protected blocks/buffers can only be used in a protected scenario.
+ * \param block pointer to where the obtained block shall be stored on success. nullptr
+ * will be stored here on failure
*
- * \retval C2_OK the allocation was successful
- * \retval C2_NO_MEMORY not enough memory to complete the allocation
- * \retval C2_TIMED_OUT the allocation timed out
- * \retval C2_REFUSED no permission to complete the allocation
- * \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
- * \retval C2_OMITTED this allocator does not support circular allocations
- * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
+ * \retval C2_OK the operation was successful
+ * \retval C2_NO_MEMORY not enough memory to complete any required allocation
+ * \retval C2_TIMED_OUT the operation timed out
+ * \retval C2_REFUSED no permission to complete any required allocation
+ * \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
+ * \retval C2_OMITTED this pool does not support circular blocks
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected)
*/
- virtual C2Status allocateCircularBlock(
+ virtual C2Status fetchCircularBlock(
uint32_t capacity __unused, C2MemoryUsage usage __unused,
std::shared_ptr<C2CircularBlock> *block /* nonnull */) {
*block = nullptr;
@@ -1711,32 +1800,30 @@
}
/**
- * Allocates a 2D graphic block of given |width|, |height|, |format| and |usage|. If successful,
- * the allocation is stored in |block|. Otherwise, |block| is set to 'nullptr'.
+ * Obtains a 2D graphic block of given |width|, |height|, |format| and |usage|. If successful,
+ * the block is stored in |block|. Otherwise, |block| is set to 'nullptr'.
*
- * \param width the width of requested allocation (the allocation could be slightly
- * larger, e.g. to account for any system-required alignment)
- * \param height the height of requested allocation (the allocation could be slightly
- * larger, e.g. to account for any system-required alignment)
- * \param format the pixel format of requested allocation. This could be a vendor
- * specific format.
- * \param usage the memory usage info for the requested allocation. \note that the
- * returned allocation may be later used/mapped with different usage.
- * The allocator should layout the buffer to be optimized for this usage,
- * but must support any usage. One exception: protected buffers can
- * only be used in a protected scenario.
- * \param block pointer to where the allocation shall be stored on success. nullptr
- * will be stored here on failure
+ * \param width the width of requested block (the obtained block could be slightly larger, e.g.
+ * to accommodate any system-required alignment)
+ * \param height the height of requested block (the obtained block could be slightly larger,
+ * e.g. to accommodate any system-required alignment)
+ * \param format the pixel format of requested block. This could be a vendor specific format.
+ * \param usage the memory usage info for the requested block. Returned blocks will be
+ * optimized for this usage, but may be used with any usage. One exception:
+ * protected blocks/buffers can only be used in a protected scenario.
+ * \param block pointer to where the obtained block shall be stored on success. nullptr
+ * will be stored here on failure
*
- * \retval C2_OK the allocation was successful
- * \retval C2_NO_MEMORY not enough memory to complete the allocation
- * \retval C2_TIMED_OUT the allocation timed out
- * \retval C2_REFUSED no permission to complete the allocation
- * \retval C2_BAD_VALUE width, height, format or usage are not supported (invalid) (caller error)
- * \retval C2_OMITTED this allocator does not support 2D allocations
- * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
+ * \retval C2_OK the operation was successful
+ * \retval C2_NO_MEMORY not enough memory to complete any required allocation
+ * \retval C2_TIMED_OUT the operation timed out
+ * \retval C2_REFUSED no permission to complete any required allocation
+ * \retval C2_BAD_VALUE width, height, format or usage are not supported (invalid) (caller
+ * error)
+ * \retval C2_OMITTED this pool does not support 2D blocks
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected)
*/
- virtual C2Status allocateGraphicBlock(
+ virtual C2Status fetchGraphicBlock(
uint32_t width __unused, uint32_t height __unused, uint32_t format __unused,
C2MemoryUsage usage __unused,
std::shared_ptr<C2GraphicBlock> *block /* nonnull */) {
@@ -1745,9 +1832,9 @@
}
protected:
- C2BlockAllocator() = default;
+ C2BlockPool() = default;
- virtual ~C2BlockAllocator() = default;
+ virtual ~C2BlockPool() = default;
};
/// @}
diff --git a/media/libstagefright/codec2/include/C2Component.h b/media/libstagefright/codec2/include/C2Component.h
index 2ac9c72..c88de62 100644
--- a/media/libstagefright/codec2/include/C2Component.h
+++ b/media/libstagefright/codec2/include/C2Component.h
@@ -542,11 +542,9 @@
class C2AllocatorStore {
public:
- // TBD
+ typedef C2Allocator::id_t id_t;
- typedef uint32_t ID;
-
- enum ID_ : uint32_t {
+ enum : C2Allocator::id_t {
DEFAULT_LINEAR, ///< basic linear allocator type
DEFAULT_GRAPHIC, ///< basic graphic allocator type
PLATFORM_START = 0x10,
@@ -554,7 +552,30 @@
};
/**
- * Creates an allocator.
+ * Returns the unique name of this allocator store.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \return the name of this allocator store.
+ * \retval an empty string if there was not enough memory to allocate the actual name.
+ */
+ virtual C2String getName() const = 0;
+
+ /**
+ * Returns the set of allocators supported by this allocator store.
+ *
+ * This method SHALL return within 1ms.
+ *
+ * \retval vector of allocator information (as shared pointers)
+ * \retval an empty vector if there was not enough memory to allocate the whole vector.
+ */
+ virtual std::vector<std::shared_ptr<const C2Allocator::Info>> listAllocators() const = 0;
+
+ /**
+ * Retrieves/creates a shared allocator object.
+ *
+ * The allocator is created on first use, and the same allocator is returned on subsequent
+ * concurrent uses in the same process. The allocator is freed when it is no longer referenced.
*
* \param id the ID of the allocator to create. This is defined by the store, but
* the ID of the default linear and graphic allocators is formalized.
@@ -568,7 +589,7 @@
* \retval C2_NOT_FOUND no such allocator
* \retval C2_NO_MEMORY not enough memory to create the allocator
*/
- virtual C2Status createAllocator(ID id, std::shared_ptr<C2Allocator>* const allocator) = 0;
+ virtual C2Status getAllocator(id_t id, std::shared_ptr<C2Allocator>* const allocator) = 0;
virtual ~C2AllocatorStore() = default;
};
diff --git a/media/libstagefright/codec2/include/C2Config.h b/media/libstagefright/codec2/include/C2Config.h
index d4294c4..0568432 100644
--- a/media/libstagefright/codec2/include/C2Config.h
+++ b/media/libstagefright/codec2/include/C2Config.h
@@ -61,13 +61,15 @@
kParamIndexMime,
kParamIndexStreamCount,
kParamIndexFormat,
+ kParamIndexBlockPools,
+
+ kParamIndexMaxVideoSizeHint,
+ kParamIndexVideoSizeTuning,
// video info
kParamIndexStructStart = 0x1,
kParamIndexVideoSize,
- kParamIndexMaxVideoSizeHint,
- kParamIndexVideoSizeTuning,
kParamIndexParamStart = 0x800,
};
@@ -125,6 +127,8 @@
typedef C2StreamParam<C2Tuning, C2Uint32Value, kParamIndexFormat> C2StreamFormatConfig;
+typedef C2PortParam<C2Tuning, C2Uint64Array, kParamIndexBlockPools> C2PortBlockPoolsTuning;
+
/*
Component description fields:
diff --git a/media/libstagefright/codec2/include/C2Work.h b/media/libstagefright/codec2/include/C2Work.h
index 69c16ab..52c00d5 100644
--- a/media/libstagefright/codec2/include/C2Work.h
+++ b/media/libstagefright/codec2/include/C2Work.h
@@ -118,8 +118,8 @@
std::list<std::unique_ptr<C2Param>> tunings; //< tunings to be applied before processing this
// worklet
std::list<C2Param::Type> requestedInfos;
- std::vector<std::shared_ptr<C2BlockAllocator>> allocators; //< This vector shall be the same size as
- //< output.buffers.
+ std::vector<std::shared_ptr<C2BlockPool>> allocators; //< This vector shall be the same size as
+ //< output.buffers. \deprecated
// OUT
C2BufferPack output;
diff --git a/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp b/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
index 8c78334..3d23c23 100644
--- a/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
+++ b/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
@@ -38,13 +38,13 @@
~C2BufferTest() = default;
void allocateLinear(size_t capacity) {
- C2Status err = mLinearAllocator->allocateLinearBuffer(
+ C2Status err = mLinearAllocator->newLinearAllocation(
capacity,
{ C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
&mLinearAllocation);
if (err != C2_OK) {
mLinearAllocation.reset();
- FAIL() << "C2Allocator::allocateLinearBuffer() failed: " << err;
+ FAIL() << "C2Allocator::newLinearAllocation() failed: " << err;
}
}
@@ -77,12 +77,12 @@
mAddr = nullptr;
}
- std::shared_ptr<C2BlockAllocator> makeLinearBlockAllocator() {
- return std::make_shared<C2DefaultBlockAllocator>(mLinearAllocator);
+ std::shared_ptr<C2BlockPool> makeLinearBlockPool() {
+ return std::make_shared<C2BasicLinearBlockPool>(mLinearAllocator);
}
void allocateGraphic(uint32_t width, uint32_t height) {
- C2Status err = mGraphicAllocator->allocateGraphicBuffer(
+ C2Status err = mGraphicAllocator->newGraphicAllocation(
width,
height,
HAL_PIXEL_FORMAT_YCBCR_420_888,
@@ -90,7 +90,7 @@
&mGraphicAllocation);
if (err != C2_OK) {
mGraphicAllocation.reset();
- FAIL() << "C2Allocator::allocateLinearBuffer() failed: " << err;
+ FAIL() << "C2Allocator::newGraphicAllocation() failed: " << err;
}
}
@@ -118,8 +118,8 @@
ASSERT_EQ(C2_OK, mGraphicAllocation->unmap(nullptr));
}
- std::shared_ptr<C2BlockAllocator> makeGraphicBlockAllocator() {
- return std::make_shared<C2DefaultGraphicBlockAllocator>(mGraphicAllocator);
+ std::shared_ptr<C2BlockPool> makeGraphicBlockPool() {
+ return std::make_shared<C2BasicGraphicBlockPool>(mGraphicAllocator);
}
private:
@@ -155,13 +155,13 @@
}
}
-TEST_F(C2BufferTest, BlockAllocatorTest) {
+TEST_F(C2BufferTest, BlockPoolTest) {
constexpr size_t kCapacity = 1024u * 1024u;
- std::shared_ptr<C2BlockAllocator> blockAllocator(makeLinearBlockAllocator());
+ std::shared_ptr<C2BlockPool> blockPool(makeLinearBlockPool());
std::shared_ptr<C2LinearBlock> block;
- ASSERT_EQ(C2_OK, blockAllocator->allocateLinearBlock(
+ ASSERT_EQ(C2_OK, blockPool->fetchLinearBlock(
kCapacity,
{ C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
&block));
@@ -285,14 +285,14 @@
ASSERT_TRUE(verifyPlane({ 0, 0, kWidth / 4, kHeight }, vInfo, v, 0));
}
-TEST_F(C2BufferTest, GraphicBlockAllocatorTest) {
+TEST_F(C2BufferTest, GraphicBlockPoolTest) {
constexpr uint32_t kWidth = 320;
constexpr uint32_t kHeight = 240;
- std::shared_ptr<C2BlockAllocator> blockAllocator(makeGraphicBlockAllocator());
+ std::shared_ptr<C2BlockPool> blockPool(makeGraphicBlockPool());
std::shared_ptr<C2GraphicBlock> block;
- ASSERT_EQ(C2_OK, blockAllocator->allocateGraphicBlock(
+ ASSERT_EQ(C2_OK, blockPool->fetchGraphicBlock(
kWidth,
kHeight,
HAL_PIXEL_FORMAT_YCBCR_420_888,
@@ -370,8 +370,8 @@
};
TEST_F(C2BufferTest, BufferDataTest) {
- std::shared_ptr<C2BlockAllocator> linearBlockAllocator(makeLinearBlockAllocator());
- std::shared_ptr<C2BlockAllocator> graphicBlockAllocator(makeGraphicBlockAllocator());
+ std::shared_ptr<C2BlockPool> linearBlockPool(makeLinearBlockPool());
+ std::shared_ptr<C2BlockPool> graphicBlockPool(makeGraphicBlockPool());
constexpr uint32_t kWidth1 = 320;
constexpr uint32_t kHeight1 = 240;
@@ -384,23 +384,23 @@
std::shared_ptr<C2LinearBlock> linearBlock1;
std::shared_ptr<C2LinearBlock> linearBlock2;
- ASSERT_EQ(C2_OK, linearBlockAllocator->allocateLinearBlock(
+ ASSERT_EQ(C2_OK, linearBlockPool->fetchLinearBlock(
kCapacity1,
{ C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
&linearBlock1));
- ASSERT_EQ(C2_OK, linearBlockAllocator->allocateLinearBlock(
+ ASSERT_EQ(C2_OK, linearBlockPool->fetchLinearBlock(
kCapacity2,
{ C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
&linearBlock2));
std::shared_ptr<C2GraphicBlock> graphicBlock1;
std::shared_ptr<C2GraphicBlock> graphicBlock2;
- ASSERT_EQ(C2_OK, graphicBlockAllocator->allocateGraphicBlock(
+ ASSERT_EQ(C2_OK, graphicBlockPool->fetchGraphicBlock(
kWidth1,
kHeight1,
HAL_PIXEL_FORMAT_YCBCR_420_888,
{ C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
&graphicBlock1));
- ASSERT_EQ(C2_OK, graphicBlockAllocator->allocateGraphicBlock(
+ ASSERT_EQ(C2_OK, graphicBlockPool->fetchGraphicBlock(
kWidth2,
kHeight2,
HAL_PIXEL_FORMAT_YCBCR_420_888,
@@ -454,11 +454,11 @@
typedef C2GlobalParam<C2Info, C2Int32Value, kParamIndexNumber2> C2Number2Info;
TEST_F(C2BufferTest, BufferTest) {
- std::shared_ptr<C2BlockAllocator> alloc(makeLinearBlockAllocator());
+ std::shared_ptr<C2BlockPool> alloc(makeLinearBlockPool());
constexpr size_t kCapacity = 1024u;
std::shared_ptr<C2LinearBlock> block;
- ASSERT_EQ(C2_OK, alloc->allocateLinearBlock(
+ ASSERT_EQ(C2_OK, alloc->fetchLinearBlock(
kCapacity,
{ C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
&block));
diff --git a/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp b/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
index 6530cc1..3e2242b 100644
--- a/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
@@ -231,11 +231,15 @@
public:
Impl();
- C2Status allocateGraphicBuffer(
+ id_t getId() const;
+
+ C2String getName() const;
+
+ C2Status newGraphicAllocation(
uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
std::shared_ptr<C2GraphicAllocation> *allocation);
- C2Status recreateGraphicBuffer(
+ C2Status priorGraphicAllocation(
const C2Handle *handle,
std::shared_ptr<C2GraphicAllocation> *allocation);
@@ -256,7 +260,15 @@
}
}
-C2Status C2AllocatorGralloc::Impl::allocateGraphicBuffer(
+C2Allocator::id_t C2AllocatorGralloc::Impl::getId() const {
+ return 1; /// \todo implement ID
+}
+
+C2String C2AllocatorGralloc::Impl::getName() const {
+ return "android.allocator.gralloc";
+}
+
+C2Status C2AllocatorGralloc::Impl::newGraphicAllocation(
uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
std::shared_ptr<C2GraphicAllocation> *allocation) {
// TODO: buffer usage should be determined according to |usage|
@@ -307,7 +319,7 @@
return C2_OK;
}
-C2Status C2AllocatorGralloc::Impl::recreateGraphicBuffer(
+C2Status C2AllocatorGralloc::Impl::priorGraphicAllocation(
const C2Handle *handle,
std::shared_ptr<C2GraphicAllocation> *allocation) {
(void) handle;
@@ -321,16 +333,24 @@
C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; }
-C2Status C2AllocatorGralloc::allocateGraphicBuffer(
- uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
- std::shared_ptr<C2GraphicAllocation> *allocation) {
- return mImpl->allocateGraphicBuffer(width, height, format, usage, allocation);
+C2Allocator::id_t C2AllocatorGralloc::getId() const {
+ return mImpl->getId();
}
-C2Status C2AllocatorGralloc::recreateGraphicBuffer(
+C2String C2AllocatorGralloc::getName() const {
+ return mImpl->getName();
+}
+
+C2Status C2AllocatorGralloc::newGraphicAllocation(
+ uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
+ std::shared_ptr<C2GraphicAllocation> *allocation) {
+ return mImpl->newGraphicAllocation(width, height, format, usage, allocation);
+}
+
+C2Status C2AllocatorGralloc::priorGraphicAllocation(
const C2Handle *handle,
std::shared_ptr<C2GraphicAllocation> *allocation) {
- return mImpl->recreateGraphicBuffer(handle, allocation);
+ return mImpl->priorGraphicAllocation(handle, allocation);
}
C2Status C2AllocatorGralloc::status() const {
diff --git a/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp b/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
index 06b4874..09df502 100644
--- a/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
+++ b/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
@@ -294,7 +294,15 @@
}
}
-C2Status C2AllocatorIon::allocateLinearBuffer(
+C2Allocator::id_t C2AllocatorIon::getId() const {
+ return 0; /// \todo implement ID
+}
+
+C2String C2AllocatorIon::getName() const {
+ return "android.allocator.ion";
+}
+
+C2Status C2AllocatorIon::newLinearAllocation(
uint32_t capacity, C2MemoryUsage usage, std::shared_ptr<C2LinearAllocation> *allocation) {
if (allocation == nullptr) {
return C2_BAD_VALUE;
@@ -328,7 +336,7 @@
return ret;
}
-C2Status C2AllocatorIon::recreateLinearBuffer(
+C2Status C2AllocatorIon::priorLinearAllocation(
const C2Handle *handle, std::shared_ptr<C2LinearAllocation> *allocation) {
*allocation = nullptr;
if (mInit != C2_OK) {
diff --git a/media/libstagefright/codec2/vndk/C2Buffer.cpp b/media/libstagefright/codec2/vndk/C2Buffer.cpp
index d3f0d70..02e2dd9 100644
--- a/media/libstagefright/codec2/vndk/C2Buffer.cpp
+++ b/media/libstagefright/codec2/vndk/C2Buffer.cpp
@@ -61,7 +61,7 @@
class C2DefaultLinearBlock : public C2LinearBlock {
using C2LinearBlock::C2LinearBlock;
- friend class ::android::C2DefaultBlockAllocator;
+ friend class ::android::C2BasicLinearBlockPool;
};
class C2DefaultGraphicView : public C2GraphicView {
@@ -87,7 +87,7 @@
class C2DefaultGraphicBlock : public C2GraphicBlock {
using C2GraphicBlock::C2GraphicBlock;
- friend class ::android::C2DefaultGraphicBlockAllocator;
+ friend class ::android::C2BasicGraphicBlockPool;
};
class C2DefaultBufferData : public C2BufferData {
@@ -345,18 +345,18 @@
return mImpl->share(offset, size, fence);
}
-C2DefaultBlockAllocator::C2DefaultBlockAllocator(
+C2BasicLinearBlockPool::C2BasicLinearBlockPool(
const std::shared_ptr<C2Allocator> &allocator)
: mAllocator(allocator) {}
-C2Status C2DefaultBlockAllocator::allocateLinearBlock(
+C2Status C2BasicLinearBlockPool::fetchLinearBlock(
uint32_t capacity,
C2MemoryUsage usage,
std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
block->reset();
std::shared_ptr<C2LinearAllocation> alloc;
- C2Status err = mAllocator->allocateLinearBuffer(capacity, usage, &alloc);
+ C2Status err = mAllocator->newLinearAllocation(capacity, usage, &alloc);
if (err != C2_OK) {
return err;
}
@@ -575,11 +575,11 @@
return mImpl->share(crop, fence);
}
-C2DefaultGraphicBlockAllocator::C2DefaultGraphicBlockAllocator(
+C2BasicGraphicBlockPool::C2BasicGraphicBlockPool(
const std::shared_ptr<C2Allocator> &allocator)
: mAllocator(allocator) {}
-C2Status C2DefaultGraphicBlockAllocator::allocateGraphicBlock(
+C2Status C2BasicGraphicBlockPool::fetchGraphicBlock(
uint32_t width,
uint32_t height,
uint32_t format,
@@ -588,7 +588,7 @@
block->reset();
std::shared_ptr<C2GraphicAllocation> alloc;
- C2Status err = mAllocator->allocateGraphicBuffer(width, height, format, usage, &alloc);
+ C2Status err = mAllocator->newGraphicAllocation(width, height, format, usage, &alloc);
if (err != C2_OK) {
return err;
}
diff --git a/media/libstagefright/codec2/vndk/C2Store.cpp b/media/libstagefright/codec2/vndk/C2Store.cpp
index 42bdf0e..f8ddfef 100644
--- a/media/libstagefright/codec2/vndk/C2Store.cpp
+++ b/media/libstagefright/codec2/vndk/C2Store.cpp
@@ -16,6 +16,7 @@
#include <C2AllocatorGralloc.h>
#include <C2AllocatorIon.h>
+#include <C2BufferPriv.h>
#include <C2Component.h>
#include <C2PlatformSupport.h>
@@ -27,7 +28,7 @@
class C2PlatformAllocatorStore : public C2AllocatorStore {
public:
- enum ID_ : uint32_t {
+ enum : id_t {
ION = PLATFORM_START,
GRALLOC,
};
@@ -35,7 +36,16 @@
C2PlatformAllocatorStore(
/* ionmapper */
);
- virtual C2Status createAllocator(ID id, std::shared_ptr<C2Allocator> *const allocator);
+
+ virtual C2Status getAllocator(id_t id, std::shared_ptr<C2Allocator> *const allocator);
+
+ virtual std::vector<std::shared_ptr<const C2Allocator::Info>> listAllocators() const {
+ return std::vector<std::shared_ptr<const C2Allocator::Info>>(); /// \todo
+ }
+
+ virtual C2String getName() const {
+ return "android.allocator-store";
+ }
private:
// returns a shared-singleton ion allocator
@@ -48,8 +58,8 @@
C2PlatformAllocatorStore::C2PlatformAllocatorStore() {
}
-C2Status C2PlatformAllocatorStore::createAllocator(
- ID id, std::shared_ptr<C2Allocator> *const allocator) {
+C2Status C2PlatformAllocatorStore::getAllocator(
+ id_t id, std::shared_ptr<C2Allocator> *const allocator) {
allocator->reset();
switch (id) {
// TODO: should we implement a generic registry for all, and use that?
@@ -100,4 +110,35 @@
return std::make_shared<C2PlatformAllocatorStore>();
}
+C2Status GetCodec2BlockPool(
+ C2BlockPool::local_id_t id, std::shared_ptr<const C2Component> component,
+ std::shared_ptr<C2BlockPool> *pool) {
+ pool->reset();
+ if (!component) {
+ return C2_BAD_VALUE;
+ }
+ // TODO support pre-registered block pools
+ std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
+ std::shared_ptr<C2Allocator> allocator;
+ C2Status res = C2_NOT_FOUND;
+
+ switch (id) {
+ case C2BlockPool::BASIC_LINEAR:
+ res = allocatorStore->getAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
+ if (res == OK) {
+ *pool = std::make_shared<C2BasicLinearBlockPool>(allocator);
+ }
+ break;
+ case C2BlockPool::BASIC_GRAPHIC:
+ res = allocatorStore->getAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
+ if (res == OK) {
+ *pool = std::make_shared<C2BasicGraphicBlockPool>(allocator);
+ }
+ break;
+ default:
+ break;
+ }
+ return res;
+}
+
} // namespace android
\ No newline at end of file
diff --git a/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h b/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
index 9bfd987..78d41c4 100644
--- a/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
+++ b/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
@@ -30,11 +30,19 @@
typedef std::function<int (C2MemoryUsage, size_t,
/* => */ size_t*, unsigned*, unsigned*)> usage_mapper_fn;
- virtual C2Status allocateGraphicBuffer(
+ virtual id_t getId() const override;
+
+ virtual C2String getName() const override;
+
+ virtual std::shared_ptr<const Info> getInfo() const override {
+ return nullptr; // \todo
+ }
+
+ virtual C2Status newGraphicAllocation(
uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
std::shared_ptr<C2GraphicAllocation> *allocation) override;
- virtual C2Status recreateGraphicBuffer(
+ virtual C2Status priorGraphicAllocation(
const C2Handle *handle,
std::shared_ptr<C2GraphicAllocation> *allocation) override;
@@ -49,20 +57,6 @@
Impl *mImpl;
};
-#if 0
-class C2Allocation::Impl {
-public:
- Impl() : mMapped(false), mBase(nullptr) { }
- uint8_t* base() { return mMapped ? mBase : nullptr; }
-
- // TODO: call map...
-
-private:
- bool mMapped;
- uint8_t *mBase;
-};
-#endif
-
} // namespace android
#endif // STAGEFRIGHT_CODEC2_ALLOCATOR_GRALLOC_H_
diff --git a/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h b/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
index 00c33fe..2fff91f 100644
--- a/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
+++ b/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
@@ -29,11 +29,19 @@
typedef std::function<int (C2MemoryUsage, size_t,
/* => */ size_t*, unsigned*, unsigned*)> usage_mapper_fn;
- virtual C2Status allocateLinearBuffer(
+ virtual id_t getId() const override;
+
+ virtual C2String getName() const override;
+
+ virtual std::shared_ptr<const Info> getInfo() const override {
+ return nullptr; // \todo
+ }
+
+ virtual C2Status newLinearAllocation(
uint32_t capacity, C2MemoryUsage usage,
std::shared_ptr<C2LinearAllocation> *allocation) override;
- virtual C2Status recreateLinearBuffer(
+ virtual C2Status priorLinearAllocation(
const C2Handle *handle,
std::shared_ptr<C2LinearAllocation> *allocation) override;
diff --git a/media/libstagefright/codec2/vndk/include/C2BufferPriv.h b/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
index f1e8acb..56b0123 100644
--- a/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
+++ b/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
@@ -23,29 +23,46 @@
namespace android {
-class C2DefaultBlockAllocator : public C2BlockAllocator {
+class C2BasicLinearBlockPool : public C2BlockPool {
public:
- explicit C2DefaultBlockAllocator(const std::shared_ptr<C2Allocator> &allocator);
+ explicit C2BasicLinearBlockPool(const std::shared_ptr<C2Allocator> &allocator);
- virtual ~C2DefaultBlockAllocator() = default;
+ virtual ~C2BasicLinearBlockPool() = default;
- virtual C2Status allocateLinearBlock(
+ virtual C2Allocator::id_t getAllocatorId() const override {
+ return mAllocator->getId();
+ }
+
+ virtual local_id_t getLocalId() const override {
+ return BASIC_LINEAR;
+ }
+
+ virtual C2Status fetchLinearBlock(
uint32_t capacity,
C2MemoryUsage usage,
std::shared_ptr<C2LinearBlock> *block /* nonnull */) override;
- // TODO:
+ // TODO: fetchCircularBlock
+
private:
const std::shared_ptr<C2Allocator> mAllocator;
};
-class C2DefaultGraphicBlockAllocator : public C2BlockAllocator {
+class C2BasicGraphicBlockPool : public C2BlockPool {
public:
- explicit C2DefaultGraphicBlockAllocator(const std::shared_ptr<C2Allocator> &allocator);
+ explicit C2BasicGraphicBlockPool(const std::shared_ptr<C2Allocator> &allocator);
- virtual ~C2DefaultGraphicBlockAllocator() = default;
+ virtual ~C2BasicGraphicBlockPool() = default;
- virtual C2Status allocateGraphicBlock(
+ virtual C2Allocator::id_t getAllocatorId() const override {
+ return mAllocator->getId();
+ }
+
+ virtual local_id_t getLocalId() const override {
+ return BASIC_GRAPHIC;
+ }
+
+ virtual C2Status fetchGraphicBlock(
uint32_t width,
uint32_t height,
uint32_t format,
@@ -56,21 +73,6 @@
const std::shared_ptr<C2Allocator> mAllocator;
};
-
-#if 0
-class C2Allocation::Impl {
-public:
- Impl() : mMapped(false), mBase(nullptr) { }
- uint8_t* base() { return mMapped ? mBase : nullptr; }
-
- // TODO: call map...
-
-private:
- bool mMapped;
- uint8_t *mBase;
-};
-#endif
-
} // namespace android
#endif // STAGEFRIGHT_CODEC2_BUFFER_PRIV_H_
diff --git a/media/libstagefright/codec2/vndk/include/C2PlatformSupport.h b/media/libstagefright/codec2/vndk/include/C2PlatformSupport.h
index 9402050..40bb548 100644
--- a/media/libstagefright/codec2/vndk/include/C2PlatformSupport.h
+++ b/media/libstagefright/codec2/vndk/include/C2PlatformSupport.h
@@ -25,9 +25,33 @@
/**
* Returns the platform allocator store.
+ * \retval nullptr if the platform allocator store could not be obtained
*/
std::shared_ptr<C2AllocatorStore> GetCodec2PlatformAllocatorStore();
+/**
+ * Retrieves a block pool for a component.
+ *
+ * \param id the local ID of the block pool
+ * \param component the component using the block pool (must be non-null)
+ * \param pool pointer to where the obtained block pool shall be stored on success. nullptr
+ * will be stored here on failure
+ *
+ * \retval C2_OK the operation was successful
+ * \retval C2_BAD_VALUE the component is null
+ * \retval C2_NOT_FOUND if the block pool does not exist
+ * \retval C2_NO_MEMORY not enough memory to fetch the block pool (this return value is only
+ * possible for basic pools)
+ * \retval C2_TIMED_OUT the operation timed out (this return value is only possible for basic pools)
+ * \retval C2_REFUSED no permission to complete any required allocation (this return value is only
+ * possible for basic pools)
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected,
+ * this return value is only possible for basic pools)
+ */
+C2Status GetCodec2BlockPool(
+ C2BlockPool::local_id_t id, std::shared_ptr<const C2Component> component,
+ std::shared_ptr<C2BlockPool> *pool);
+
} // namespace android
#endif // STAGEFRIGHT_CODEC2_PLATFORM_SUPPORT_H_
diff --git a/media/libstagefright/codecs/avcdec/Android.bp b/media/libstagefright/codecs/avcdec/Android.bp
index 3b2602d..5dcffd5 100644
--- a/media/libstagefright/codecs/avcdec/Android.bp
+++ b/media/libstagefright/codecs/avcdec/Android.bp
@@ -74,9 +74,9 @@
misc_undefined: [
"signed-integer-overflow",
],
- cfi: true,
+ cfi: false, // true,
diag: {
- cfi: true,
+ cfi: false, // true,
},
},
diff --git a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
index 77db255..12eaff5 100644
--- a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
+++ b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
@@ -27,6 +27,8 @@
#include "ih264d.h"
#include "C2SoftAvcDec.h"
+#include <C2PlatformSupport.h>
+
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaDefs.h>
#include <utils/misc.h>
@@ -275,6 +277,8 @@
mMaxVideoSizeHint.mWidth = H264_MAX_FRAME_WIDTH;
mMaxVideoSizeHint.mHeight = H264_MAX_FRAME_HEIGHT;
+ mOutputBlockPools = C2PortBlockPoolsTuning::output::alloc_unique({});
+
auto insertParam = [¶ms = mParams] (C2Param *param) {
params[restoreIndex(param)] = param;
};
@@ -422,6 +426,8 @@
false, "_video_size", &mVideoSize));
mParamDescs.push_back(std::make_shared<C2ParamDescriptor>(
false, "_max_video_size_hint", &mMaxVideoSizeHint));
+ mParamDescs.push_back(std::make_shared<C2ParamDescriptor>(
+ false, "_output_block_pools", mOutputBlockPools.get()));
}
C2String C2SoftAvcDecIntf::getName() const {
@@ -443,6 +449,8 @@
uint32_t index = restoreIndex(param);
if (!mParams.count(index)) {
+ // TODO: add support for output-block-pools (this will be done when we move all
+ // config to shared ptr)
continue;
}
@@ -471,6 +479,13 @@
C2Status err = C2_OK;
for (C2Param *param : params) {
uint32_t index = restoreIndex(param);
+ if (param->index() == mOutputBlockPools.get()->index()) {
+ // setting output block pools
+ mOutputBlockPools.reset(
+ (C2PortBlockPoolsTuning::output *)C2Param::Copy(*param).release());
+ continue;
+ }
+
if (mParams.count(index) == 0) {
// We can't create C2SettingResult with no field, so just skipping in this case.
err = C2_BAD_INDEX;
@@ -1211,7 +1226,19 @@
// TODO: format & usage
uint32_t format = HAL_PIXEL_FORMAT_YV12;
C2MemoryUsage usage = { C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite };
- (void) work->worklets.front()->allocators[0]->allocateGraphicBlock(
+ // TODO: lock access to interface
+ C2BlockPool::local_id_t poolId =
+ mIntf->mOutputBlockPools->flexCount() ?
+ mIntf->mOutputBlockPools->m.mValues[0] : C2BlockPool::BASIC_GRAPHIC;
+ if (!mOutputBlockPool || mOutputBlockPool->getLocalId() != poolId) {
+ C2Status err = GetCodec2BlockPool(poolId, shared_from_this(), &mOutputBlockPool);
+ if (err != C2_OK) {
+ // TODO: trip
+ }
+ }
+ ALOGE("using allocator %u", mOutputBlockPool->getAllocatorId());
+
+ (void)mOutputBlockPool->fetchGraphicBlock(
mWidth, mHeight, format, usage, &mAllocatedBlock);
ALOGE("provided (%dx%d) required (%dx%d)", mAllocatedBlock->width(), mAllocatedBlock->height(), mWidth, mHeight);
}
diff --git a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
index cc33083..41ccf39 100644
--- a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
+++ b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.h
@@ -118,6 +118,7 @@
// TODO: C2StreamMimeConfig mInputStreamMime;
// TODO: C2StreamMimeConfig mOutputStreamMime;
C2StreamFormatConfig::input mInputStreamFormat;
+ std::unique_ptr<C2PortBlockPoolsTuning::output> mOutputBlockPools;
C2StreamFormatConfig::output mOutputStreamFormat;
C2VideoSizeStreamInfo::output mVideoSize;
C2MaxVideoSizeHintPortSetting::input mMaxVideoSizeHint;
@@ -138,6 +139,7 @@
std::vector<std::shared_ptr<C2ParamDescriptor>> mParamDescs;
void updateSupportedValues();
+ friend class C2SoftAvcDec;
};
class C2SoftAvcDec
@@ -191,6 +193,7 @@
const std::shared_ptr<C2SoftAvcDecIntf> mIntf;
const std::shared_ptr<C2ComponentListener> mListener;
+ std::shared_ptr<C2BlockPool> mOutputBlockPool;
std::mutex mQueueLock;
std::condition_variable mQueueCond;
diff --git a/media/libstagefright/codecs/cmds/codec2.cpp b/media/libstagefright/codecs/cmds/codec2.cpp
index 29669aa..c7e1c82 100644
--- a/media/libstagefright/codecs/cmds/codec2.cpp
+++ b/media/libstagefright/codecs/cmds/codec2.cpp
@@ -95,9 +95,7 @@
sp<IProducerListener> mProducerListener;
std::shared_ptr<C2Allocator> mAllocIon;
- std::shared_ptr<C2Allocator> mAllocGralloc;
- std::shared_ptr<C2BlockAllocator> mLinearAlloc;
- std::shared_ptr<C2BlockAllocator> mGraphicAlloc;
+ std::shared_ptr<C2BlockPool> mLinearPool;
std::mutex mQueueLock;
std::condition_variable mQueueCondition;
@@ -144,11 +142,8 @@
CHECK_EQ(mComposerClient->initCheck(), (status_t)OK);
std::shared_ptr<C2AllocatorStore> store = GetCodec2PlatformAllocatorStore();
- CHECK_EQ(store->createAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mAllocIon), C2_OK);
- CHECK_EQ(store->createAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &mAllocGralloc), C2_OK);
-
- mLinearAlloc = std::make_shared<C2DefaultBlockAllocator>(mAllocIon);
- mGraphicAlloc = std::make_shared<C2DefaultGraphicBlockAllocator>(mAllocGralloc);
+ CHECK_EQ(store->getAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mAllocIon), C2_OK);
+ mLinearPool = std::make_shared<C2BasicLinearBlockPool>(mAllocIon);
mControl = mComposerClient->createSurface(
String8("A Surface"),
@@ -214,6 +209,10 @@
}
std::shared_ptr<C2Component> component(std::make_shared<C2SoftAvcDec>("avc", 0, mListener));
+ std::unique_ptr<C2PortBlockPoolsTuning::output> pools =
+ C2PortBlockPoolsTuning::output::alloc_unique({ (uint64_t)C2BlockPool::BASIC_GRAPHIC });
+ std::vector<std::unique_ptr<C2SettingResult>> result;
+ (void)component->intf()->config_nb({pools.get()}, &result);
component->start();
for (int i = 0; i < 8; ++i) {
@@ -274,7 +273,7 @@
});
long numFrames = 0;
- mLinearAlloc.reset(new C2DefaultBlockAllocator(mAllocIon));
+ mLinearPool.reset(new C2BasicLinearBlockPool(mAllocIon));
for (;;) {
size_t size = 0u;
@@ -328,7 +327,7 @@
work->input.ordinal.frame_index = numFrames;
std::shared_ptr<C2LinearBlock> block;
- mLinearAlloc->allocateLinearBlock(
+ mLinearPool->fetchLinearBlock(
size,
{ C2MemoryUsage::kSoftwareRead, C2MemoryUsage::kSoftwareWrite },
&block);
@@ -343,7 +342,6 @@
work->input.buffers.emplace_back(new LinearBuffer(block));
work->worklets.clear();
work->worklets.emplace_back(new C2Worklet);
- work->worklets.front()->allocators.emplace_back(mGraphicAlloc);
std::list<std::unique_ptr<C2Work>> items;
items.push_back(std::move(work));
diff --git a/media/libstagefright/include/OmxNodeOwner.h b/media/libstagefright/include/OmxNodeOwner.h
deleted file mode 100644
index 64ec7f7..0000000
--- a/media/libstagefright/include/OmxNodeOwner.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef OMX_NODE_OWNER_H_
-
-#define OMX_NODE_OWNER_H_
-
-namespace android {
-
-struct OMXNodeInstance;
-
-/**
- * This struct is needed to separate OMX from OMXNodeInstance.
- *
- * TODO: This might not be needed after Treble transition is complete.
- */
-struct OmxNodeOwner {
- virtual status_t freeNode(const sp<OMXNodeInstance> &instance) = 0;
- virtual ~OmxNodeOwner() {}
-};
-
-}
-
-#endif // OMX_NODE_OWNER_H_
diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h
index 424246d..d1a9d25 100644
--- a/media/libstagefright/include/media/stagefright/ACodec.h
+++ b/media/libstagefright/include/media/stagefright/ACodec.h
@@ -95,11 +95,6 @@
static status_t getOMXChannelMapping(size_t numChannels, OMX_AUDIO_CHANNELTYPE map[]);
- // Save the flag.
- void setTrebleFlag(bool trebleFlag);
- // Return the saved flag.
- bool getTrebleFlag() const;
-
protected:
virtual ~ACodec();
@@ -233,9 +228,7 @@
sp<IOMX> mOMX;
sp<IOMXNode> mOMXNode;
int32_t mNodeGeneration;
- bool mTrebleFlag;
sp<TAllocator> mAllocator[2];
- sp<MemoryDealer> mDealer[2];
bool mUsingNativeWindow;
sp<ANativeWindow> mNativeWindow;
diff --git a/media/libstagefright/include/media/stagefright/OMXClient.h b/media/libstagefright/include/media/stagefright/OMXClient.h
index b1864b8..bb133d3 100644
--- a/media/libstagefright/include/media/stagefright/OMXClient.h
+++ b/media/libstagefright/include/media/stagefright/OMXClient.h
@@ -18,25 +18,19 @@
#define OMX_CLIENT_H_
-#include <media/IOMX.h>
-
namespace android {
+class IOMX;
+
class OMXClient {
public:
OMXClient();
status_t connect();
- status_t connect(bool* trebleFlag);
- status_t connect(const char* name, bool* trebleFlag = nullptr);
-
- status_t connectLegacy();
- status_t connectTreble(const char* name = "default");
+ status_t connect(const char* name);
void disconnect();
- sp<IOMX> interface() {
- return mOMX;
- }
+ sp<IOMX> interface();
private:
sp<IOMX> mOMX;
diff --git a/media/libstagefright/omx/Android.bp b/media/libstagefright/omx/Android.bp
index f388a48..8539864 100644
--- a/media/libstagefright/omx/Android.bp
+++ b/media/libstagefright/omx/Android.bp
@@ -9,8 +9,6 @@
"FrameDropper.cpp",
"GraphicBufferSource.cpp",
"BWGraphicBufferSource.cpp",
- "OMX.cpp",
- "OMXStore.cpp",
"OMXMaster.cpp",
"OMXNodeInstance.cpp",
"OMXUtils.cpp",
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
deleted file mode 100644
index 09c4019..0000000
--- a/media/libstagefright/omx/OMX.cpp
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <inttypes.h>
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "OMX"
-#include <utils/Log.h>
-
-#include <dlfcn.h>
-
-#include <media/stagefright/omx/OMX.h>
-#include <media/stagefright/omx/OMXNodeInstance.h>
-#include <media/stagefright/omx/BWGraphicBufferSource.h>
-#include <media/stagefright/omx/OMXMaster.h>
-#include <media/stagefright/omx/OMXUtils.h>
-#include <media/stagefright/foundation/ADebug.h>
-
-namespace android {
-
-// node ids are created by concatenating the pid with a 16-bit counter
-static size_t kMaxNodeInstances = (1 << 16);
-
-OMX::OMX() : mMaster(new OMXMaster), mParser() {
-}
-
-OMX::~OMX() {
- delete mMaster;
- mMaster = NULL;
-}
-
-void OMX::binderDied(const wp<IBinder> &the_late_who) {
- sp<OMXNodeInstance> instance;
-
- {
- Mutex::Autolock autoLock(mLock);
-
- ssize_t index = mLiveNodes.indexOfKey(the_late_who);
-
- if (index < 0) {
- ALOGE("b/27597103, nonexistent observer on binderDied");
- android_errorWriteLog(0x534e4554, "27597103");
- return;
- }
-
- instance = mLiveNodes.editValueAt(index);
- mLiveNodes.removeItemsAt(index);
- }
-
- instance->onObserverDied();
-}
-
-status_t OMX::listNodes(List<ComponentInfo> *list) {
- list->clear();
-
- OMX_U32 index = 0;
- char componentName[256];
- while (mMaster->enumerateComponents(
- componentName, sizeof(componentName), index) == OMX_ErrorNone) {
- list->push_back(ComponentInfo());
- ComponentInfo &info = *--list->end();
-
- info.mName = componentName;
-
- Vector<String8> roles;
- OMX_ERRORTYPE err =
- mMaster->getRolesOfComponent(componentName, &roles);
-
- if (err == OMX_ErrorNone) {
- for (OMX_U32 i = 0; i < roles.size(); ++i) {
- info.mRoles.push_back(roles[i]);
- }
- }
-
- ++index;
- }
-
- return OK;
-}
-
-status_t OMX::allocateNode(
- const char *name, const sp<IOMXObserver> &observer,
- sp<IOMXNode> *omxNode) {
- Mutex::Autolock autoLock(mLock);
-
- omxNode->clear();
-
- if (mLiveNodes.size() == kMaxNodeInstances) {
- return NO_MEMORY;
- }
-
- sp<OMXNodeInstance> instance = new OMXNodeInstance(this, observer, name);
-
- OMX_COMPONENTTYPE *handle;
- OMX_ERRORTYPE err = mMaster->makeComponentInstance(
- name, &OMXNodeInstance::kCallbacks,
- instance.get(), &handle);
-
- if (err != OMX_ErrorNone) {
- ALOGE("FAILED to allocate omx component '%s' err=%s(%#x)", name, asString(err), err);
-
- return StatusFromOMXError(err);
- }
- instance->setHandle(handle);
-
- // Find quirks from mParser
- const auto& codec = mParser.getCodecMap().find(name);
- if (codec == mParser.getCodecMap().cend()) {
- ALOGW("Failed to obtain quirks for omx component '%s' from XML files",
- name);
- } else {
- uint32_t quirks = 0;
- for (const auto& quirk : codec->second.quirkSet) {
- if (quirk == "requires-allocate-on-input-ports") {
- quirks |= OMXNodeInstance::
- kRequiresAllocateBufferOnInputPorts;
- }
- if (quirk == "requires-allocate-on-output-ports") {
- quirks |= OMXNodeInstance::
- kRequiresAllocateBufferOnOutputPorts;
- }
- }
- instance->setQuirks(quirks);
- }
-
- mLiveNodes.add(IInterface::asBinder(observer), instance);
- IInterface::asBinder(observer)->linkToDeath(this);
-
- *omxNode = instance;
-
- return OK;
-}
-
-status_t OMX::freeNode(const sp<OMXNodeInstance> &instance) {
- if (instance == NULL) {
- return OK;
- }
-
- {
- Mutex::Autolock autoLock(mLock);
- ssize_t index = mLiveNodes.indexOfKey(IInterface::asBinder(instance->observer()));
- if (index < 0) {
- // This could conceivably happen if the observer dies at roughly the
- // same time that a client attempts to free the node explicitly.
-
- // NOTE: it's guaranteed that this method is called at most once per
- // instance.
- ALOGV("freeNode: instance already removed from book-keeping.");
- } else {
- mLiveNodes.removeItemsAt(index);
- IInterface::asBinder(instance->observer())->unlinkToDeath(this);
- }
- }
-
- CHECK(instance->handle() != NULL);
- OMX_ERRORTYPE err = mMaster->destroyComponentInstance(
- static_cast<OMX_COMPONENTTYPE *>(instance->handle()));
- ALOGV("freeNode: handle destroyed: %p", instance->handle());
-
- return StatusFromOMXError(err);
-}
-
-status_t OMX::createInputSurface(
- sp<IGraphicBufferProducer> *bufferProducer,
- sp<IGraphicBufferSource> *bufferSource) {
- if (bufferProducer == NULL || bufferSource == NULL) {
- ALOGE("b/25884056");
- return BAD_VALUE;
- }
-
- sp<GraphicBufferSource> graphicBufferSource = new GraphicBufferSource();
- status_t err = graphicBufferSource->initCheck();
- if (err != OK) {
- ALOGE("Failed to create persistent input surface: %s (%d)",
- strerror(-err), err);
- return err;
- }
-
- *bufferProducer = graphicBufferSource->getIGraphicBufferProducer();
- *bufferSource = new BWGraphicBufferSource(graphicBufferSource);
-
- return OK;
-}
-
-} // namespace android
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 015a148..ff58eb6 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -344,7 +344,7 @@
////////////////////////////////////////////////////////////////////////////////
OMXNodeInstance::OMXNodeInstance(
- OmxNodeOwner *owner, const sp<IOMXObserver> &observer, const char *name)
+ Omx *owner, const sp<IOMXObserver> &observer, const char *name)
: mOwner(owner),
mHandle(NULL),
mObserver(observer),
diff --git a/media/libstagefright/omx/OMXStore.cpp b/media/libstagefright/omx/OMXStore.cpp
deleted file mode 100644
index 345336d..0000000
--- a/media/libstagefright/omx/OMXStore.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "OMXStore"
-#include <utils/Log.h>
-
-#include <media/stagefright/omx/OMXUtils.h>
-#include <media/stagefright/omx/OMX.h>
-#include <media/stagefright/omx/OMXStore.h>
-#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
-
-#include <map>
-#include <string>
-
-namespace android {
-
-namespace {
- struct RoleProperties {
- std::string type;
- bool isEncoder;
- bool preferPlatformNodes;
- std::multimap<size_t, IOMXStore::NodeInfo> nodeList;
- };
-} // Unnamed namespace
-
-OMXStore::OMXStore(
- const char* owner,
- const char* const* searchDirs,
- const char* mainXmlName,
- const char* performanceXmlName,
- const char* profilingResultsXmlPath) {
- MediaCodecsXmlParser parser(
- searchDirs,
- mainXmlName,
- performanceXmlName,
- profilingResultsXmlPath);
- mParsingStatus = parser.getParsingStatus();
-
- const auto& serviceAttributeMap = parser.getServiceAttributeMap();
- mServiceAttributeList.reserve(serviceAttributeMap.size());
- for (const auto& attributePair : serviceAttributeMap) {
- Attribute attribute;
- attribute.key = attributePair.first;
- attribute.value = attributePair.second;
- mServiceAttributeList.push_back(std::move(attribute));
- }
-
- const auto& roleMap = parser.getRoleMap();
- mRoleList.reserve(roleMap.size());
- for (const auto& rolePair : roleMap) {
- RoleInfo role;
- role.role = rolePair.first;
- role.type = rolePair.second.type;
- role.isEncoder = rolePair.second.isEncoder;
- // TODO: Currently, preferPlatformNodes information is not available in
- // the xml file. Once we have a way to provide this information, it
- // should be parsed properly.
- role.preferPlatformNodes = rolePair.first.compare(0, 5, "audio") == 0;
- std::vector<NodeInfo>& nodeList = role.nodes;
- nodeList.reserve(rolePair.second.nodeList.size());
- for (const auto& nodePair : rolePair.second.nodeList) {
- NodeInfo node;
- node.name = nodePair.second.name;
- node.owner = owner;
- std::vector<Attribute>& attributeList = node.attributes;
- attributeList.reserve(nodePair.second.attributeList.size());
- for (const auto& attributePair : nodePair.second.attributeList) {
- Attribute attribute;
- attribute.key = attributePair.first;
- attribute.value = attributePair.second;
- attributeList.push_back(std::move(attribute));
- }
- nodeList.push_back(std::move(node));
- }
- mRoleList.push_back(std::move(role));
- }
-
- mPrefix = parser.getCommonPrefix();
-}
-
-status_t OMXStore::listServiceAttributes(std::vector<Attribute>* attributes) {
- *attributes = mServiceAttributeList;
- return mParsingStatus;
-}
-
-status_t OMXStore::getNodePrefix(std::string* prefix) {
- *prefix = mPrefix;
- return mParsingStatus;
-}
-
-status_t OMXStore::listRoles(std::vector<RoleInfo>* roleList) {
- *roleList = mRoleList;
- return mParsingStatus;
-}
-
-status_t OMXStore::getOmx(const std::string& name, sp<IOMX>* omx) {
- *omx = new OMX();
- return NO_ERROR;
-}
-
-OMXStore::~OMXStore() {
-}
-
-} // namespace android
-
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/1.0/Omx.h b/media/libstagefright/omx/include/media/stagefright/omx/1.0/Omx.h
index a6a9d3e..baa7b81 100644
--- a/media/libstagefright/omx/include/media/stagefright/omx/1.0/Omx.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/1.0/Omx.h
@@ -20,13 +20,13 @@
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
-#include <media/stagefright/omx/OMXNodeInstance.h>
#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
namespace android {
struct OMXMaster;
+struct OMXNodeInstance;
namespace hardware {
namespace media {
@@ -50,10 +50,9 @@
using ::android::wp;
using ::android::OMXMaster;
-using ::android::OmxNodeOwner;
using ::android::OMXNodeInstance;
-struct Omx : public IOmx, public hidl_death_recipient, public OmxNodeOwner {
+struct Omx : public IOmx, public hidl_death_recipient {
Omx();
virtual ~Omx();
@@ -68,8 +67,8 @@
// Method from hidl_death_recipient
void serviceDied(uint64_t cookie, const wp<IBase>& who) override;
- // Method from OmxNodeOwner
- virtual status_t freeNode(sp<OMXNodeInstance> const& instance) override;
+ // Method for OMXNodeInstance
+ status_t freeNode(sp<OMXNodeInstance> const& instance);
protected:
OMXMaster* mMaster;
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/OMX.h b/media/libstagefright/omx/include/media/stagefright/omx/OMX.h
deleted file mode 100644
index 594b4c0..0000000
--- a/media/libstagefright/omx/include/media/stagefright/omx/OMX.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_OMX_H_
-#define ANDROID_OMX_H_
-
-#include <media/IOMX.h>
-#include <utils/threads.h>
-#include <utils/KeyedVector.h>
-#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
-#include "OmxNodeOwner.h"
-
-namespace android {
-
-struct OMXMaster;
-struct OMXNodeInstance;
-
-class OMX : public BnOMX,
- public OmxNodeOwner,
- public IBinder::DeathRecipient {
-public:
- OMX();
-
- virtual status_t listNodes(List<ComponentInfo> *list);
-
- virtual status_t allocateNode(
- const char *name, const sp<IOMXObserver> &observer,
- sp<IOMXNode> *omxNode);
-
- virtual status_t createInputSurface(
- sp<IGraphicBufferProducer> *bufferProducer,
- sp<IGraphicBufferSource> *bufferSource);
-
- virtual void binderDied(const wp<IBinder> &the_late_who);
-
- virtual status_t freeNode(const sp<OMXNodeInstance>& instance);
-
-protected:
- virtual ~OMX();
-
-private:
- Mutex mLock;
- OMXMaster *mMaster;
- MediaCodecsXmlParser mParser;
-
- KeyedVector<wp<IBinder>, sp<OMXNodeInstance> > mLiveNodes;
-
- OMX(const OMX &);
- OMX &operator=(const OMX &);
-};
-
-} // namespace android
-
-#endif // ANDROID_OMX_H_
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h b/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h
index 1065ca5..c436121 100644
--- a/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h
@@ -25,9 +25,9 @@
#include <utils/threads.h>
#include <utils/KeyedVector.h>
#include <utils/SortedVector.h>
-#include "OmxNodeOwner.h"
#include <android/hidl/memory/1.0/IMemory.h>
+#include <media/stagefright/omx/1.0/Omx.h>
namespace android {
class GraphicBuffer;
@@ -35,11 +35,12 @@
class IOMXObserver;
struct OMXMaster;
class OMXBuffer;
-typedef hidl::memory::V1_0::IMemory IHidlMemory;
+using IHidlMemory = hidl::memory::V1_0::IMemory;
+using hardware::media::omx::V1_0::implementation::Omx;
struct OMXNodeInstance : public BnOMXNode {
OMXNodeInstance(
- OmxNodeOwner *owner, const sp<IOMXObserver> &observer, const char *name);
+ Omx *owner, const sp<IOMXObserver> &observer, const char *name);
void setHandle(OMX_HANDLETYPE handle);
@@ -122,7 +123,7 @@
Mutex mLock;
- OmxNodeOwner *mOwner;
+ Omx *mOwner;
OMX_HANDLETYPE mHandle;
sp<IOMXObserver> mObserver;
sp<CallbackDispatcher> mDispatcher;
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/OMXStore.h b/media/libstagefright/omx/include/media/stagefright/omx/OMXStore.h
deleted file mode 100644
index e00d713..0000000
--- a/media/libstagefright/omx/include/media/stagefright/omx/OMXStore.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_OMXSTORE_H_
-#define ANDROID_OMXSTORE_H_
-
-#include <media/IOMXStore.h>
-#include <media/IOMX.h>
-#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
-
-#include <vector>
-#include <string>
-
-namespace android {
-
-class OMXStore : public BnOMXStore {
-public:
- OMXStore(
- const char* owner = "default",
- const char* const* searchDirs
- = MediaCodecsXmlParser::defaultSearchDirs,
- const char* mainXmlName
- = MediaCodecsXmlParser::defaultMainXmlName,
- const char* performanceXmlName
- = MediaCodecsXmlParser::defaultPerformanceXmlName,
- const char* profilingResultsXmlPath
- = MediaCodecsXmlParser::defaultProfilingResultsXmlPath);
-
- status_t listServiceAttributes(
- std::vector<Attribute>* attributes) override;
-
- status_t getNodePrefix(std::string* prefix) override;
-
- status_t listRoles(std::vector<RoleInfo>* roleList) override;
-
- status_t getOmx(const std::string& name, sp<IOMX>* omx) override;
-
- ~OMXStore() override;
-
-protected:
- status_t mParsingStatus;
- std::string mPrefix;
- std::vector<Attribute> mServiceAttributeList;
- std::vector<RoleInfo> mRoleList;
-};
-
-} // namespace android
-
-#endif // ANDROID_OMXSTORE_H_
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index 8092887..86c7211 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -25,11 +25,9 @@
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
-#include <binder/MemoryDealer.h>
#include <cutils/properties.h>
#include <media/DataSource.h>
#include <media/IMediaHTTPService.h>
-#include <media/IMediaCodecService.h>
#include <media/MediaExtractor.h>
#include <media/MediaSource.h>
#include <media/OMXBuffer.h>
@@ -71,7 +69,7 @@
/////////////////////////////////////////////////////////////////////
Harness::Harness()
- : mInitCheck(NO_INIT), mUseTreble(false) {
+ : mInitCheck(NO_INIT) {
mInitCheck = initOMX();
}
@@ -83,21 +81,12 @@
}
status_t Harness::initOMX() {
- if (property_get_bool("persist.media.treble_omx", true)) {
- using namespace ::android::hardware::media::omx::V1_0;
- sp<IOmx> tOmx = IOmx::getService();
- if (tOmx == nullptr) {
- return NO_INIT;
- }
- mOMX = new utils::LWOmx(tOmx);
- mUseTreble = true;
- } else {
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder = sm->getService(String16("media.codec"));
- sp<IMediaCodecService> service = interface_cast<IMediaCodecService>(binder);
- mOMX = service->getOMX();
- mUseTreble = false;
+ using namespace ::android::hardware::media::omx::V1_0;
+ sp<IOmx> tOmx = IOmx::getService();
+ if (tOmx == nullptr) {
+ return NO_INIT;
}
+ mOMX = new utils::LWOmx(tOmx);
return mOMX != 0 ? OK : NO_INIT;
}
@@ -225,25 +214,19 @@
for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
Buffer buffer;
buffer.mFlags = 0;
- if (mUseTreble) {
- bool success;
- auto transStatus = mAllocator->allocate(def.nBufferSize,
- [&success, &buffer](
- bool s,
- hidl_memory const& m) {
- success = s;
- buffer.mHidlMemory = m;
- });
- EXPECT(transStatus.isOk(),
- "Cannot call allocator");
- EXPECT(success,
- "Cannot allocate memory");
- err = mOMXNode->useBuffer(portIndex, buffer.mHidlMemory, &buffer.mID);
- } else {
- buffer.mMemory = mDealer->allocate(def.nBufferSize);
- CHECK(buffer.mMemory != NULL);
- err = mOMXNode->useBuffer(portIndex, buffer.mMemory, &buffer.mID);
- }
+ bool success;
+ auto transStatus = mAllocator->allocate(def.nBufferSize,
+ [&success, &buffer](
+ bool s,
+ hidl_memory const& m) {
+ success = s;
+ buffer.mHidlMemory = m;
+ });
+ EXPECT(transStatus.isOk(),
+ "Cannot call allocator");
+ EXPECT(success,
+ "Cannot allocate memory");
+ err = mOMXNode->useBuffer(portIndex, buffer.mHidlMemory, &buffer.mID);
EXPECT_SUCCESS(err, "useBuffer");
@@ -312,13 +295,11 @@
return OK;
}
- if (mUseTreble) {
- mAllocator = IAllocator::getService("ashmem");
- EXPECT(mAllocator != nullptr,
- "Cannot obtain hidl AshmemAllocator");
- } else {
- mDealer = new MemoryDealer(16 * 1024 * 1024, "OMXHarness");
- }
+ mAllocator = IAllocator::getService("ashmem");
+ EXPECT(mAllocator != nullptr,
+ "Cannot obtain hidl AshmemAllocator");
+ // TODO: When Treble has MemoryHeap/MemoryDealer, we should specify the heap
+ // size to be 16 * 1024 * 1024.
sp<CodecObserver> observer = new CodecObserver(this, ++mCurGeneration);
diff --git a/media/libstagefright/omx/tests/OMXHarness.h b/media/libstagefright/omx/tests/OMXHarness.h
index 4fc0f79..dca787c 100644
--- a/media/libstagefright/omx/tests/OMXHarness.h
+++ b/media/libstagefright/omx/tests/OMXHarness.h
@@ -93,8 +93,6 @@
Condition mMessageAddedCondition;
int32_t mLastMsgGeneration;
int32_t mCurGeneration;
- bool mUseTreble;
- sp<MemoryDealer> mDealer;
sp<IAllocator> mAllocator;
status_t initOMX();
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 79e540a..9cb0357 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -641,38 +641,52 @@
// IAudioFlinger interface
-
-sp<IAudioTrack> AudioFlinger::createTrack(
- audio_stream_type_t streamType,
- uint32_t sampleRate,
- audio_format_t format,
- audio_channel_mask_t channelMask,
- size_t *frameCount,
- audio_output_flags_t *flags,
- const sp<IMemory>& sharedBuffer,
- audio_io_handle_t output,
- pid_t pid,
- pid_t tid,
- audio_session_t *sessionId,
- int clientUid,
- status_t *status,
- audio_port_handle_t portId)
+sp<IAudioTrack> AudioFlinger::createTrack(const CreateTrackInput& input,
+ CreateTrackOutput& output,
+ status_t *status)
{
sp<PlaybackThread::Track> track;
sp<TrackHandle> trackHandle;
sp<Client> client;
status_t lStatus;
- audio_session_t lSessionId;
+ audio_stream_type_t streamType;
+ audio_port_handle_t portId;
+ bool updatePid = (input.clientInfo.clientPid == -1);
const uid_t callingUid = IPCThreadState::self()->getCallingUid();
- if (pid == -1 || !isTrustedCallingUid(callingUid)) {
+ uid_t clientUid = input.clientInfo.clientUid;
+ if (!isTrustedCallingUid(callingUid)) {
+ ALOGW_IF(clientUid != callingUid,
+ "%s uid %d tried to pass itself off as %d",
+ __FUNCTION__, callingUid, clientUid);
+ clientUid = callingUid;
+ updatePid = true;
+ }
+ pid_t clientPid = input.clientInfo.clientPid;
+ if (updatePid) {
const pid_t callingPid = IPCThreadState::self()->getCallingPid();
- ALOGW_IF(pid != -1 && pid != callingPid,
+ ALOGW_IF(clientPid != -1 && clientPid != callingPid,
"%s uid %d pid %d tried to pass itself off as pid %d",
- __func__, callingUid, callingPid, pid);
- pid = callingPid;
+ __func__, callingUid, callingPid, clientPid);
+ clientPid = callingPid;
}
+ audio_session_t sessionId = input.sessionId;
+ if (sessionId == AUDIO_SESSION_ALLOCATE) {
+ sessionId = (audio_session_t) newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+ }
+ output.sessionId = sessionId;
+ output.outputId = AUDIO_IO_HANDLE_NONE;
+ output.selectedDeviceId = input.selectedDeviceId;
+
+ lStatus = AudioSystem::getOutputForAttr(&input.attr, &output.outputId, sessionId, &streamType,
+ clientUid, &input.config, input.flags,
+ &output.selectedDeviceId, &portId);
+
+ if (lStatus != NO_ERROR || output.outputId == AUDIO_IO_HANDLE_NONE) {
+ ALOGE("createTrack() getOutputForAttr() return error %d or invalid output handle", lStatus);
+ goto Exit;
+ }
// client AudioTrack::set already implements AUDIO_STREAM_DEFAULT => AUDIO_STREAM_MUSIC,
// but if someone uses binder directly they could bypass that and cause us to crash
if (uint32_t(streamType) >= AUDIO_STREAM_CNT) {
@@ -681,91 +695,76 @@
goto Exit;
}
- // further sample rate checks are performed by createTrack_l() depending on the thread type
- if (sampleRate == 0) {
- ALOGE("createTrack() invalid sample rate %u", sampleRate);
- lStatus = BAD_VALUE;
- goto Exit;
- }
-
// further channel mask checks are performed by createTrack_l() depending on the thread type
- if (!audio_is_output_channel(channelMask)) {
- ALOGE("createTrack() invalid channel mask %#x", channelMask);
+ if (!audio_is_output_channel(input.config.channel_mask)) {
+ ALOGE("createTrack() invalid channel mask %#x", input.config.channel_mask);
lStatus = BAD_VALUE;
goto Exit;
}
// further format checks are performed by createTrack_l() depending on the thread type
- if (!audio_is_valid_format(format)) {
- ALOGE("createTrack() invalid format %#x", format);
- lStatus = BAD_VALUE;
- goto Exit;
- }
-
- if (sharedBuffer != 0 && sharedBuffer->pointer() == NULL) {
- ALOGE("createTrack() sharedBuffer is non-0 but has NULL pointer()");
+ if (!audio_is_valid_format(input.config.format)) {
+ ALOGE("createTrack() invalid format %#x", input.config.format);
lStatus = BAD_VALUE;
goto Exit;
}
{
Mutex::Autolock _l(mLock);
- PlaybackThread *thread = checkPlaybackThread_l(output);
+ PlaybackThread *thread = checkPlaybackThread_l(output.outputId);
if (thread == NULL) {
- ALOGE("no playback thread found for output handle %d", output);
+ ALOGE("no playback thread found for output handle %d", output.outputId);
lStatus = BAD_VALUE;
goto Exit;
}
- client = registerPid(pid);
+ client = registerPid(clientPid);
PlaybackThread *effectThread = NULL;
- if (sessionId != NULL && *sessionId != AUDIO_SESSION_ALLOCATE) {
- if (audio_unique_id_get_use(*sessionId) != AUDIO_UNIQUE_ID_USE_SESSION) {
- ALOGE("createTrack() invalid session ID %d", *sessionId);
- lStatus = BAD_VALUE;
- goto Exit;
- }
- lSessionId = *sessionId;
- // check if an effect chain with the same session ID is present on another
- // output thread and move it here.
- for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
- if (mPlaybackThreads.keyAt(i) != output) {
- uint32_t sessions = t->hasAudioSession(lSessionId);
- if (sessions & ThreadBase::EFFECT_SESSION) {
- effectThread = t.get();
- break;
- }
+ // check if an effect chain with the same session ID is present on another
+ // output thread and move it here.
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+ sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
+ if (mPlaybackThreads.keyAt(i) != output.outputId) {
+ uint32_t sessions = t->hasAudioSession(sessionId);
+ if (sessions & ThreadBase::EFFECT_SESSION) {
+ effectThread = t.get();
+ break;
}
}
- } else {
- // if no audio session id is provided, create one here
- lSessionId = (audio_session_t) nextUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
- if (sessionId != NULL) {
- *sessionId = lSessionId;
- }
}
- ALOGV("createTrack() lSessionId: %d", lSessionId);
+ ALOGV("createTrack() sessionId: %d", sessionId);
- track = thread->createTrack_l(client, streamType, sampleRate, format,
- channelMask, frameCount, sharedBuffer, lSessionId, flags, tid,
- clientUid, &lStatus, portId);
+ output.sampleRate = input.config.sample_rate;
+ output.frameCount = input.frameCount;
+ output.notificationFrameCount = input.notificationFrameCount;
+ output.flags = input.flags;
+
+ track = thread->createTrack_l(client, streamType, &output.sampleRate, input.config.format,
+ input.config.channel_mask,
+ &output.frameCount, &output.notificationFrameCount,
+ input.notificationsPerBuffer, input.speed,
+ input.sharedBuffer, sessionId, &output.flags,
+ input.clientInfo.clientTid, clientUid, &lStatus, portId);
LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (track == 0));
// we don't abort yet if lStatus != NO_ERROR; there is still work to be done regardless
+ output.afFrameCount = thread->frameCount();
+ output.afSampleRate = thread->sampleRate();
+ output.afLatencyMs = thread->latency();
+
// move effect chain to this output thread if an effect on same session was waiting
// for a track to be created
if (lStatus == NO_ERROR && effectThread != NULL) {
// no risk of deadlock because AudioFlinger::mLock is held
Mutex::Autolock _dl(thread->mLock);
Mutex::Autolock _sl(effectThread->mLock);
- moveEffectChain_l(lSessionId, effectThread, thread, true);
+ moveEffectChain_l(sessionId, effectThread, thread, true);
}
// Look for sync events awaiting for a session to be used.
for (size_t i = 0; i < mPendingSyncEvents.size(); i++) {
- if (mPendingSyncEvents[i]->triggerSession() == lSessionId) {
+ if (mPendingSyncEvents[i]->triggerSession() == sessionId) {
if (thread->isValidSyncEvent(mPendingSyncEvents[i])) {
if (lStatus == NO_ERROR) {
(void) track->setSyncEvent(mPendingSyncEvents[i]);
@@ -778,7 +777,7 @@
}
}
- setAudioHwSyncForSession_l(thread, lSessionId);
+ setAudioHwSyncForSession_l(thread, sessionId);
}
if (lStatus != NO_ERROR) {
@@ -798,6 +797,9 @@
trackHandle = new TrackHandle(track);
Exit:
+ if (lStatus != NO_ERROR && output.outputId != AUDIO_IO_HANDLE_NONE) {
+ AudioSystem::releaseOutput(output.outputId, streamType, sessionId);
+ }
*status = lStatus;
return trackHandle;
}
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index dff94d2..7e9ef26 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -114,21 +114,9 @@
virtual status_t dump(int fd, const Vector<String16>& args);
// IAudioFlinger interface, in binder opcode order
- virtual sp<IAudioTrack> createTrack(
- audio_stream_type_t streamType,
- uint32_t sampleRate,
- audio_format_t format,
- audio_channel_mask_t channelMask,
- size_t *pFrameCount,
- audio_output_flags_t *flags,
- const sp<IMemory>& sharedBuffer,
- audio_io_handle_t output,
- pid_t pid,
- pid_t tid,
- audio_session_t *sessionId,
- int clientUid,
- status_t *status /*non-NULL*/,
- audio_port_handle_t portId);
+ virtual sp<IAudioTrack> createTrack(const CreateTrackInput& input,
+ CreateTrackOutput& output,
+ status_t *status);
virtual sp<media::IAudioRecord> openRecord(
audio_io_handle_t input,
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 8c7c830..8e6c720 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1837,10 +1837,13 @@
sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
const sp<AudioFlinger::Client>& client,
audio_stream_type_t streamType,
- uint32_t sampleRate,
+ uint32_t *pSampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
size_t *pFrameCount,
+ size_t *pNotificationFrameCount,
+ uint32_t notificationsPerBuffer,
+ float speed,
const sp<IMemory>& sharedBuffer,
audio_session_t sessionId,
audio_output_flags_t *flags,
@@ -1850,9 +1853,16 @@
audio_port_handle_t portId)
{
size_t frameCount = *pFrameCount;
+ size_t notificationFrameCount = *pNotificationFrameCount;
sp<Track> track;
status_t lStatus;
audio_output_flags_t outputFlags = mOutput->flags;
+ audio_output_flags_t requestedFlags = *flags;
+
+ if (*pSampleRate == 0) {
+ *pSampleRate = mSampleRate;
+ }
+ uint32_t sampleRate = *pSampleRate;
// special case for FAST flag considered OK if fast mixer is present
if (hasFastMixer()) {
@@ -1929,36 +1939,114 @@
*flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_FAST);
}
}
- // For normal PCM streaming tracks, update minimum frame count.
- // For compatibility with AudioTrack calculation, buffer depth is forced
- // to be at least 2 x the normal mixer frame count and cover audio hardware latency.
- // This is probably too conservative, but legacy application code may depend on it.
- // If you change this calculation, also review the start threshold which is related.
- if (!(*flags & AUDIO_OUTPUT_FLAG_FAST)
- && audio_has_proportional_frames(format) && sharedBuffer == 0) {
- // this must match AudioTrack.cpp calculateMinFrameCount().
- // TODO: Move to a common library
- uint32_t latencyMs = 0;
- lStatus = mOutput->stream->getLatency(&latencyMs);
- if (lStatus != OK) {
- ALOGE("Error when retrieving output stream latency: %d", lStatus);
+
+ if (!audio_has_proportional_frames(format)) {
+ if (sharedBuffer != 0) {
+ // Same comment as below about ignoring frameCount parameter for set()
+ frameCount = sharedBuffer->size();
+ } else if (frameCount == 0) {
+ frameCount = mNormalFrameCount;
+ }
+ if (notificationFrameCount != frameCount) {
+ notificationFrameCount = frameCount;
+ }
+ } else if (sharedBuffer != 0) {
+ // FIXME: Ensure client side memory buffers need
+ // not have additional alignment beyond sample
+ // (e.g. 16 bit stereo accessed as 32 bit frame).
+ size_t alignment = audio_bytes_per_sample(format);
+ if (alignment & 1) {
+ // for AUDIO_FORMAT_PCM_24_BIT_PACKED (not exposed through Java).
+ alignment = 1;
+ }
+ uint32_t channelCount = audio_channel_count_from_out_mask(channelMask);
+ size_t frameSize = channelCount * audio_bytes_per_sample(format);
+ if (channelCount > 1) {
+ // More than 2 channels does not require stronger alignment than stereo
+ alignment <<= 1;
+ }
+ if (((uintptr_t)sharedBuffer->pointer() & (alignment - 1)) != 0) {
+ ALOGE("Invalid buffer alignment: address %p, channel count %u",
+ sharedBuffer->pointer(), channelCount);
+ lStatus = BAD_VALUE;
goto Exit;
}
- uint32_t minBufCount = latencyMs / ((1000 * mNormalFrameCount) / mSampleRate);
- if (minBufCount < 2) {
- minBufCount = 2;
+
+ // When initializing a shared buffer AudioTrack via constructors,
+ // there's no frameCount parameter.
+ // But when initializing a shared buffer AudioTrack via set(),
+ // there _is_ a frameCount parameter. We silently ignore it.
+ frameCount = sharedBuffer->size() / frameSize;
+ } else {
+ size_t minFrameCount = 0;
+ // For fast tracks we try to respect the application's request for notifications per buffer.
+ if (*flags & AUDIO_OUTPUT_FLAG_FAST) {
+ if (notificationsPerBuffer > 0) {
+ // Avoid possible arithmetic overflow during multiplication.
+ if (notificationsPerBuffer > SIZE_MAX / mFrameCount) {
+ ALOGE("Requested notificationPerBuffer=%u ignored for HAL frameCount=%zu",
+ notificationsPerBuffer, mFrameCount);
+ } else {
+ minFrameCount = mFrameCount * notificationsPerBuffer;
+ }
+ }
+ } else {
+ // For normal PCM streaming tracks, update minimum frame count.
+ // Buffer depth is forced to be at least 2 x the normal mixer frame count and
+ // cover audio hardware latency.
+ // This is probably too conservative, but legacy application code may depend on it.
+ // If you change this calculation, also review the start threshold which is related.
+ uint32_t latencyMs = latency_l();
+ if (latencyMs == 0) {
+ ALOGE("Error when retrieving output stream latency");
+ lStatus = UNKNOWN_ERROR;
+ goto Exit;
+ }
+
+ minFrameCount = AudioSystem::calculateMinFrameCount(latencyMs, mNormalFrameCount,
+ mSampleRate, sampleRate, speed /*, 0 mNotificationsPerBufferReq*/);
+
}
- // For normal mixing tracks, if speed is > 1.0f (normal), AudioTrack
- // or the client should compute and pass in a larger buffer request.
- size_t minFrameCount =
- minBufCount * sourceFramesNeededWithTimestretch(
- sampleRate, mNormalFrameCount,
- mSampleRate, AUDIO_TIMESTRETCH_SPEED_NORMAL /*speed*/);
- if (frameCount < minFrameCount) { // including frameCount == 0
+ if (frameCount < minFrameCount) {
frameCount = minFrameCount;
}
}
+
+ // Make sure that application is notified with sufficient margin before underrun.
+ // The client can divide the AudioTrack buffer into sub-buffers,
+ // and expresses its desire to server as the notification frame count.
+ if (sharedBuffer == 0 && audio_is_linear_pcm(format)) {
+ size_t maxNotificationFrames;
+ if (*flags & AUDIO_OUTPUT_FLAG_FAST) {
+ // notify every HAL buffer, regardless of the size of the track buffer
+ maxNotificationFrames = mFrameCount;
+ } else {
+ // For normal tracks, use at least double-buffering if no sample rate conversion,
+ // or at least triple-buffering if there is sample rate conversion
+ const int nBuffering = sampleRate == mSampleRate ? 2 : 3;
+ maxNotificationFrames = frameCount / nBuffering;
+ // If client requested a fast track but this was denied, then use the smaller maximum.
+ if (requestedFlags & AUDIO_OUTPUT_FLAG_FAST) {
+ size_t maxNotificationFramesFastDenied = FMS_20 * sampleRate / 1000;
+ if (maxNotificationFrames > maxNotificationFramesFastDenied) {
+ maxNotificationFrames = maxNotificationFramesFastDenied;
+ }
+ }
+ }
+ if (notificationFrameCount == 0 || notificationFrameCount > maxNotificationFrames) {
+ if (notificationFrameCount == 0) {
+ ALOGD("Client defaulted notificationFrames to %zu for frameCount %zu",
+ maxNotificationFrames, frameCount);
+ } else {
+ ALOGW("Client adjusted notificationFrames from %zu to %zu for frameCount %zu",
+ notificationFrameCount, maxNotificationFrames, frameCount);
+ }
+ notificationFrameCount = maxNotificationFrames;
+ }
+ }
+
*pFrameCount = frameCount;
+ *pNotificationFrameCount = notificationFrameCount;
switch (mType) {
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index b685e1b..2ca273f 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -706,10 +706,13 @@
sp<Track> createTrack_l(
const sp<AudioFlinger::Client>& client,
audio_stream_type_t streamType,
- uint32_t sampleRate,
+ uint32_t *sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
size_t *pFrameCount,
+ size_t *pNotificationFrameCount,
+ uint32_t notificationsPerBuffer,
+ float speed,
const sp<IMemory>& sharedBuffer,
audio_session_t sessionId,
audio_output_flags_t *flags,
diff --git a/services/mediacodec/Android.mk b/services/mediacodec/Android.mk
index faeb0a7..9348ecd 100644
--- a/services/mediacodec/Android.mk
+++ b/services/mediacodec/Android.mk
@@ -1,28 +1,11 @@
LOCAL_PATH := $(call my-dir)
-# service library
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := MediaCodecService.cpp
-LOCAL_SHARED_LIBRARIES := \
- libmedia_omx \
- libbinder \
- libgui \
- libutils \
- liblog \
- libstagefright_omx \
- libstagefright_xmlparser
-LOCAL_MODULE:= libmediacodecservice
-LOCAL_VENDOR_MODULE := true
-LOCAL_32_BIT_ONLY := true
-include $(BUILD_SHARED_LIBRARY)
-
# service executable
include $(CLEAR_VARS)
LOCAL_REQUIRED_MODULES_arm := mediacodec.policy
LOCAL_SRC_FILES := main_codecservice.cpp
LOCAL_SHARED_LIBRARIES := \
libmedia_omx \
- libmediacodecservice \
libbinder \
libutils \
libgui \
@@ -42,6 +25,11 @@
LOCAL_VENDOR_MODULE := true
LOCAL_32_BIT_ONLY := true
LOCAL_INIT_RC := android.hardware.media.omx@1.0-service.rc
+
+ifeq ($(PRODUCT_FULL_TREBLE),true)
+LOCAL_CFLAGS += -DUSE_VNDBINDER
+endif
+
include $(BUILD_EXECUTABLE)
# service seccomp policy
diff --git a/services/mediacodec/MediaCodecService.cpp b/services/mediacodec/MediaCodecService.cpp
deleted file mode 100644
index 6b510c6..0000000
--- a/services/mediacodec/MediaCodecService.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "MediaCodecService"
-//#define LOG_NDEBUG 0
-#include <utils/Log.h>
-
-#include "MediaCodecService.h"
-
-namespace android {
-
-sp<IOMX> MediaCodecService::getOMX() {
-
- Mutex::Autolock autoLock(mOMXLock);
-
- if (mOMX.get() == NULL) {
- mOMX = new OMX();
- }
-
- return mOMX;
-}
-
-sp<IOMXStore> MediaCodecService::getOMXStore() {
-
- Mutex::Autolock autoLock(mOMXStoreLock);
-
- if (mOMXStore.get() == NULL) {
- mOMXStore = new OMXStore();
- }
-
- return mOMXStore;
-}
-
-status_t MediaCodecService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
- uint32_t flags)
-{
- return BnMediaCodecService::onTransact(code, data, reply, flags);
-}
-
-} // namespace android
diff --git a/services/mediacodec/MediaCodecService.h b/services/mediacodec/MediaCodecService.h
deleted file mode 100644
index 9301135..0000000
--- a/services/mediacodec/MediaCodecService.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_MEDIA_CODEC_SERVICE_H
-#define ANDROID_MEDIA_CODEC_SERVICE_H
-
-#include <binder/BinderService.h>
-#include <media/IMediaCodecService.h>
-#include <media/stagefright/omx/OMX.h>
-#include <media/stagefright/omx/OMXStore.h>
-
-namespace android {
-
-class MediaCodecService : public BinderService<MediaCodecService>,
- public BnMediaCodecService
-{
- friend class BinderService<MediaCodecService>; // for MediaCodecService()
-public:
- MediaCodecService() : BnMediaCodecService() { }
- virtual ~MediaCodecService() { }
- virtual void onFirstRef() { }
-
- static const char* getServiceName() { return "media.codec"; }
-
- virtual sp<IOMX> getOMX();
-
- virtual sp<IOMXStore> getOMXStore();
-
- virtual status_t onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags);
-
-private:
- Mutex mOMXLock;
- sp<IOMX> mOMX;
- Mutex mOMXStoreLock;
- sp<IOMXStore> mOMXStore;
-};
-
-} // namespace android
-
-#endif // ANDROID_MEDIA_CODEC_SERVICE_H
diff --git a/services/mediacodec/main_codecservice.cpp b/services/mediacodec/main_codecservice.cpp
index 79d6da5..6f14a42 100644
--- a/services/mediacodec/main_codecservice.cpp
+++ b/services/mediacodec/main_codecservice.cpp
@@ -15,22 +15,12 @@
** limitations under the License.
*/
-#include <fcntl.h>
-#include <sys/prctl.h>
-#include <sys/wait.h>
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
-#include <cutils/properties.h>
-
-#include <string>
-
#include <android-base/logging.h>
// from LOCAL_C_INCLUDES
-#include "MediaCodecService.h"
#include "minijail.h"
+#include <binder/ProcessState.h>
#include <hidl/HidlTransportSupport.h>
#include <media/stagefright/omx/1.0/Omx.h>
#include <media/stagefright/omx/1.0/OmxStore.h>
@@ -45,41 +35,33 @@
int main(int argc __unused, char** argv)
{
+ strcpy(argv[0], "media.codec");
LOG(INFO) << "mediacodecservice starting";
- bool treble = property_get_bool("persist.media.treble_omx", true);
- if (treble) {
- android::ProcessState::initWithDriver("/dev/vndbinder");
- }
-
signal(SIGPIPE, SIG_IGN);
SetUpMinijail(kSystemSeccompPolicyPath, kVendorSeccompPolicyPath);
- strcpy(argv[0], "media.codec");
+#ifdef USE_VNDBINDER
+ android::ProcessState::initWithDriver("/dev/vndbinder");
+ android::ProcessState::self()->startThreadPool();
+#endif // USE_VNDBINDER
::android::hardware::configureRpcThreadpool(64, false);
- sp<ProcessState> proc(ProcessState::self());
- if (treble) {
- using namespace ::android::hardware::media::omx::V1_0;
- sp<IOmxStore> omxStore = new implementation::OmxStore();
- if (omxStore == nullptr) {
- LOG(ERROR) << "Cannot create IOmxStore HAL service.";
- } else if (omxStore->registerAsService() != OK) {
- LOG(ERROR) << "Cannot register IOmxStore HAL service.";
- }
- sp<IOmx> omx = new implementation::Omx();
- if (omx == nullptr) {
- LOG(ERROR) << "Cannot create IOmx HAL service.";
- } else if (omx->registerAsService() != OK) {
- LOG(ERROR) << "Cannot register IOmx HAL service.";
- } else {
- LOG(INFO) << "Treble OMX service created.";
- }
+ using namespace ::android::hardware::media::omx::V1_0;
+ sp<IOmxStore> omxStore = new implementation::OmxStore();
+ if (omxStore == nullptr) {
+ LOG(ERROR) << "Cannot create IOmxStore HAL service.";
+ } else if (omxStore->registerAsService() != OK) {
+ LOG(ERROR) << "Cannot register IOmxStore HAL service.";
+ }
+ sp<IOmx> omx = new implementation::Omx();
+ if (omx == nullptr) {
+ LOG(ERROR) << "Cannot create IOmx HAL service.";
+ } else if (omx->registerAsService() != OK) {
+ LOG(ERROR) << "Cannot register IOmx HAL service.";
} else {
- MediaCodecService::instantiate();
- LOG(INFO) << "Non-Treble OMX service created.";
+ LOG(INFO) << "IOmx HAL service created.";
}
- ProcessState::self()->startThreadPool();
- IPCThreadState::self()->joinThreadPool();
+ ::android::hardware::joinRpcThreadpool();
}