Merge "Fix plugin loading"
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index f656008..ba2100c 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -335,7 +335,7 @@
return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
}
out->numCameras = numCameras;
- out->cameraIds = new const char*[numCameras] {nullptr};
+ out->cameraIds = new const char*[numCameras];
if (!out->cameraIds) {
ALOGE("Allocate memory for ACameraIdList failed!");
deleteCameraIdList(out);
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index b28d509..9a236fc 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -124,29 +124,6 @@
include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= \
- sf2.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
- libstagefright liblog libutils libbinder libstagefright_foundation \
- libmedia libgui libcutils
-
-LOCAL_C_INCLUDES:= \
- frameworks/av/media/libstagefright \
- $(TOP)/frameworks/native/include/media/openmax
-
-LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE:= sf2
-
-include $(BUILD_EXECUTABLE)
-
-################################################################################
-
-include $(CLEAR_VARS)
-
LOCAL_SRC_FILES:= \
codec.cpp \
SimplePlayer.cpp \
diff --git a/cmds/stagefright/sf2.cpp b/cmds/stagefright/sf2.cpp
deleted file mode 100644
index 12bbfd1..0000000
--- a/cmds/stagefright/sf2.cpp
+++ /dev/null
@@ -1,788 +0,0 @@
-/*
- * Copyright (C) 2010 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 "sf2"
-#include <inttypes.h>
-#include <utils/Log.h>
-
-#include <signal.h>
-
-#include <binder/ProcessState.h>
-
-#include <media/IMediaHTTPService.h>
-
-#include <media/stagefright/foundation/hexdump.h>
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-#include <media/stagefright/ACodec.h>
-#include <media/stagefright/DataSource.h>
-#include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaExtractor.h>
-#include <media/stagefright/MediaSource.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/Utils.h>
-
-#include <gui/SurfaceComposerClient.h>
-#include <gui/Surface.h>
-
-#include "include/ESDS.h"
-
-using namespace android;
-
-volatile static bool ctrlc = false;
-
-static sighandler_t oldhandler = NULL;
-
-static void mysighandler(int signum) {
- if (signum == SIGINT) {
- ctrlc = true;
- return;
- }
- oldhandler(signum);
-}
-
-namespace {
-
-enum {
- kWhatFillThisBuffer = 'fill',
- kWhatDrainThisBuffer = 'drai',
- kWhatEOS = 'eos ',
- kWhatStopCompleted = 'scom',
- kWhatReleaseCompleted = 'rcom',
- kWhatFlushCompleted = 'fcom',
- kWhatError = 'erro',
-};
-
-class Sf2Callback : public CodecBase::Callback {
-public:
- explicit Sf2Callback(const sp<AMessage> ¬ify);
- ~Sf2Callback();
-
- virtual void fillThisBuffer(IOMX::buffer_id bufferId, const sp<MediaCodecBuffer> &buffer,
- const sp<AMessage> &reply) override;
- virtual void drainThisBuffer(IOMX::buffer_id bufferId, const sp<MediaCodecBuffer> &buffer,
- int32_t flags, const sp<AMessage> &reply) override;
- virtual void onEos(status_t err) override;
- virtual void onStopCompleted() override;
- virtual void onReleaseCompleted() override;
- virtual void onFlushCompleted() override;
- virtual void onError(status_t err, enum ActionCode actionCode) override;
- // Events below are not handled; thus ignore.
- virtual void onComponentAllocated(const char *) override {}
- virtual void onComponentConfigured(const sp<AMessage> &, const sp<AMessage> &) override {}
- virtual void onInputSurfaceCreated(
- const sp<AMessage> &,
- const sp<AMessage> &,
- const sp<BufferProducerWrapper> &) override {}
- virtual void onInputSurfaceCreationFailed(status_t) override {}
- virtual void onInputSurfaceAccepted(const sp<AMessage> &, const sp<AMessage> &) override {}
- virtual void onInputSurfaceDeclined(status_t) override {}
- virtual void onSignaledInputEOS(status_t) override {}
- virtual void onBuffersAllocated(int32_t, const sp<CodecBase::PortDescription> &) override {}
- virtual void onOutputFramesRendered(const std::list<FrameRenderTracker::Info> &) override {}
-private:
- const sp<AMessage> mNotify;
-};
-
-Sf2Callback::Sf2Callback(const sp<AMessage> ¬ify) : mNotify(notify) {}
-
-Sf2Callback::~Sf2Callback() {}
-
-void Sf2Callback::fillThisBuffer(
- IOMX::buffer_id bufferId,
- const sp<MediaCodecBuffer> &buffer,
- const sp<AMessage> &reply) {
- sp<AMessage> notify(mNotify->dup());
- notify->setInt32("what", kWhatFillThisBuffer);
- notify->setInt32("buffer-id", bufferId);
- notify->setObject("buffer", buffer);
- notify->setMessage("reply", reply);
- notify->post();
-}
-
-void Sf2Callback::drainThisBuffer(
- IOMX::buffer_id bufferId,
- const sp<MediaCodecBuffer> &buffer,
- int32_t flags,
- const sp<AMessage> &reply) {
- sp<AMessage> notify(mNotify->dup());
- notify->setInt32("what", kWhatDrainThisBuffer);
- notify->setInt32("buffer-id", bufferId);
- notify->setObject("buffer", buffer);
- notify->setInt32("flags", flags);
- notify->setMessage("reply", reply);
- notify->post();
-}
-
-void Sf2Callback::onEos(status_t err) {
- sp<AMessage> notify(mNotify->dup());
- notify->setInt32("what", kWhatEOS);
- notify->setInt32("err", err);
- notify->post();
-}
-
-void Sf2Callback::onStopCompleted() {
- sp<AMessage> notify(mNotify->dup());
- notify->setInt32("what", kWhatStopCompleted);
- notify->post();
-}
-
-void Sf2Callback::onReleaseCompleted() {
- sp<AMessage> notify(mNotify->dup());
- notify->setInt32("what", kWhatReleaseCompleted);
- notify->post();
-}
-
-void Sf2Callback::onFlushCompleted() {
- sp<AMessage> notify(mNotify->dup());
- notify->setInt32("what", kWhatFlushCompleted);
- notify->post();
-}
-
-void Sf2Callback::onError(status_t err, enum ActionCode actionCode) {
- sp<AMessage> notify(mNotify->dup());
- notify->setInt32("what", kWhatError);
- notify->setInt32("err", err);
- notify->setInt32("actionCode", actionCode);
- notify->post();
-}
-
-} // namespace
-
-struct Controller : public AHandler {
- Controller(const char *uri, bool decodeAudio,
- const sp<Surface> &surface, bool renderToSurface)
- : mURI(uri),
- mDecodeAudio(decodeAudio),
- mSurface(surface),
- mRenderToSurface(renderToSurface),
- mCodec(new ACodec),
- mIsVorbis(false) {
- CHECK(!mDecodeAudio || mSurface == NULL);
- }
-
- void startAsync() {
- (new AMessage(kWhatStart, this))->post();
- }
-
-protected:
- virtual ~Controller() {
- }
-
- virtual void printStatistics() {
- int64_t delayUs = ALooper::GetNowUs() - mStartTimeUs;
-
- if (mDecodeAudio) {
- printf("%" PRId64 " bytes received. %.2f KB/sec\n",
- mTotalBytesReceived,
- mTotalBytesReceived * 1E6 / 1024 / delayUs);
- } else {
- printf("%d frames decoded, %.2f fps. %" PRId64 " bytes "
- "received. %.2f KB/sec\n",
- mNumOutputBuffersReceived,
- mNumOutputBuffersReceived * 1E6 / delayUs,
- mTotalBytesReceived,
- mTotalBytesReceived * 1E6 / 1024 / delayUs);
- }
- }
-
- virtual void onMessageReceived(const sp<AMessage> &msg) {
- if (ctrlc) {
- printf("\n");
- printStatistics();
- (new AMessage(kWhatStop, this))->post();
- ctrlc = false;
- }
- switch (msg->what()) {
- case kWhatStart:
- {
-#if 1
- mDecodeLooper = looper();
-#else
- mDecodeLooper = new ALooper;
- mDecodeLooper->setName("sf2 decode looper");
- mDecodeLooper->start();
-#endif
-
- sp<DataSource> dataSource =
- DataSource::CreateFromURI(
- NULL /* httpService */, mURI.c_str());
-
- sp<IMediaExtractor> extractor =
- MediaExtractor::Create(dataSource);
-
- for (size_t i = 0; i < extractor->countTracks(); ++i) {
- sp<MetaData> meta = extractor->getTrackMetaData(i);
-
- const char *mime;
- CHECK(meta->findCString(kKeyMIMEType, &mime));
-
- if (!strncasecmp(mDecodeAudio ? "audio/" : "video/",
- mime, 6)) {
- mSource = extractor->getTrack(i);
-
- if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
- mIsVorbis = true;
- } else {
- mIsVorbis = false;
- }
- break;
- }
- }
- if (mSource == NULL) {
- printf("no %s track found\n", mDecodeAudio ? "audio" : "video");
- exit (1);
- }
-
- CHECK_EQ(mSource->start(), (status_t)OK);
-
- mDecodeLooper->registerHandler(mCodec);
-
- mCodec->setCallback(
- std::make_shared<Sf2Callback>(new AMessage(kWhatCodecNotify, this)));
-
- sp<AMessage> format = makeFormat(mSource->getFormat());
-
- if (mSurface != NULL) {
- format->setObject("surface", mSurface);
- }
-
- mCodec->initiateSetup(format);
-
- mCSDIndex = 0;
- mStartTimeUs = ALooper::GetNowUs();
- mNumOutputBuffersReceived = 0;
- mTotalBytesReceived = 0;
- mLeftOverBuffer = NULL;
- mFinalResult = OK;
- mSeekState = SEEK_NONE;
-
- // (new AMessage(kWhatSeek, this))->post(5000000ll);
- break;
- }
-
- case kWhatSeek:
- {
- printf("+");
- fflush(stdout);
-
- CHECK(mSeekState == SEEK_NONE
- || mSeekState == SEEK_FLUSH_COMPLETED);
-
- if (mLeftOverBuffer != NULL) {
- mLeftOverBuffer->release();
- mLeftOverBuffer = NULL;
- }
-
- mSeekState = SEEK_FLUSHING;
- mSeekTimeUs = 30000000ll;
-
- mCodec->signalFlush();
- break;
- }
-
- case kWhatStop:
- {
- if (mLeftOverBuffer != NULL) {
- mLeftOverBuffer->release();
- mLeftOverBuffer = NULL;
- }
-
- CHECK_EQ(mSource->stop(), (status_t)OK);
- mSource.clear();
-
- mCodec->initiateShutdown();
- break;
- }
-
- case kWhatCodecNotify:
- {
- int32_t what;
- CHECK(msg->findInt32("what", &what));
-
- if (what == kWhatFillThisBuffer) {
- onFillThisBuffer(msg);
- } else if (what == kWhatDrainThisBuffer) {
- if ((mNumOutputBuffersReceived++ % 16) == 0) {
- printf(".");
- fflush(stdout);
- }
-
- onDrainThisBuffer(msg);
- } else if (what == kWhatEOS
- || what == kWhatError) {
- printf((what == kWhatEOS) ? "$\n" : "E\n");
-
- printStatistics();
- (new AMessage(kWhatStop, this))->post();
- } else if (what == kWhatFlushCompleted) {
- mSeekState = SEEK_FLUSH_COMPLETED;
- mCodec->signalResume();
-
- (new AMessage(kWhatSeek, this))->post(5000000ll);
- } else if (what == kWhatStopCompleted ||
- what == kWhatReleaseCompleted) {
- mDecodeLooper->unregisterHandler(mCodec->id());
-
- if (mDecodeLooper != looper()) {
- mDecodeLooper->stop();
- }
-
- looper()->stop();
- }
- break;
- }
-
- default:
- TRESPASS();
- break;
- }
- }
-
-private:
- enum {
- kWhatStart = 'strt',
- kWhatStop = 'stop',
- kWhatCodecNotify = 'noti',
- kWhatSeek = 'seek',
- };
-
- sp<ALooper> mDecodeLooper;
-
- AString mURI;
- bool mDecodeAudio;
- sp<Surface> mSurface;
- bool mRenderToSurface;
- sp<ACodec> mCodec;
- sp<IMediaSource> mSource;
- bool mIsVorbis;
-
- Vector<sp<ABuffer> > mCSD;
- size_t mCSDIndex;
-
- MediaBuffer *mLeftOverBuffer;
- status_t mFinalResult;
-
- int64_t mStartTimeUs;
- int32_t mNumOutputBuffersReceived;
- int64_t mTotalBytesReceived;
-
- enum SeekState {
- SEEK_NONE,
- SEEK_FLUSHING,
- SEEK_FLUSH_COMPLETED,
- };
- SeekState mSeekState;
- int64_t mSeekTimeUs;
-
- sp<AMessage> makeFormat(const sp<MetaData> &meta) {
- CHECK(mCSD.isEmpty());
-
- const char *mime;
- CHECK(meta->findCString(kKeyMIMEType, &mime));
-
- sp<AMessage> msg = new AMessage;
- msg->setString("mime", mime);
-
- if (!strncasecmp("video/", mime, 6)) {
- int32_t width, height;
- CHECK(meta->findInt32(kKeyWidth, &width));
- CHECK(meta->findInt32(kKeyHeight, &height));
-
- msg->setInt32("width", width);
- msg->setInt32("height", height);
- } else {
- CHECK(!strncasecmp("audio/", mime, 6));
-
- int32_t numChannels, sampleRate;
- CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
- CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
-
- msg->setInt32("channel-count", numChannels);
- msg->setInt32("sample-rate", sampleRate);
-
- int32_t isADTS;
- if (meta->findInt32(kKeyIsADTS, &isADTS) && isADTS != 0) {
- msg->setInt32("is-adts", true);
- }
- }
-
- uint32_t type;
- const void *data;
- size_t size;
- if (meta->findData(kKeyAVCC, &type, &data, &size)) {
- // Parse the AVCDecoderConfigurationRecord
-
- const uint8_t *ptr = (const uint8_t *)data;
-
- CHECK(size >= 7);
- CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1
- uint8_t profile __unused = ptr[1];
- uint8_t level __unused = ptr[3];
-
- // There is decodable content out there that fails the following
- // assertion, let's be lenient for now...
- // CHECK((ptr[4] >> 2) == 0x3f); // reserved
-
- size_t lengthSize __unused = 1 + (ptr[4] & 3);
-
- // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
- // violates it...
- // CHECK((ptr[5] >> 5) == 7); // reserved
-
- size_t numSeqParameterSets = ptr[5] & 31;
-
- ptr += 6;
- size -= 6;
-
- sp<ABuffer> buffer = new ABuffer(1024);
- buffer->setRange(0, 0);
-
- for (size_t i = 0; i < numSeqParameterSets; ++i) {
- CHECK(size >= 2);
- size_t length = U16_AT(ptr);
-
- ptr += 2;
- size -= 2;
-
- CHECK(size >= length);
-
- memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4);
- memcpy(buffer->data() + buffer->size() + 4, ptr, length);
- buffer->setRange(0, buffer->size() + 4 + length);
-
- ptr += length;
- size -= length;
- }
-
- buffer->meta()->setInt32("csd", true);
- mCSD.push(buffer);
-
- buffer = new ABuffer(1024);
- buffer->setRange(0, 0);
-
- CHECK(size >= 1);
- size_t numPictureParameterSets = *ptr;
- ++ptr;
- --size;
-
- for (size_t i = 0; i < numPictureParameterSets; ++i) {
- CHECK(size >= 2);
- size_t length = U16_AT(ptr);
-
- ptr += 2;
- size -= 2;
-
- CHECK(size >= length);
-
- memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4);
- memcpy(buffer->data() + buffer->size() + 4, ptr, length);
- buffer->setRange(0, buffer->size() + 4 + length);
-
- ptr += length;
- size -= length;
- }
-
- buffer->meta()->setInt32("csd", true);
- mCSD.push(buffer);
-
- msg->setBuffer("csd", buffer);
- } else if (meta->findData(kKeyESDS, &type, &data, &size)) {
- ESDS esds((const char *)data, size);
- CHECK_EQ(esds.InitCheck(), (status_t)OK);
-
- const void *codec_specific_data;
- size_t codec_specific_data_size;
- esds.getCodecSpecificInfo(
- &codec_specific_data, &codec_specific_data_size);
-
- sp<ABuffer> buffer = new ABuffer(codec_specific_data_size);
-
- memcpy(buffer->data(), codec_specific_data,
- codec_specific_data_size);
-
- buffer->meta()->setInt32("csd", true);
- mCSD.push(buffer);
- } else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) {
- sp<ABuffer> buffer = new ABuffer(size);
- memcpy(buffer->data(), data, size);
-
- buffer->meta()->setInt32("csd", true);
- mCSD.push(buffer);
-
- CHECK(meta->findData(kKeyVorbisBooks, &type, &data, &size));
-
- buffer = new ABuffer(size);
- memcpy(buffer->data(), data, size);
-
- buffer->meta()->setInt32("csd", true);
- mCSD.push(buffer);
- }
-
- int32_t maxInputSize;
- if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) {
- msg->setInt32("max-input-size", maxInputSize);
- }
-
- return msg;
- }
-
- void onFillThisBuffer(const sp<AMessage> &msg) {
- sp<AMessage> reply;
- CHECK(msg->findMessage("reply", &reply));
-
- if (mSource == NULL || mSeekState == SEEK_FLUSHING) {
- reply->setInt32("err", ERROR_END_OF_STREAM);
- reply->post();
- return;
- }
-
- sp<ABuffer> outBuffer;
- CHECK(msg->findBuffer("buffer", &outBuffer));
-
- if (mCSDIndex < mCSD.size()) {
- outBuffer = mCSD.editItemAt(mCSDIndex++);
- outBuffer->meta()->setInt64("timeUs", 0);
- } else {
- size_t sizeLeft = outBuffer->capacity();
- outBuffer->setRange(0, 0);
-
- int32_t n = 0;
-
- for (;;) {
- MediaBuffer *inBuffer;
-
- if (mLeftOverBuffer != NULL) {
- inBuffer = mLeftOverBuffer;
- mLeftOverBuffer = NULL;
- } else if (mFinalResult != OK) {
- break;
- } else {
- MediaSource::ReadOptions options;
- if (mSeekState == SEEK_FLUSH_COMPLETED) {
- options.setSeekTo(mSeekTimeUs);
- mSeekState = SEEK_NONE;
- }
- status_t err = mSource->read(&inBuffer, &options);
-
- if (err != OK) {
- mFinalResult = err;
- break;
- }
- }
-
- size_t sizeNeeded = inBuffer->range_length();
- if (mIsVorbis) {
- // Vorbis data is suffixed with the number of
- // valid samples on the page.
- sizeNeeded += sizeof(int32_t);
- }
-
- if (sizeNeeded > sizeLeft) {
- if (outBuffer->size() == 0) {
- ALOGE("Unable to fit even a single input buffer of size %zu.",
- sizeNeeded);
- }
- CHECK_GT(outBuffer->size(), 0u);
-
- mLeftOverBuffer = inBuffer;
- break;
- }
-
- ++n;
-
- if (outBuffer->size() == 0) {
- int64_t timeUs;
- CHECK(inBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
-
- outBuffer->meta()->setInt64("timeUs", timeUs);
- }
-
- memcpy(outBuffer->data() + outBuffer->size(),
- (const uint8_t *)inBuffer->data()
- + inBuffer->range_offset(),
- inBuffer->range_length());
-
- if (mIsVorbis) {
- int32_t numPageSamples;
- if (!inBuffer->meta_data()->findInt32(
- kKeyValidSamples, &numPageSamples)) {
- numPageSamples = -1;
- }
-
- memcpy(outBuffer->data()
- + outBuffer->size() + inBuffer->range_length(),
- &numPageSamples, sizeof(numPageSamples));
- }
-
- outBuffer->setRange(
- 0, outBuffer->size() + sizeNeeded);
-
- sizeLeft -= sizeNeeded;
-
- inBuffer->release();
- inBuffer = NULL;
-
- break; // Don't coalesce
- }
-
- ALOGV("coalesced %d input buffers", n);
-
- if (outBuffer->size() == 0) {
- CHECK_NE(mFinalResult, (status_t)OK);
-
- reply->setInt32("err", mFinalResult);
- reply->post();
- return;
- }
- }
-
- reply->setBuffer("buffer", outBuffer);
- reply->post();
- }
-
- void onDrainThisBuffer(const sp<AMessage> &msg) {
- sp<ABuffer> buffer;
- CHECK(msg->findBuffer("buffer", &buffer));
-
- mTotalBytesReceived += buffer->size();
-
- sp<AMessage> reply;
- CHECK(msg->findMessage("reply", &reply));
-
- if (mRenderToSurface) {
- reply->setInt32("render", 1);
- }
-
- reply->post();
- }
-
- DISALLOW_EVIL_CONSTRUCTORS(Controller);
-};
-
-static void usage(const char *me) {
- fprintf(stderr, "usage: %s\n", me);
- fprintf(stderr, " -h(elp)\n");
- fprintf(stderr, " -a(udio)\n");
-
- fprintf(stderr,
- " -S(urface) Allocate output buffers on a surface.\n"
- " -R(ender) Render surface-allocated buffers.\n");
-}
-
-int main(int argc, char **argv) {
- android::ProcessState::self()->startThreadPool();
-
- bool decodeAudio = false;
- bool useSurface = false;
- bool renderToSurface = false;
-
- int res;
- while ((res = getopt(argc, argv, "haSR")) >= 0) {
- switch (res) {
- case 'a':
- decodeAudio = true;
- break;
-
- case 'S':
- useSurface = true;
- break;
-
- case 'R':
- renderToSurface = true;
- break;
-
- case '?':
- case 'h':
- default:
- {
- usage(argv[0]);
- return 1;
- }
- }
- }
-
- argc -= optind;
- argv += optind;
-
- if (argc != 1) {
- usage(argv[-optind]);
- return 1;
- }
-
- sp<ALooper> looper = new ALooper;
- looper->setName("sf2");
-
- sp<SurfaceComposerClient> composerClient;
- sp<SurfaceControl> control;
- sp<Surface> surface;
-
- if (!decodeAudio && useSurface) {
- composerClient = new SurfaceComposerClient;
- CHECK_EQ(composerClient->initCheck(), (status_t)OK);
-
- control = composerClient->createSurface(
- String8("A Surface"),
- 1280,
- 800,
- PIXEL_FORMAT_RGB_565,
- 0);
-
- CHECK(control != NULL);
- CHECK(control->isValid());
-
- SurfaceComposerClient::openGlobalTransaction();
- CHECK_EQ(control->setLayer(INT_MAX), (status_t)OK);
- CHECK_EQ(control->show(), (status_t)OK);
- SurfaceComposerClient::closeGlobalTransaction();
-
- surface = control->getSurface();
- CHECK(surface != NULL);
-
- CHECK_EQ((status_t)OK,
- native_window_api_connect(
- surface.get(), NATIVE_WINDOW_API_MEDIA));
- }
-
- sp<Controller> controller =
- new Controller(argv[0], decodeAudio, surface, renderToSurface);
-
- looper->registerHandler(controller);
-
- signal(SIGINT, mysighandler);
-
- controller->startAsync();
-
- CHECK_EQ(looper->start(true /* runOnCallingThread */), (status_t)OK);
-
- looper->unregisterHandler(controller->id());
-
- if (!decodeAudio && useSurface) {
- CHECK_EQ((status_t)OK,
- native_window_api_disconnect(
- surface.get(), NATIVE_WINDOW_API_MEDIA));
-
- composerClient->dispose();
- }
-
- return 0;
-}
-
diff --git a/services/audioflinger/AudioMixer.h b/include/media/AudioMixer.h
similarity index 99%
rename from services/audioflinger/AudioMixer.h
rename to include/media/AudioMixer.h
index 540caac..87ada76 100644
--- a/services/audioflinger/AudioMixer.h
+++ b/include/media/AudioMixer.h
@@ -22,15 +22,14 @@
#include <sys/types.h>
#include <media/AudioBufferProvider.h>
+#include <media/AudioResampler.h>
#include <media/AudioResamplerPublic.h>
+#include <media/BufferProviders.h>
#include <media/nbaio/NBLog.h>
#include <system/audio.h>
#include <utils/Compat.h>
#include <utils/threads.h>
-#include "AudioResampler.h"
-#include "BufferProviders.h"
-
// FIXME This is actually unity gain, which might not be max in future, expressed in U.12
#define MAX_GAIN_INT AudioMixer::UNITY_GAIN_INT
diff --git a/services/audioflinger/AudioResampler.h b/include/media/AudioResampler.h
similarity index 100%
rename from services/audioflinger/AudioResampler.h
rename to include/media/AudioResampler.h
diff --git a/services/audioflinger/BufferProviders.h b/include/media/BufferProviders.h
similarity index 96%
rename from services/audioflinger/BufferProviders.h
rename to include/media/BufferProviders.h
index 2a857fe..68b3f23 100644
--- a/services/audioflinger/BufferProviders.h
+++ b/include/media/BufferProviders.h
@@ -23,11 +23,15 @@
#include <media/AudioBufferProvider.h>
#include <system/audio.h>
#include <system/audio_effect.h>
-#include <sonic.h>
#include <utils/StrongPointer.h>
+// external forward declaration from external/sonic/sonic.h
+struct sonicStreamStruct;
+typedef struct sonicStreamStruct *sonicStream;
+
namespace android {
+class EffectBufferHalInterface;
class EffectHalInterface;
class EffectsFactoryHalInterface;
@@ -108,6 +112,8 @@
protected:
sp<EffectsFactoryHalInterface> mEffectsFactory;
sp<EffectHalInterface> mDownmixInterface;
+ sp<EffectBufferHalInterface> mInBuffer;
+ sp<EffectBufferHalInterface> mOutBuffer;
effect_config_t mDownmixConfig;
// effect descriptor for the downmixer used by the mixer
diff --git a/services/audioflinger/LinearMap.h b/include/media/LinearMap.h
similarity index 100%
rename from services/audioflinger/LinearMap.h
rename to include/media/LinearMap.h
diff --git a/include/media/audiohal/EffectBufferHalInterface.h b/include/media/audiohal/EffectBufferHalInterface.h
new file mode 100644
index 0000000..102ec56
--- /dev/null
+++ b/include/media/audiohal/EffectBufferHalInterface.h
@@ -0,0 +1,58 @@
+/*
+ * 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_HARDWARE_EFFECT_BUFFER_HAL_INTERFACE_H
+#define ANDROID_HARDWARE_EFFECT_BUFFER_HAL_INTERFACE_H
+
+#include <system/audio_effect.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+// Abstraction for an audio buffer. It may be a "mirror" for
+// a buffer that the effect chain doesn't own, or a buffer owned by
+// the effect chain.
+class EffectBufferHalInterface : public RefBase
+{
+ public:
+ virtual audio_buffer_t* audioBuffer() = 0;
+ virtual void* externalData() const = 0;
+ // To be used when interacting with the code that doesn't know about
+ // "mirrored" buffers.
+ virtual void* ptr() {
+ return externalData() != nullptr ? externalData() : audioBuffer()->raw;
+ }
+
+ virtual void setExternalData(void* external) = 0;
+ virtual void setFrameCount(size_t frameCount) = 0;
+
+ virtual void update() = 0; // copies data from the external buffer, noop for allocated buffers
+ virtual void commit() = 0; // copies data to the external buffer, noop for allocated buffers
+
+ static status_t allocate(size_t size, sp<EffectBufferHalInterface>* buffer);
+ static status_t mirror(void* external, size_t size, sp<EffectBufferHalInterface>* buffer);
+
+ protected:
+ // Subclasses can not be constructed directly by clients.
+ EffectBufferHalInterface() {}
+
+ virtual ~EffectBufferHalInterface() {}
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_EFFECT_BUFFER_HAL_INTERFACE_H
diff --git a/include/media/audiohal/EffectHalInterface.h b/include/media/audiohal/EffectHalInterface.h
index 7bbd3b5..7f9a6fd 100644
--- a/include/media/audiohal/EffectHalInterface.h
+++ b/include/media/audiohal/EffectHalInterface.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_HARDWARE_EFFECT_HAL_INTERFACE_H
#define ANDROID_HARDWARE_EFFECT_HAL_INTERFACE_H
+#include <media/audiohal/EffectBufferHalInterface.h>
#include <system/audio_effect.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
@@ -26,14 +27,20 @@
class EffectHalInterface : public RefBase
{
public:
+ // Set the input buffer.
+ virtual status_t setInBuffer(const sp<EffectBufferHalInterface>& buffer) = 0;
+
+ // Set the output buffer.
+ virtual status_t setOutBuffer(const sp<EffectBufferHalInterface>& buffer) = 0;
+
// Effect process function. Takes input samples as specified
// in input buffer descriptor and output processed samples as specified
// in output buffer descriptor.
- virtual status_t process(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) = 0;
+ virtual status_t process() = 0;
// Process reverse stream function. This function is used to pass
// a reference stream to the effect engine.
- virtual status_t processReverse(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) = 0;
+ virtual status_t processReverse() = 0;
// Send a command and receive a response to/from effect engine.
virtual status_t command(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData,
@@ -42,6 +49,9 @@
// Returns the effect descriptor.
virtual status_t getDescriptor(effect_descriptor_t *pDescriptor) = 0;
+ // Free resources on the remote side.
+ virtual status_t close() = 0;
+
protected:
// Subclasses can not be constructed directly by clients.
EffectHalInterface() {}
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index d42012b..3420617 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -35,6 +35,7 @@
namespace android {
struct ABuffer;
+class ACodecBufferChannel;
class MediaCodecBuffer;
class MemoryDealer;
struct DescribeColorFormat2Params;
@@ -43,10 +44,9 @@
struct ACodec : public AHierarchicalStateMachine, public CodecBase {
ACodec();
- virtual void setNotificationMessage(const sp<AMessage> &msg);
-
void initiateSetup(const sp<AMessage> &msg);
+ virtual std::shared_ptr<BufferChannelBase> getBufferChannel() override;
virtual void initiateAllocateComponent(const sp<AMessage> &msg);
virtual void initiateConfigureComponent(const sp<AMessage> &msg);
virtual void initiateCreateInputSurface();
@@ -72,23 +72,6 @@
handleMessage(msg);
}
- struct PortDescription : public CodecBase::PortDescription {
- size_t countBuffers();
- IOMX::buffer_id bufferIDAt(size_t index) const;
- sp<MediaCodecBuffer> bufferAt(size_t index) const;
-
- private:
- friend struct ACodec;
-
- Vector<IOMX::buffer_id> mBufferIDs;
- Vector<sp<MediaCodecBuffer> > mBuffers;
-
- PortDescription();
- void addBuffer(IOMX::buffer_id id, const sp<MediaCodecBuffer> &buffer);
-
- DISALLOW_EVIL_CONSTRUCTORS(PortDescription);
- };
-
// Returns 0 if configuration is not supported. NOTE: this is treated by
// some OMX components as auto level, and by others as invalid level.
static int /* OMX_VIDEO_AVCLEVELTYPE */ getAVCLevelFor(
@@ -218,8 +201,6 @@
KeyedVector<int64_t, BufferStats> mBufferStats;
#endif
- sp<AMessage> mNotify;
-
sp<UninitializedState> mUninitializedState;
sp<LoadedState> mLoadedState;
sp<LoadedToIdleState> mLoadedToIdleState;
@@ -296,6 +277,8 @@
OMX_INDEXTYPE mDescribeColorAspectsIndex;
OMX_INDEXTYPE mDescribeHDRStaticInfoIndex;
+ std::shared_ptr<ACodecBufferChannel> mBufferChannel;
+
status_t setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode);
status_t allocateBuffersOnPort(OMX_U32 portIndex);
status_t freeBuffersOnPort(OMX_U32 portIndex);
diff --git a/include/media/stagefright/CodecBase.h b/include/media/stagefright/CodecBase.h
index 516f698..cfbaea4 100644
--- a/include/media/stagefright/CodecBase.h
+++ b/include/media/stagefright/CodecBase.h
@@ -24,6 +24,7 @@
#define STRINGIFY_ENUMS
+#include <media/ICrypto.h>
#include <media/IOMX.h>
#include <media/MediaCodecInfo.h>
#include <media/stagefright/MediaErrors.h>
@@ -37,6 +38,7 @@
namespace android {
+class BufferChannelBase;
class BufferProducerWrapper;
class MediaCodecBuffer;
struct PersistentSurface;
@@ -44,43 +46,15 @@
class Surface;
struct CodecBase : public AHandler, /* static */ ColorUtils {
- struct PortDescription;
-
/**
* This interface defines events firing from CodecBase back to MediaCodec.
* All methods must not block.
*/
- class Callback {
+ class CodecCallback {
public:
- virtual ~Callback() = default;
+ virtual ~CodecCallback() = default;
/**
- * Request MediaCodec to fill the specified input buffer.
- *
- * @param bufferId ID of the buffer, assigned by underlying component.
- * @param buffer a buffer to be filled.
- * @param reply a message to post once MediaCodec has filled the
- * buffer.
- */
- virtual void fillThisBuffer(
- IOMX::buffer_id bufferId,
- const sp<MediaCodecBuffer> &buffer,
- const sp<AMessage> &reply) = 0;
- /**
- * Request MediaCodec to drain the specified output buffer.
- *
- * @param bufferId ID of the buffer, assigned by underlying component.
- * @param buffer a buffer to be filled.
- * @param flags flags associated with this buffer (e.g. EOS).
- * @param reply a message to post once MediaCodec has filled the
- * buffer.
- */
- virtual void drainThisBuffer(
- IOMX::buffer_id bufferId,
- const sp<MediaCodecBuffer> &buffer,
- int32_t flags,
- const sp<AMessage> &reply) = 0;
- /**
* Notify MediaCodec for seeing an output EOS.
*
* @param err the underlying cause of the EOS. If the value is neither
@@ -89,6 +63,10 @@
*/
virtual void onEos(status_t err) = 0;
/**
+ * Notify MediaCodec that start operation is complete.
+ */
+ virtual void onStartCompleted() = 0;
+ /**
* Notify MediaCodec that stop operation is complete.
*/
virtual void onStopCompleted() = 0;
@@ -169,27 +147,55 @@
*/
virtual void onSignaledInputEOS(status_t err) = 0;
/**
- * Notify MediaCodec with the allocated buffers.
- *
- * @param portIndex zero for input port, one for output port.
- * @param portDesc a PortDescription object containing allocated
- * buffers.
- */
- virtual void onBuffersAllocated(int32_t portIndex, const sp<PortDescription> &portDesc) = 0;
- /**
* Notify MediaCodec that output frames are rendered with information on
* those frames.
*
* @param done a list of rendered frames.
*/
virtual void onOutputFramesRendered(const std::list<RenderedFrameInfo> &done) = 0;
+ /**
+ * Notify MediaCodec that output buffers are changed.
+ */
+ virtual void onOutputBuffersChanged() = 0;
};
+ /**
+ * This interface defines events firing from BufferChannelBase back to MediaCodec.
+ * All methods must not block.
+ */
+ class BufferCallback {
+ public:
+ virtual ~BufferCallback() = default;
+
+ /**
+ * Notify MediaCodec that an input buffer is available with given index.
+ * When BufferChannelBase::getInputBufferArray() is not called,
+ * BufferChannelBase may report different buffers with the same index if
+ * MediaCodec already queued/discarded the buffer. After calling
+ * BufferChannelBase::getInputBufferArray(), the buffer and index match the
+ * returned array.
+ */
+ virtual void onInputBufferAvailable(
+ size_t index, const sp<MediaCodecBuffer> &buffer) = 0;
+ /**
+ * Notify MediaCodec that an output buffer is available with given index.
+ * When BufferChannelBase::getOutputBufferArray() is not called,
+ * BufferChannelBase may report different buffers with the same index if
+ * MediaCodec already queued/discarded the buffer. After calling
+ * BufferChannelBase::getOutputBufferArray(), the buffer and index match the
+ * returned array.
+ */
+ virtual void onOutputBufferAvailable(
+ size_t index, const sp<MediaCodecBuffer> &buffer) = 0;
+ };
enum {
kMaxCodecBufferSize = 8192 * 4096 * 4, // 8K RGBA
};
- void setCallback(std::shared_ptr<Callback> &&callback);
+ inline void setCallback(std::unique_ptr<CodecCallback> &&callback) {
+ mCallback = std::move(callback);
+ }
+ virtual std::shared_ptr<BufferChannelBase> getBufferChannel() = 0;
virtual void initiateAllocateComponent(const sp<AMessage> &msg) = 0;
virtual void initiateConfigureComponent(const sp<AMessage> &msg) = 0;
@@ -215,33 +221,104 @@
virtual void signalSetParameters(const sp<AMessage> &msg) = 0;
virtual void signalEndOfInputStream() = 0;
- struct PortDescription : public RefBase {
- virtual size_t countBuffers() = 0;
- virtual IOMX::buffer_id bufferIDAt(size_t index) const = 0;
- virtual sp<MediaCodecBuffer> bufferAt(size_t index) const = 0;
-
- protected:
- PortDescription();
- virtual ~PortDescription();
-
- private:
- DISALLOW_EVIL_CONSTRUCTORS(PortDescription);
- };
-
/*
* Codec-related defines
*/
protected:
- CodecBase();
- virtual ~CodecBase();
+ CodecBase() = default;
+ virtual ~CodecBase() = default;
- std::shared_ptr<Callback> mCallback;
+ std::unique_ptr<CodecCallback> mCallback;
private:
DISALLOW_EVIL_CONSTRUCTORS(CodecBase);
};
+/**
+ * A channel between MediaCodec and CodecBase object which manages buffer
+ * passing. Only MediaCodec is expected to call these methods, and
+ * underlying CodecBase implementation should define its own interface
+ * separately for itself.
+ *
+ * Concurrency assumptions:
+ *
+ * 1) Clients may access the object at multiple threads concurrently.
+ * 2) All methods do not call underlying CodecBase object while holding a lock.
+ * 3) Code inside critical section executes within 1ms.
+ */
+class BufferChannelBase {
+public:
+ virtual ~BufferChannelBase() = default;
+
+ inline void setCallback(std::unique_ptr<CodecBase::BufferCallback> &&callback) {
+ mCallback = std::move(callback);
+ }
+
+ inline void setCrypto(const sp<ICrypto> &crypto) {
+ mCrypto = crypto;
+ }
+
+ /**
+ * Queue an input buffer into the buffer channel.
+ *
+ * @return OK if successful;
+ * -ENOENT if the buffer is not known (TODO: this should be
+ * handled gracefully in the future, here and below).
+ */
+ virtual status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) = 0;
+ /**
+ * Queue a secure input buffer into the buffer channel.
+ *
+ * @return OK if successful;
+ * -ENOENT if the buffer is not known;
+ * -ENOSYS if mCrypto is not set so that decryption is not
+ * possible;
+ * other errors if decryption failed.
+ */
+ virtual status_t queueSecureInputBuffer(
+ const sp<MediaCodecBuffer> &buffer,
+ bool secure,
+ const uint8_t *key,
+ const uint8_t *iv,
+ CryptoPlugin::Mode mode,
+ CryptoPlugin::Pattern pattern,
+ const CryptoPlugin::SubSample *subSamples,
+ size_t numSubSamples,
+ AString *errorDetailMsg) = 0;
+ /**
+ * Request buffer rendering at specified time.
+ *
+ * @param timestampNs nanosecond timestamp for rendering time.
+ * @return OK if successful;
+ * -ENOENT if the buffer is not known.
+ */
+ virtual status_t renderOutputBuffer(
+ const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) = 0;
+ /**
+ * Discard a buffer to the underlying CodecBase object.
+ *
+ * TODO: remove once this operation can be handled by just clearing the
+ * reference.
+ *
+ * @return OK if successful;
+ * -ENOENT if the buffer is not known.
+ */
+ virtual status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) = 0;
+ /**
+ * Clear and fill array with input buffers.
+ */
+ virtual void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) = 0;
+ /**
+ * Clear and fill array with output buffers.
+ */
+ virtual void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) = 0;
+
+protected:
+ std::unique_ptr<CodecBase::BufferCallback> mCallback;
+ sp<ICrypto> mCrypto;
+};
+
} // namespace android
#endif // CODEC_BASE_H_
diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h
index 1031de0..2e367bf 100644
--- a/include/media/stagefright/MediaCodec.h
+++ b/include/media/stagefright/MediaCodec.h
@@ -18,6 +18,9 @@
#define MEDIA_CODEC_H_
+#include <memory>
+#include <vector>
+
#include <gui/IGraphicBufferProducer.h>
#include <media/hardware/CryptoAPI.h>
#include <media/MediaCodecInfo.h>
@@ -32,12 +35,12 @@
struct AMessage;
struct AReplyToken;
struct AString;
+class BufferChannelBase;
struct CodecBase;
class IBatteryStats;
struct ICrypto;
class MediaCodecBuffer;
class IMemory;
-struct MemoryDealer;
class IResourceManagerClient;
class IResourceManagerService;
struct PersistentSurface;
@@ -252,11 +255,9 @@
};
struct BufferInfo {
- uint32_t mBufferID;
+ BufferInfo();
+
sp<MediaCodecBuffer> mData;
- sp<MediaCodecBuffer> mSecureData;
- sp<IMemory> mSharedEncryptedBuffer;
- sp<AMessage> mNotify;
bool mOwnedByClient;
};
@@ -301,7 +302,6 @@
sp<AMessage> mInputFormat;
sp<AMessage> mCallback;
sp<AMessage> mOnFrameRenderedNotification;
- sp<MemoryDealer> mDealer;
sp<IResourceManagerClient> mResourceManagerClient;
sp<ResourceManagerServiceProxy> mResourceManagerService;
@@ -327,8 +327,7 @@
Mutex mBufferLock;
List<size_t> mAvailPortBuffers[2];
- Vector<BufferInfo> mPortBuffers[2];
- Vector<sp<MediaCodecBuffer>> mPortBufferArrays[2];
+ std::vector<BufferInfo> mPortBuffers[2];
int32_t mDequeueInputTimeoutGeneration;
sp<AReplyToken> mDequeueInputReplyID;
@@ -345,6 +344,8 @@
bool mHaveInputSurface;
bool mHavePendingInputBuffers;
+ std::shared_ptr<BufferChannelBase> mBufferChannel;
+
MediaCodec(const sp<ALooper> &looper, pid_t pid, uid_t uid);
static sp<CodecBase> GetCodecBase(const AString &name, bool nameIsType = false);
diff --git a/include/media/stagefright/MediaFilter.h b/include/media/stagefright/MediaFilter.h
index c8b681c..0c10d11 100644
--- a/include/media/stagefright/MediaFilter.h
+++ b/include/media/stagefright/MediaFilter.h
@@ -21,6 +21,7 @@
namespace android {
+class ACodecBufferChannel;
struct GraphicBufferListener;
class MemoryDealer;
struct SimpleFilter;
@@ -28,6 +29,7 @@
struct MediaFilter : public CodecBase {
MediaFilter();
+ virtual std::shared_ptr<BufferChannelBase> getBufferChannel() override;
virtual void initiateAllocateComponent(const sp<AMessage> &msg);
virtual void initiateConfigureComponent(const sp<AMessage> &msg);
virtual void initiateCreateInputSurface();
@@ -45,25 +47,6 @@
virtual void onMessageReceived(const sp<AMessage> &msg);
- struct PortDescription : public CodecBase::PortDescription {
- virtual size_t countBuffers();
- virtual IOMX::buffer_id bufferIDAt(size_t index) const;
- virtual sp<MediaCodecBuffer> bufferAt(size_t index) const;
-
- protected:
- PortDescription();
-
- private:
- friend struct MediaFilter;
-
- Vector<IOMX::buffer_id> mBufferIDs;
- Vector<sp<MediaCodecBuffer> > mBuffers;
-
- void addBuffer(IOMX::buffer_id id, const sp<MediaCodecBuffer> &buffer);
-
- DISALLOW_EVIL_CONSTRUCTORS(PortDescription);
- };
-
protected:
virtual ~MediaFilter();
@@ -130,6 +113,8 @@
sp<SimpleFilter> mFilter;
sp<GraphicBufferListener> mGraphicBufferListener;
+ std::shared_ptr<ACodecBufferChannel> mBufferChannel;
+
// helper functions
void signalProcessBuffers();
void signalError(status_t error);
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
new file mode 100644
index 0000000..03dce0c
--- /dev/null
+++ b/media/libaudioclient/Android.bp
@@ -0,0 +1,45 @@
+cc_library_shared {
+ name: "libaudioclient",
+ srcs: [
+ "AudioEffect.cpp",
+ "AudioPolicy.cpp",
+ "AudioRecord.cpp",
+ "AudioSystem.cpp",
+ "AudioTrack.cpp",
+ "AudioTrackShared.cpp",
+ "IAudioFlinger.cpp",
+ "IAudioFlingerClient.cpp",
+ "IAudioPolicyService.cpp",
+ "IAudioPolicyServiceClient.cpp",
+ "IAudioRecord.cpp",
+ "IAudioTrack.cpp",
+ "IEffect.cpp",
+ "IEffectClient.cpp",
+ "ToneGenerator.cpp",
+ ],
+ shared_libs: [
+ "liblog",
+ "libcutils",
+ "libutils",
+ "libbinder",
+ "libdl",
+ "libaudioutils",
+ ],
+ export_shared_lib_headers: ["libbinder"],
+ // for memory heap analysis
+ static_libs: [
+ "libc_malloc_debug_backtrace",
+ "libc_logging",
+ ],
+ cflags: [
+ "-Werror",
+ "-Wno-error=deprecated-declarations",
+ "-Wall",
+ ],
+ sanitize: {
+ misc_undefined : [
+ "unsigned-integer-overflow",
+ "signed-integer-overflow",
+ ],
+ },
+}
diff --git a/media/libaudioclient/Android.mk b/media/libaudioclient/Android.mk
deleted file mode 100644
index 348ab50..0000000
--- a/media/libaudioclient/Android.mk
+++ /dev/null
@@ -1,50 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES += \
- AudioEffect.cpp \
- AudioPolicy.cpp \
- AudioRecord.cpp \
- AudioSystem.cpp \
- AudioTrack.cpp \
- AudioTrackShared.cpp \
- IAudioFlinger.cpp \
- IAudioFlingerClient.cpp \
- IAudioPolicyService.cpp \
- IAudioPolicyServiceClient.cpp \
- IAudioRecord.cpp \
- IAudioTrack.cpp \
- IEffect.cpp \
- IEffectClient.cpp \
- ToneGenerator.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
- liblog libcutils libutils libbinder \
- libdl libaudioutils \
-
-LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := libbinder
-
-# for memory heap analysis
-LOCAL_STATIC_LIBRARIES := libc_malloc_debug_backtrace libc_logging
-
-LOCAL_MODULE:= libaudioclient
-
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_C_INCLUDES := \
- $(TOP)/frameworks/native/include/media/openmax \
- $(TOP)/frameworks/av/include/media/ \
- $(TOP)/frameworks/av/media/libstagefright \
- $(TOP)/frameworks/av/media/libmedia/aidl \
- $(call include-path-for, audio-utils)
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
- frameworks/av/include/media \
- frameworks/av/media/libmedia/aidl
-
-LOCAL_CFLAGS += -Werror -Wno-error=deprecated-declarations -Wall
-LOCAL_SANITIZE := unsigned-integer-overflow signed-integer-overflow
-
-include $(BUILD_SHARED_LIBRARY)
-
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 776e509..f0f413d 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -834,10 +834,15 @@
static_cast <audio_policy_dev_state_t>(data.readInt32());
const char *device_address = data.readCString();
const char *device_name = data.readCString();
- reply->writeInt32(static_cast<uint32_t> (setDeviceConnectionState(device,
- state,
- device_address,
- device_name)));
+ if (device_address == nullptr || device_name == nullptr) {
+ ALOGE("Bad Binder transaction: SET_DEVICE_CONNECTION_STATE for device %u", device);
+ reply->writeInt32(static_cast<int32_t> (BAD_VALUE));
+ } else {
+ reply->writeInt32(static_cast<uint32_t> (setDeviceConnectionState(device,
+ state,
+ device_address,
+ device_name)));
+ }
return NO_ERROR;
} break;
@@ -846,8 +851,13 @@
audio_devices_t device =
static_cast<audio_devices_t> (data.readInt32());
const char *device_address = data.readCString();
- reply->writeInt32(static_cast<uint32_t> (getDeviceConnectionState(device,
- device_address)));
+ if (device_address == nullptr) {
+ ALOGE("Bad Binder transaction: GET_DEVICE_CONNECTION_STATE for device %u", device);
+ reply->writeInt32(static_cast<int32_t> (AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
+ } else {
+ reply->writeInt32(static_cast<uint32_t> (getDeviceConnectionState(device,
+ device_address)));
+ }
return NO_ERROR;
} break;
@@ -857,9 +867,14 @@
static_cast <audio_devices_t>(data.readInt32());
const char *device_address = data.readCString();
const char *device_name = data.readCString();
- reply->writeInt32(static_cast<uint32_t> (handleDeviceConfigChange(device,
- device_address,
- device_name)));
+ if (device_address == nullptr || device_name == nullptr) {
+ ALOGE("Bad Binder transaction: HANDLE_DEVICE_CONFIG_CHANGE for device %u", device);
+ reply->writeInt32(static_cast<int32_t> (BAD_VALUE));
+ } else {
+ reply->writeInt32(static_cast<uint32_t> (handleDeviceConfigChange(device,
+ device_address,
+ device_name)));
+ }
return NO_ERROR;
} break;
diff --git a/media/libaudiohal/Android.mk b/media/libaudiohal/Android.mk
index 893c626..deb26b5 100644
--- a/media/libaudiohal/Android.mk
+++ b/media/libaudiohal/Android.mk
@@ -3,12 +3,10 @@
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := \
- libbase \
- libcutils \
- libeffects \
- libfmq \
+ libcutils \
+ libeffects \
libhardware \
- liblog \
+ liblog \
libutils
ifeq ($(ENABLE_TREBLE), true)
@@ -19,19 +17,23 @@
ConversionHelperHidl.cpp \
DeviceHalHidl.cpp \
DevicesFactoryHalHidl.cpp \
+ EffectBufferHalHidl.cpp \
EffectHalHidl.cpp \
EffectsFactoryHalHidl.cpp \
StreamHalHidl.cpp
LOCAL_SHARED_LIBRARIES += \
+ libbase \
+ libfmq \
libhwbinder \
libhidlbase \
+ libhidlmemory \
libhidltransport \
- libbase \
android.hardware.audio@2.0 \
android.hardware.audio.common@2.0 \
android.hardware.audio.common@2.0-util \
- android.hardware.audio.effect@2.0 \
+ android.hardware.audio.effect@2.0 \
+ android.hidl.memory@1.0 \
libmedia_helper
else # if !ENABLE_TREBLE
@@ -39,6 +41,7 @@
LOCAL_SRC_FILES := \
DeviceHalLocal.cpp \
DevicesFactoryHalLocal.cpp \
+ EffectBufferHalLocal.cpp \
EffectHalLocal.cpp \
EffectsFactoryHalLocal.cpp \
StreamHalLocal.cpp
diff --git a/media/libaudiohal/ConversionHelperHidl.cpp b/media/libaudiohal/ConversionHelperHidl.cpp
index 1fabfbe..9f9eb75 100644
--- a/media/libaudiohal/ConversionHelperHidl.cpp
+++ b/media/libaudiohal/ConversionHelperHidl.cpp
@@ -82,26 +82,8 @@
}
}
-// static
-void ConversionHelperHidl::crashIfHalIsDead(const Status& status) {
- LOG_ALWAYS_FATAL_IF(
- status.transactionError() == DEAD_OBJECT, "HAL server crashed, need to restart");
-}
-
-status_t ConversionHelperHidl::processReturn(const char* funcName, const Status& status) {
- const status_t st = status.transactionError();
- ALOGE_IF(st, "%s %p %s: %s (from rpc)", mClassName, this, funcName, strerror(-st));
- crashIfHalIsDead(status);
- return st;
-}
-
-status_t ConversionHelperHidl::processReturn(
- const char* funcName, const Status& status, hardware::audio::V2_0::Result retval) {
- const status_t st = status.isOk() ? analyzeResult(retval) : status.transactionError();
- ALOGE_IF(!status.isOk() && st, "%s %p %s: %s (from rpc)",
- mClassName, this, funcName, strerror(-st));
- crashIfHalIsDead(status);
- return st;
+void ConversionHelperHidl::emitError(const char* funcName, const char* description) {
+ ALOGE("%s %p %s: %s (from rpc)", mClassName, this, funcName, description);
}
} // namespace android
diff --git a/media/libaudiohal/ConversionHelperHidl.h b/media/libaudiohal/ConversionHelperHidl.h
index 428daf2..00d5b2c 100644
--- a/media/libaudiohal/ConversionHelperHidl.h
+++ b/media/libaudiohal/ConversionHelperHidl.h
@@ -30,9 +30,6 @@
namespace android {
class ConversionHelperHidl {
- public:
- static void crashIfHalIsDead(const Status& status);
-
protected:
static status_t keysFromHal(const String8& keys, hidl_vec<hidl_string> *hidlKeys);
static status_t parametersFromHal(const String8& kvPairs, hidl_vec<ParameterValue> *hidlParams);
@@ -40,18 +37,22 @@
ConversionHelperHidl(const char* className);
- status_t processReturn(const char* funcName, const Return<void>& ret) {
- return processReturn(funcName, ret.getStatus());
- }
-
template<typename R, typename T>
status_t processReturn(const char* funcName, const Return<R>& ret, T *retval) {
- if (ret.getStatus().isOk()) {
+ if (ret.isOk()) {
// This way it also works for enum class to unscoped enum conversion.
*retval = static_cast<T>(static_cast<R>(ret));
return OK;
}
- return processReturn(funcName, ret.getStatus());
+ return processReturn(funcName, ret);
+ }
+
+ template<typename T>
+ status_t processReturn(const char* funcName, const Return<T>& ret) {
+ if (!ret.isOk()) {
+ emitError(funcName, ret.description().c_str());
+ }
+ return ret.isOk() ? OK : UNKNOWN_ERROR;
}
status_t processReturn(const char* funcName, const Return<hardware::audio::V2_0::Result>& ret) {
@@ -61,16 +62,19 @@
template<typename T>
status_t processReturn(
const char* funcName, const Return<T>& ret, hardware::audio::V2_0::Result retval) {
- return processReturn(funcName, ret.getStatus(), retval);
+ const status_t st = ret.isOk() ? analyzeResult(retval) : UNKNOWN_ERROR;
+ if (!ret.isOk()) {
+ emitError(funcName, ret.description().c_str());
+ }
+ return st;
}
private:
const char* mClassName;
static status_t analyzeResult(const hardware::audio::V2_0::Result& result);
- status_t processReturn(const char* funcName, const Status& status);
- status_t processReturn(
- const char* funcName, const Status& status, hardware::audio::V2_0::Result retval);
+
+ void emitError(const char* funcName, const char* description);
};
} // namespace android
diff --git a/media/libaudiohal/DevicesFactoryHalHidl.cpp b/media/libaudiohal/DevicesFactoryHalHidl.cpp
index efcc089..6444079 100644
--- a/media/libaudiohal/DevicesFactoryHalHidl.cpp
+++ b/media/libaudiohal/DevicesFactoryHalHidl.cpp
@@ -78,13 +78,12 @@
*device = new DeviceHalHidl(result);
}
});
- if (ret.getStatus().isOk()) {
+ if (ret.isOk()) {
if (retval == Result::OK) return OK;
else if (retval == Result::INVALID_ARGUMENTS) return BAD_VALUE;
else return NO_INIT;
}
- ConversionHelperHidl::crashIfHalIsDead(ret.getStatus());
- return ret.getStatus().transactionError();
+ return UNKNOWN_ERROR;
}
} // namespace android
diff --git a/media/libaudiohal/EffectBufferHalHidl.cpp b/media/libaudiohal/EffectBufferHalHidl.cpp
new file mode 100644
index 0000000..446d2ef
--- /dev/null
+++ b/media/libaudiohal/EffectBufferHalHidl.cpp
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+#include <atomic>
+
+#define LOG_TAG "EffectBufferHalHidl"
+//#define LOG_NDEBUG 0
+
+#include <android/hidl/memory/1.0/IAllocator.h>
+#include <hidlmemory/mapping.h>
+#include <utils/Log.h>
+
+#include "ConversionHelperHidl.h"
+#include "EffectBufferHalHidl.h"
+
+using ::android::hardware::Return;
+using ::android::hardware::Status;
+using ::android::hidl::memory::V1_0::IAllocator;
+
+namespace android {
+
+// static
+uint64_t EffectBufferHalHidl::makeUniqueId() {
+ static std::atomic<uint64_t> counter{1};
+ return counter++;
+}
+
+// static
+status_t EffectBufferHalInterface::allocate(
+ size_t size, sp<EffectBufferHalInterface>* buffer) {
+ return mirror(nullptr, size, buffer);
+}
+
+// static
+status_t EffectBufferHalInterface::mirror(
+ void* external, size_t size, sp<EffectBufferHalInterface>* buffer) {
+ sp<EffectBufferHalInterface> tempBuffer = new EffectBufferHalHidl(size);
+ status_t result = reinterpret_cast<EffectBufferHalHidl*>(tempBuffer.get())->init();
+ if (result == OK) {
+ tempBuffer->setExternalData(external);
+ *buffer = tempBuffer;
+ }
+ return result;
+}
+
+EffectBufferHalHidl::EffectBufferHalHidl(size_t size)
+ : mBufferSize(size), mExternalData(nullptr), mAudioBuffer{0, {nullptr}} {
+ mHidlBuffer.id = makeUniqueId();
+ mHidlBuffer.frameCount = 0;
+}
+
+EffectBufferHalHidl::~EffectBufferHalHidl() {
+}
+
+status_t EffectBufferHalHidl::init() {
+ sp<IAllocator> ashmem = IAllocator::getService("ashmem");
+ if (ashmem == 0) {
+ ALOGE("Failed to retrieve ashmem allocator service");
+ return NO_INIT;
+ }
+ status_t retval = NO_MEMORY;
+ Return<void> result = ashmem->allocate(
+ mBufferSize,
+ [&](bool success, const hidl_memory& memory) {
+ if (success) {
+ mHidlBuffer.data = memory;
+ retval = OK;
+ }
+ });
+ if (retval == OK) {
+ mMemory = hardware::mapMemory(mHidlBuffer.data);
+ if (mMemory != 0) {
+ mMemory->update();
+ mAudioBuffer.raw = static_cast<void*>(mMemory->getPointer());
+ memset(mAudioBuffer.raw, 0, mMemory->getSize());
+ mMemory->commit();
+ } else {
+ ALOGE("Failed to map allocated ashmem");
+ retval = NO_MEMORY;
+ }
+ }
+ return retval;
+}
+
+audio_buffer_t* EffectBufferHalHidl::audioBuffer() {
+ return &mAudioBuffer;
+}
+
+void* EffectBufferHalHidl::externalData() const {
+ return mExternalData;
+}
+
+void EffectBufferHalHidl::setFrameCount(size_t frameCount) {
+ mHidlBuffer.frameCount = frameCount;
+ mAudioBuffer.frameCount = frameCount;
+}
+
+void EffectBufferHalHidl::setExternalData(void* external) {
+ mExternalData = external;
+}
+
+void EffectBufferHalHidl::update() {
+ if (mExternalData == nullptr) return;
+ mMemory->update();
+ memcpy(mAudioBuffer.raw, mExternalData, mBufferSize);
+ mMemory->commit();
+}
+
+void EffectBufferHalHidl::commit() {
+ if (mExternalData == nullptr) return;
+ memcpy(mExternalData, mAudioBuffer.raw, mBufferSize);
+}
+
+} // namespace android
diff --git a/media/libaudiohal/EffectBufferHalHidl.h b/media/libaudiohal/EffectBufferHalHidl.h
new file mode 100644
index 0000000..4c4ec87
--- /dev/null
+++ b/media/libaudiohal/EffectBufferHalHidl.h
@@ -0,0 +1,67 @@
+/*
+ * 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_HARDWARE_EFFECT_BUFFER_HAL_HIDL_H
+#define ANDROID_HARDWARE_EFFECT_BUFFER_HAL_HIDL_H
+
+#include <android/hardware/audio/effect/2.0/types.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidl/HidlSupport.h>
+#include <media/audiohal/EffectBufferHalInterface.h>
+#include <system/audio_effect.h>
+
+using android::hardware::audio::effect::V2_0::AudioBuffer;
+using android::hardware::hidl_memory;
+using android::hidl::memory::V1_0::IMemory;
+
+namespace android {
+
+class EffectBufferHalHidl : public EffectBufferHalInterface
+{
+ public:
+ virtual audio_buffer_t* audioBuffer();
+ virtual void* externalData() const;
+
+ virtual void setExternalData(void* external);
+ virtual void setFrameCount(size_t frameCount);
+
+ virtual void update();
+ virtual void commit();
+
+ const AudioBuffer& hidlBuffer() const { return mHidlBuffer; }
+
+ private:
+ friend class EffectBufferHalInterface;
+
+ static uint64_t makeUniqueId();
+
+ const size_t mBufferSize;
+ void* mExternalData;
+ AudioBuffer mHidlBuffer;
+ sp<IMemory> mMemory;
+ audio_buffer_t mAudioBuffer;
+
+ // Can not be constructed directly by clients.
+ explicit EffectBufferHalHidl(size_t size);
+
+ virtual ~EffectBufferHalHidl();
+
+ status_t init();
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_EFFECT_BUFFER_HAL_HIDL_H
diff --git a/media/libaudiohal/EffectBufferHalLocal.cpp b/media/libaudiohal/EffectBufferHalLocal.cpp
new file mode 100644
index 0000000..20b1339
--- /dev/null
+++ b/media/libaudiohal/EffectBufferHalLocal.cpp
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "EffectBufferHalLocal"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+
+#include "EffectBufferHalLocal.h"
+
+namespace android {
+
+// static
+status_t EffectBufferHalInterface::allocate(
+ size_t size, sp<EffectBufferHalInterface>* buffer) {
+ *buffer = new EffectBufferHalLocal(size);
+ return OK;
+}
+
+// static
+status_t EffectBufferHalInterface::mirror(
+ void* external, size_t size, sp<EffectBufferHalInterface>* buffer) {
+ *buffer = new EffectBufferHalLocal(external, size);
+ return OK;
+}
+
+EffectBufferHalLocal::EffectBufferHalLocal(size_t size)
+ : mOwnBuffer(new uint8_t[size]),
+ mBufferSize(size),
+ mAudioBuffer{0, {mOwnBuffer.get()}} {
+}
+
+EffectBufferHalLocal::EffectBufferHalLocal(void* external, size_t size)
+ : mOwnBuffer(nullptr),
+ mBufferSize(size),
+ mAudioBuffer{0, {external}} {
+}
+
+EffectBufferHalLocal::~EffectBufferHalLocal() {
+}
+
+audio_buffer_t* EffectBufferHalLocal::audioBuffer() {
+ return &mAudioBuffer;
+}
+
+void* EffectBufferHalLocal::externalData() const {
+ return mAudioBuffer.raw;
+}
+
+void EffectBufferHalLocal::setFrameCount(size_t frameCount) {
+ mAudioBuffer.frameCount = frameCount;
+}
+
+void EffectBufferHalLocal::setExternalData(void* external) {
+ ALOGE_IF(mOwnBuffer != nullptr, "Attempt to set external data for allocated buffer");
+ mAudioBuffer.raw = external;
+}
+
+void EffectBufferHalLocal::update() {
+}
+
+void EffectBufferHalLocal::commit() {
+}
+
+} // namespace android
diff --git a/media/libaudiohal/EffectBufferHalLocal.h b/media/libaudiohal/EffectBufferHalLocal.h
new file mode 100644
index 0000000..df7bd43
--- /dev/null
+++ b/media/libaudiohal/EffectBufferHalLocal.h
@@ -0,0 +1,57 @@
+/*
+ * 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_HARDWARE_EFFECT_BUFFER_HAL_LOCAL_H
+#define ANDROID_HARDWARE_EFFECT_BUFFER_HAL_LOCAL_H
+
+#include <memory>
+
+#include <media/audiohal/EffectBufferHalInterface.h>
+#include <system/audio_effect.h>
+
+namespace android {
+
+class EffectBufferHalLocal : public EffectBufferHalInterface
+{
+ public:
+ virtual audio_buffer_t* audioBuffer();
+ virtual void* externalData() const;
+
+ virtual void setExternalData(void* external);
+ virtual void setFrameCount(size_t frameCount);
+
+ virtual void update();
+ virtual void commit();
+
+ private:
+ friend class EffectBufferHalInterface;
+
+ std::unique_ptr<uint8_t[]> mOwnBuffer;
+ const size_t mBufferSize;
+ audio_buffer_t mAudioBuffer;
+
+ // Can not be constructed directly by clients.
+ explicit EffectBufferHalLocal(size_t size);
+ EffectBufferHalLocal(void* external, size_t size);
+
+ virtual ~EffectBufferHalLocal();
+
+ status_t init();
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_EFFECT_BUFFER_HAL_LOCAL_H
diff --git a/media/libaudiohal/EffectHalHidl.cpp b/media/libaudiohal/EffectHalHidl.cpp
index 1cd1997..f1f3f2a 100644
--- a/media/libaudiohal/EffectHalHidl.cpp
+++ b/media/libaudiohal/EffectHalHidl.cpp
@@ -21,21 +21,26 @@
#include <utils/Log.h>
#include "ConversionHelperHidl.h"
+#include "EffectBufferHalHidl.h"
#include "EffectHalHidl.h"
#include "HidlUtils.h"
+using ::android::hardware::audio::effect::V2_0::AudioBuffer;
+using ::android::hardware::audio::effect::V2_0::MessageQueueFlagBits;
using ::android::hardware::audio::effect::V2_0::Result;
using ::android::hardware::hidl_vec;
+using ::android::hardware::MQDescriptorSync;
using ::android::hardware::Return;
using ::android::hardware::Status;
namespace android {
EffectHalHidl::EffectHalHidl(const sp<IEffect>& effect, uint64_t effectId)
- : mEffect(effect), mEffectId(effectId) {
+ : mEffect(effect), mEffectId(effectId), mBuffersChanged(true) {
}
EffectHalHidl::~EffectHalHidl() {
+ close();
}
// static
@@ -64,16 +69,100 @@
}
}
-status_t EffectHalHidl::process(audio_buffer_t */*inBuffer*/, audio_buffer_t */*outBuffer*/) {
- // Idea -- intercept set buffer config command, capture audio format, use it
- // for determining frame size in bytes on input and output.
+status_t EffectHalHidl::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
+ if (mInBuffer == 0 || buffer->audioBuffer() != mInBuffer->audioBuffer()) {
+ mBuffersChanged = true;
+ }
+ mInBuffer = buffer;
return OK;
}
-status_t EffectHalHidl::processReverse(audio_buffer_t */*inBuffer*/, audio_buffer_t */*outBuffer*/) {
+status_t EffectHalHidl::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
+ if (mOutBuffer == 0 || buffer->audioBuffer() != mOutBuffer->audioBuffer()) {
+ mBuffersChanged = true;
+ }
+ mOutBuffer = buffer;
return OK;
}
+status_t EffectHalHidl::process() {
+ return processImpl(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS));
+}
+
+status_t EffectHalHidl::processReverse() {
+ return processImpl(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_REVERSE));
+}
+
+status_t EffectHalHidl::prepareForProcessing() {
+ std::unique_ptr<StatusMQ> tempStatusMQ;
+ Result retval;
+ Return<void> ret = mEffect->prepareForProcessing(
+ [&](Result r, const MQDescriptorSync<Result>& statusMQ) {
+ retval = r;
+ if (retval == Result::OK) {
+ tempStatusMQ.reset(new StatusMQ(statusMQ));
+ if (tempStatusMQ->isValid() && tempStatusMQ->getEventFlagWord()) {
+ EventFlag::createEventFlag(tempStatusMQ->getEventFlagWord(), &mEfGroup);
+ }
+ }
+ });
+ if (!ret.isOk() || retval != Result::OK) {
+ return ret.isOk() ? analyzeResult(retval) : FAILED_TRANSACTION;
+ }
+ if (!tempStatusMQ || !tempStatusMQ->isValid() || !mEfGroup) {
+ ALOGE_IF(!tempStatusMQ, "Failed to obtain status message queue for effects");
+ ALOGE_IF(tempStatusMQ && !tempStatusMQ->isValid(),
+ "Status message queue for effects is invalid");
+ ALOGE_IF(!mEfGroup, "Event flag creation for effects failed");
+ return NO_INIT;
+ }
+ mStatusMQ = std::move(tempStatusMQ);
+ return OK;
+}
+
+status_t EffectHalHidl::processImpl(uint32_t mqFlag) {
+ if (mEffect == 0 || mInBuffer == 0 || mOutBuffer == 0) return NO_INIT;
+ status_t status;
+ if (!mStatusMQ && (status = prepareForProcessing()) != OK) {
+ return status;
+ }
+ if (mBuffersChanged && (status = setProcessBuffers()) != OK) {
+ return status;
+ }
+ // The data is already in the buffers, just need to flush it and wake up the server side.
+ std::atomic_thread_fence(std::memory_order_release);
+ mEfGroup->wake(mqFlag);
+ uint32_t efState = 0;
+retry:
+ status_t ret = mEfGroup->wait(
+ static_cast<uint32_t>(MessageQueueFlagBits::DONE_PROCESSING), &efState, NS_PER_SEC);
+ if (efState & static_cast<uint32_t>(MessageQueueFlagBits::DONE_PROCESSING)) {
+ Result retval = Result::NOT_INITIALIZED;
+ mStatusMQ->read(&retval);
+ if (retval == Result::OK || retval == Result::INVALID_STATE) {
+ // Sync back the changed contents of the buffer.
+ std::atomic_thread_fence(std::memory_order_acquire);
+ }
+ return analyzeResult(retval);
+ }
+ if (ret == -EAGAIN) {
+ // This normally retries no more than once.
+ goto retry;
+ }
+ return ret;
+}
+
+status_t EffectHalHidl::setProcessBuffers() {
+ Return<Result> ret = mEffect->setProcessBuffers(
+ reinterpret_cast<EffectBufferHalHidl*>(mInBuffer.get())->hidlBuffer(),
+ reinterpret_cast<EffectBufferHalHidl*>(mOutBuffer.get())->hidlBuffer());
+ if (ret.isOk() && ret == Result::OK) {
+ mBuffersChanged = false;
+ return OK;
+ }
+ return ret.isOk() ? analyzeResult(ret) : UNKNOWN_ERROR;
+}
+
status_t EffectHalHidl::command(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData,
uint32_t *replySize, void *pReplyData) {
if (mEffect == 0) return NO_INIT;
@@ -103,8 +192,13 @@
effectDescriptorToHal(result, pDescriptor);
}
});
- ConversionHelperHidl::crashIfHalIsDead(ret.getStatus());
- return ret.getStatus().isOk() ? analyzeResult(retval) : ret.getStatus().transactionError();
+ return ret.isOk() ? analyzeResult(retval) : UNKNOWN_ERROR;
+}
+
+status_t EffectHalHidl::close() {
+ if (mEffect == 0) return NO_INIT;
+ Return<Result> ret = mEffect->close();
+ return ret.isOk() ? analyzeResult(ret) : UNKNOWN_ERROR;
}
} // namespace android
diff --git a/media/libaudiohal/EffectHalHidl.h b/media/libaudiohal/EffectHalHidl.h
index b79bee0..1ed1153 100644
--- a/media/libaudiohal/EffectHalHidl.h
+++ b/media/libaudiohal/EffectHalHidl.h
@@ -19,24 +19,32 @@
#include <android/hardware/audio/effect/2.0/IEffect.h>
#include <media/audiohal/EffectHalInterface.h>
+#include <fmq/EventFlag.h>
+#include <fmq/MessageQueue.h>
#include <system/audio_effect.h>
using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
using ::android::hardware::audio::effect::V2_0::IEffect;
+using ::android::hardware::EventFlag;
+using ::android::hardware::MessageQueue;
namespace android {
class EffectHalHidl : public EffectHalInterface
{
public:
- // Effect process function. Takes input samples as specified
- // in input buffer descriptor and output processed samples as specified
- // in output buffer descriptor.
- virtual status_t process(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer);
+ // Set the input buffer.
+ virtual status_t setInBuffer(const sp<EffectBufferHalInterface>& buffer);
+
+ // Set the output buffer.
+ virtual status_t setOutBuffer(const sp<EffectBufferHalInterface>& buffer);
+
+ // Effect process function.
+ virtual status_t process();
// Process reverse stream function. This function is used to pass
// a reference stream to the effect engine.
- virtual status_t processReverse(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer);
+ virtual status_t processReverse();
// Send a command and receive a response to/from effect engine.
virtual status_t command(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData,
@@ -45,6 +53,9 @@
// Returns the effect descriptor.
virtual status_t getDescriptor(effect_descriptor_t *pDescriptor);
+ // Free resources on the remote side.
+ virtual status_t close();
+
uint64_t effectId() const { return mEffectId; }
static void effectDescriptorToHal(
@@ -52,8 +63,16 @@
private:
friend class EffectsFactoryHalHidl;
+ typedef MessageQueue<
+ hardware::audio::effect::V2_0::Result, hardware::kSynchronizedReadWrite> StatusMQ;
+
sp<IEffect> mEffect;
const uint64_t mEffectId;
+ sp<EffectBufferHalInterface> mInBuffer;
+ sp<EffectBufferHalInterface> mOutBuffer;
+ bool mBuffersChanged;
+ std::unique_ptr<StatusMQ> mStatusMQ;
+ EventFlag* mEfGroup;
static status_t analyzeResult(const hardware::audio::effect::V2_0::Result& result);
@@ -62,6 +81,10 @@
// The destructor automatically releases the effect.
virtual ~EffectHalHidl();
+
+ status_t prepareForProcessing();
+ status_t processImpl(uint32_t mqFlag);
+ status_t setProcessBuffers();
};
} // namespace android
diff --git a/media/libaudiohal/EffectHalLocal.cpp b/media/libaudiohal/EffectHalLocal.cpp
index 56a365c..dd465c3 100644
--- a/media/libaudiohal/EffectHalLocal.cpp
+++ b/media/libaudiohal/EffectHalLocal.cpp
@@ -34,12 +34,37 @@
mHandle = 0;
}
-status_t EffectHalLocal::process(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) {
- return (*mHandle)->process(mHandle, inBuffer, outBuffer);
+status_t EffectHalLocal::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
+ mInBuffer = buffer;
+ return OK;
}
-status_t EffectHalLocal::processReverse(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) {
- return (*mHandle)->process_reverse(mHandle, inBuffer, outBuffer);
+status_t EffectHalLocal::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
+ mOutBuffer = buffer;
+ return OK;
+}
+
+status_t EffectHalLocal::process() {
+ if (mInBuffer == nullptr || mOutBuffer == nullptr) {
+ ALOGE_IF(mInBuffer == nullptr, "Input buffer not set");
+ ALOGE_IF(mOutBuffer == nullptr, "Output buffer not set");
+ return NO_INIT;
+ }
+ return (*mHandle)->process(mHandle, mInBuffer->audioBuffer(), mOutBuffer->audioBuffer());
+}
+
+status_t EffectHalLocal::processReverse() {
+ if ((*mHandle)->process_reverse != NULL) {
+ if (mInBuffer == nullptr || mOutBuffer == nullptr) {
+ ALOGE_IF(mInBuffer == nullptr, "Input buffer not set");
+ ALOGE_IF(mOutBuffer == nullptr, "Output buffer not set");
+ return NO_INIT;
+ }
+ return (*mHandle)->process_reverse(
+ mHandle, mInBuffer->audioBuffer(), mOutBuffer->audioBuffer());
+ } else {
+ return INVALID_OPERATION;
+ }
}
status_t EffectHalLocal::command(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData,
@@ -51,4 +76,8 @@
return (*mHandle)->get_descriptor(mHandle, pDescriptor);
}
+status_t EffectHalLocal::close() {
+ return OK;
+}
+
} // namespace android
diff --git a/media/libaudiohal/EffectHalLocal.h b/media/libaudiohal/EffectHalLocal.h
index 77f774f..b499462 100644
--- a/media/libaudiohal/EffectHalLocal.h
+++ b/media/libaudiohal/EffectHalLocal.h
@@ -25,14 +25,18 @@
class EffectHalLocal : public EffectHalInterface
{
public:
- // Effect process function. Takes input samples as specified
- // in input buffer descriptor and output processed samples as specified
- // in output buffer descriptor.
- virtual status_t process(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer);
+ // Set the input buffer.
+ virtual status_t setInBuffer(const sp<EffectBufferHalInterface>& buffer);
+
+ // Set the output buffer.
+ virtual status_t setOutBuffer(const sp<EffectBufferHalInterface>& buffer);
+
+ // Effect process function.
+ virtual status_t process();
// Process reverse stream function. This function is used to pass
// a reference stream to the effect engine.
- virtual status_t processReverse(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer);
+ virtual status_t processReverse();
// Send a command and receive a response to/from effect engine.
virtual status_t command(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData,
@@ -41,10 +45,15 @@
// Returns the effect descriptor.
virtual status_t getDescriptor(effect_descriptor_t *pDescriptor);
+ // Free resources on the remote side.
+ virtual status_t close();
+
effect_handle_t handle() const { return mHandle; }
private:
effect_handle_t mHandle;
+ sp<EffectBufferHalInterface> mInBuffer;
+ sp<EffectBufferHalInterface> mOutBuffer;
friend class EffectsFactoryHalLocal;
diff --git a/media/libaudiohal/EffectsFactoryHalHidl.cpp b/media/libaudiohal/EffectsFactoryHalHidl.cpp
index bacbe4e..1ab5dad 100644
--- a/media/libaudiohal/EffectsFactoryHalHidl.cpp
+++ b/media/libaudiohal/EffectsFactoryHalHidl.cpp
@@ -43,7 +43,7 @@
return EffectIsNullUuid(pEffectUuid);
}
-EffectsFactoryHalHidl::EffectsFactoryHalHidl() {
+EffectsFactoryHalHidl::EffectsFactoryHalHidl() : ConversionHelperHidl("EffectsFactory"){
mEffectsFactory = IEffectsFactory::getService("audio_effects_factory");
}
@@ -60,12 +60,11 @@
mLastDescriptors = result;
}
});
- if (ret.getStatus().isOk()) {
+ if (ret.isOk()) {
return retval == Result::OK ? OK : NO_INIT;
}
mLastDescriptors.resize(0);
- ConversionHelperHidl::crashIfHalIsDead(ret.getStatus());
- return ret.getStatus().transactionError();
+ return processReturn(__FUNCTION__, ret);
}
status_t EffectsFactoryHalHidl::queryNumberEffects(uint32_t *pNumEffects) {
@@ -104,13 +103,12 @@
EffectHalHidl::effectDescriptorToHal(result, pDescriptor);
}
});
- if (ret.getStatus().isOk()) {
+ if (ret.isOk()) {
if (retval == Result::OK) return OK;
else if (retval == Result::INVALID_ARGUMENTS) return NAME_NOT_FOUND;
else return NO_INIT;
}
- ConversionHelperHidl::crashIfHalIsDead(ret.getStatus());
- return ret.getStatus().transactionError();
+ return processReturn(__FUNCTION__, ret);
}
status_t EffectsFactoryHalHidl::createEffect(
@@ -128,13 +126,12 @@
*effect = new EffectHalHidl(result, effectId);
}
});
- if (ret.getStatus().isOk()) {
+ if (ret.isOk()) {
if (retval == Result::OK) return OK;
else if (retval == Result::INVALID_ARGUMENTS) return NAME_NOT_FOUND;
else return NO_INIT;
}
- ConversionHelperHidl::crashIfHalIsDead(ret.getStatus());
- return ret.getStatus().transactionError();
+ return processReturn(__FUNCTION__, ret);
}
status_t EffectsFactoryHalHidl::dumpEffects(int fd) {
@@ -143,8 +140,7 @@
hidlHandle->data[0] = fd;
Return<void> ret = mEffectsFactory->debugDump(hidlHandle);
native_handle_delete(hidlHandle);
- ConversionHelperHidl::crashIfHalIsDead(ret.getStatus());
- return ret.getStatus().transactionError();
+ return processReturn(__FUNCTION__, ret);
}
} // namespace android
diff --git a/media/libaudiohal/EffectsFactoryHalHidl.h b/media/libaudiohal/EffectsFactoryHalHidl.h
index f16db17..e89f042 100644
--- a/media/libaudiohal/EffectsFactoryHalHidl.h
+++ b/media/libaudiohal/EffectsFactoryHalHidl.h
@@ -27,7 +27,7 @@
using ::android::hardware::audio::effect::V2_0::IEffectsFactory;
using ::android::hardware::hidl_vec;
-class EffectsFactoryHalHidl : public EffectsFactoryHalInterface
+class EffectsFactoryHalHidl : public EffectsFactoryHalInterface, public ConversionHelperHidl
{
public:
// Returns the number of different effects in all loaded libraries.
diff --git a/media/libaudiohal/StreamHalHidl.cpp b/media/libaudiohal/StreamHalHidl.cpp
index 7f8d663..5943e22 100644
--- a/media/libaudiohal/StreamHalHidl.cpp
+++ b/media/libaudiohal/StreamHalHidl.cpp
@@ -342,7 +342,7 @@
}
}
});
- if (!ret.getStatus().isOk() || retval != Result::OK) {
+ if (!ret.isOk() || retval != Result::OK) {
return processReturn("prepareForWriting", ret, retval);
}
if (!tempDataMQ || !tempDataMQ->isValid() || !tempStatusMQ || !tempStatusMQ->isValid()
@@ -456,7 +456,7 @@
timestamp->tv_nsec = hidlTimeStamp.tvNSec;
}
});
- if (ret.getStatus().isOk() && retval == Result::NOT_SUPPORTED) {
+ if (ret.isOk() && retval == Result::NOT_SUPPORTED) {
mGetPresentationPositionNotSupported = true;
}
return processReturn("getPresentationPosition", ret, retval);
@@ -570,7 +570,7 @@
}
}
});
- if (!ret.getStatus().isOk() || retval != Result::OK) {
+ if (!ret.isOk() || retval != Result::OK) {
return processReturn("prepareForReading", ret, retval);
}
if (!tempDataMQ || !tempDataMQ->isValid() || !tempStatusMQ || !tempStatusMQ->isValid()
diff --git a/media/libaudioprocessing/Android.mk b/media/libaudioprocessing/Android.mk
new file mode 100644
index 0000000..d47d158
--- /dev/null
+++ b/media/libaudioprocessing/Android.mk
@@ -0,0 +1,35 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ AudioMixer.cpp.arm \
+ AudioResampler.cpp.arm \
+ AudioResamplerCubic.cpp.arm \
+ AudioResamplerSinc.cpp.arm \
+ AudioResamplerDyn.cpp.arm \
+ BufferProviders.cpp \
+
+LOCAL_C_INCLUDES := \
+ $(TOP) \
+ $(call include-path-for, audio-utils) \
+
+LOCAL_SHARED_LIBRARIES := \
+ libaudiohal \
+ libaudioutils \
+ libcutils \
+ liblog \
+ libnbaio \
+ libsonic \
+ libutils \
+
+LOCAL_MODULE := libaudioprocessing
+
+LOCAL_CFLAGS := -Werror -Wall
+
+# uncomment to disable NEON on architectures that actually do support NEON, for benchmarking
+#LOCAL_CFLAGS += -DUSE_NEON=false
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/services/audioflinger/AudioMixer.cpp b/media/libaudioprocessing/AudioMixer.cpp
similarity index 99%
rename from services/audioflinger/AudioMixer.cpp
rename to media/libaudioprocessing/AudioMixer.cpp
index 945f4b3..a7d9f0f 100644
--- a/services/audioflinger/AudioMixer.cpp
+++ b/media/libaudioprocessing/AudioMixer.cpp
@@ -18,7 +18,6 @@
#define LOG_TAG "AudioMixer"
//#define LOG_NDEBUG 0
-#include "Configuration.h"
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
@@ -36,9 +35,9 @@
#include <audio_utils/primitives.h>
#include <audio_utils/format.h>
+#include <media/AudioMixer.h>
#include "AudioMixerOps.h"
-#include "AudioMixer.h"
// The FCC_2 macro refers to the Fixed Channel Count of 2 for the legacy integer mixer.
#ifndef FCC_2
diff --git a/services/audioflinger/AudioMixerOps.h b/media/libaudioprocessing/AudioMixerOps.h
similarity index 100%
rename from services/audioflinger/AudioMixerOps.h
rename to media/libaudioprocessing/AudioMixerOps.h
diff --git a/services/audioflinger/AudioResampler.cpp b/media/libaudioprocessing/AudioResampler.cpp
similarity index 99%
rename from services/audioflinger/AudioResampler.cpp
rename to media/libaudioprocessing/AudioResampler.cpp
index 43624a0..c761b38 100644
--- a/services/audioflinger/AudioResampler.cpp
+++ b/media/libaudioprocessing/AudioResampler.cpp
@@ -22,11 +22,11 @@
#include <stdlib.h>
#include <sys/types.h>
-#include <android/log.h>
#include <cutils/properties.h>
+#include <log/log.h>
#include <audio_utils/primitives.h>
-#include "AudioResampler.h"
+#include <media/AudioResampler.h>
#include "AudioResamplerSinc.h"
#include "AudioResamplerCubic.h"
#include "AudioResamplerDyn.h"
diff --git a/services/audioflinger/AudioResamplerCubic.cpp b/media/libaudioprocessing/AudioResamplerCubic.cpp
similarity index 98%
rename from services/audioflinger/AudioResamplerCubic.cpp
rename to media/libaudioprocessing/AudioResamplerCubic.cpp
index d27dce7..9bcd8e1 100644
--- a/services/audioflinger/AudioResamplerCubic.cpp
+++ b/media/libaudioprocessing/AudioResamplerCubic.cpp
@@ -19,9 +19,9 @@
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
-#include <android/log.h>
-#include "AudioResampler.h"
+#include <log/log.h>
+
#include "AudioResamplerCubic.h"
namespace android {
diff --git a/services/audioflinger/AudioResamplerCubic.h b/media/libaudioprocessing/AudioResamplerCubic.h
similarity index 98%
rename from services/audioflinger/AudioResamplerCubic.h
rename to media/libaudioprocessing/AudioResamplerCubic.h
index f218fd9..defaf33 100644
--- a/services/audioflinger/AudioResamplerCubic.h
+++ b/media/libaudioprocessing/AudioResamplerCubic.h
@@ -21,7 +21,7 @@
#include <sys/types.h>
#include <android/log.h>
-#include "AudioResampler.h"
+#include <media/AudioResampler.h>
namespace android {
// ----------------------------------------------------------------------------
diff --git a/services/audioflinger/AudioResamplerDyn.cpp b/media/libaudioprocessing/AudioResamplerDyn.cpp
similarity index 100%
rename from services/audioflinger/AudioResamplerDyn.cpp
rename to media/libaudioprocessing/AudioResamplerDyn.cpp
diff --git a/services/audioflinger/AudioResamplerDyn.h b/media/libaudioprocessing/AudioResamplerDyn.h
similarity index 98%
rename from services/audioflinger/AudioResamplerDyn.h
rename to media/libaudioprocessing/AudioResamplerDyn.h
index 6af9017..1840fc7 100644
--- a/services/audioflinger/AudioResamplerDyn.h
+++ b/media/libaudioprocessing/AudioResamplerDyn.h
@@ -21,7 +21,7 @@
#include <sys/types.h>
#include <android/log.h>
-#include "AudioResampler.h"
+#include <media/AudioResampler.h>
namespace android {
diff --git a/services/audioflinger/AudioResamplerFirGen.h b/media/libaudioprocessing/AudioResamplerFirGen.h
similarity index 100%
rename from services/audioflinger/AudioResamplerFirGen.h
rename to media/libaudioprocessing/AudioResamplerFirGen.h
diff --git a/services/audioflinger/AudioResamplerFirOps.h b/media/libaudioprocessing/AudioResamplerFirOps.h
similarity index 100%
rename from services/audioflinger/AudioResamplerFirOps.h
rename to media/libaudioprocessing/AudioResamplerFirOps.h
diff --git a/services/audioflinger/AudioResamplerFirProcess.h b/media/libaudioprocessing/AudioResamplerFirProcess.h
similarity index 100%
rename from services/audioflinger/AudioResamplerFirProcess.h
rename to media/libaudioprocessing/AudioResamplerFirProcess.h
diff --git a/services/audioflinger/AudioResamplerFirProcessNeon.h b/media/libaudioprocessing/AudioResamplerFirProcessNeon.h
similarity index 100%
rename from services/audioflinger/AudioResamplerFirProcessNeon.h
rename to media/libaudioprocessing/AudioResamplerFirProcessNeon.h
diff --git a/services/audioflinger/AudioResamplerFirProcessSSE.h b/media/libaudioprocessing/AudioResamplerFirProcessSSE.h
similarity index 100%
rename from services/audioflinger/AudioResamplerFirProcessSSE.h
rename to media/libaudioprocessing/AudioResamplerFirProcessSSE.h
diff --git a/services/audioflinger/AudioResamplerSinc.cpp b/media/libaudioprocessing/AudioResamplerSinc.cpp
similarity index 100%
rename from services/audioflinger/AudioResamplerSinc.cpp
rename to media/libaudioprocessing/AudioResamplerSinc.cpp
diff --git a/services/audioflinger/AudioResamplerSinc.h b/media/libaudioprocessing/AudioResamplerSinc.h
similarity index 98%
rename from services/audioflinger/AudioResamplerSinc.h
rename to media/libaudioprocessing/AudioResamplerSinc.h
index df8b45a..f6dcf91 100644
--- a/services/audioflinger/AudioResamplerSinc.h
+++ b/media/libaudioprocessing/AudioResamplerSinc.h
@@ -21,7 +21,7 @@
#include <sys/types.h>
#include <android/log.h>
-#include "AudioResampler.h"
+#include <media/AudioResampler.h>
namespace android {
diff --git a/services/audioflinger/AudioResamplerSincDown.h b/media/libaudioprocessing/AudioResamplerSincDown.h
similarity index 100%
rename from services/audioflinger/AudioResamplerSincDown.h
rename to media/libaudioprocessing/AudioResamplerSincDown.h
diff --git a/services/audioflinger/AudioResamplerSincUp.h b/media/libaudioprocessing/AudioResamplerSincUp.h
similarity index 100%
rename from services/audioflinger/AudioResamplerSincUp.h
rename to media/libaudioprocessing/AudioResamplerSincUp.h
diff --git a/services/audioflinger/BufferProviders.cpp b/media/libaudioprocessing/BufferProviders.cpp
similarity index 92%
rename from services/audioflinger/BufferProviders.cpp
rename to media/libaudioprocessing/BufferProviders.cpp
index ba5f7b6..8341a1e 100644
--- a/services/audioflinger/BufferProviders.cpp
+++ b/media/libaudioprocessing/BufferProviders.cpp
@@ -19,16 +19,15 @@
#include <audio_utils/primitives.h>
#include <audio_utils/format.h>
+#include <external/sonic/sonic.h>
+#include <media/audiohal/EffectBufferHalInterface.h>
#include <media/audiohal/EffectHalInterface.h>
#include <media/audiohal/EffectsFactoryHalInterface.h>
#include <media/AudioResamplerPublic.h>
+#include <media/BufferProviders.h>
#include <system/audio_effects/effect_downmix.h>
-
#include <utils/Log.h>
-#include "Configuration.h"
-#include "BufferProviders.h"
-
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
#endif
@@ -179,17 +178,44 @@
EFFECT_CONFIG_FORMAT | EFFECT_CONFIG_ACC_MODE;
mDownmixConfig.outputCfg.mask = mDownmixConfig.inputCfg.mask;
+ status_t status;
+ status = EffectBufferHalInterface::mirror(
+ nullptr,
+ audio_bytes_per_sample(format) * audio_channel_count_from_out_mask(inputChannelMask),
+ &mInBuffer);
+ if (status != 0) {
+ ALOGE("DownmixerBufferProvider() error %d while creating input buffer", status);
+ mDownmixInterface.clear();
+ mEffectsFactory.clear();
+ return;
+ }
+ status = EffectBufferHalInterface::mirror(
+ nullptr,
+ audio_bytes_per_sample(format) * audio_channel_count_from_out_mask(outputChannelMask),
+ &mOutBuffer);
+ if (status != 0) {
+ ALOGE("DownmixerBufferProvider() error %d while creating output buffer", status);
+ mInBuffer.clear();
+ mDownmixInterface.clear();
+ mEffectsFactory.clear();
+ return;
+ }
+ mDownmixInterface->setInBuffer(mInBuffer);
+ mDownmixInterface->setOutBuffer(mOutBuffer);
+
int cmdStatus;
uint32_t replySize = sizeof(int);
// Configure downmixer
- status_t status = mDownmixInterface->command(
+ status = mDownmixInterface->command(
EFFECT_CMD_SET_CONFIG /*cmdCode*/, sizeof(effect_config_t) /*cmdSize*/,
&mDownmixConfig /*pCmdData*/,
&replySize, &cmdStatus /*pReplyData*/);
if (status != 0 || cmdStatus != 0) {
ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while configuring downmixer",
status, cmdStatus);
+ mOutBuffer.clear();
+ mInBuffer.clear();
mDownmixInterface.clear();
mEffectsFactory.clear();
return;
@@ -203,6 +229,8 @@
if (status != 0 || cmdStatus != 0) {
ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while enabling downmixer",
status, cmdStatus);
+ mOutBuffer.clear();
+ mInBuffer.clear();
mDownmixInterface.clear();
mEffectsFactory.clear();
return;
@@ -228,6 +256,8 @@
if (status != 0 || cmdStatus != 0) {
ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while setting downmix type",
status, cmdStatus);
+ mOutBuffer.clear();
+ mInBuffer.clear();
mDownmixInterface.clear();
mEffectsFactory.clear();
return;
@@ -238,18 +268,26 @@
DownmixerBufferProvider::~DownmixerBufferProvider()
{
ALOGV("~DownmixerBufferProvider (%p)", this);
+ if (mDownmixInterface != 0) {
+ mDownmixInterface->close();
+ }
}
void DownmixerBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
{
- mDownmixConfig.inputCfg.buffer.frameCount = frames;
- mDownmixConfig.inputCfg.buffer.raw = const_cast<void *>(src);
- mDownmixConfig.outputCfg.buffer.frameCount = frames;
- mDownmixConfig.outputCfg.buffer.raw = dst;
+ mInBuffer->setExternalData(const_cast<void*>(src));
+ mInBuffer->setFrameCount(frames);
+ mInBuffer->update();
+ mOutBuffer->setExternalData(dst);
+ mOutBuffer->setFrameCount(frames);
+ mOutBuffer->update();
// may be in-place if src == dst.
- status_t res = mDownmixInterface->process(
- &mDownmixConfig.inputCfg.buffer, &mDownmixConfig.outputCfg.buffer);
- ALOGE_IF(res != OK, "DownmixBufferProvider error %d", res);
+ status_t res = mDownmixInterface->process();
+ if (res == OK) {
+ mOutBuffer->commit();
+ } else {
+ ALOGE("DownmixBufferProvider error %d", res);
+ }
}
/* call once in a pthread_once handler. */
diff --git a/services/audioflinger/audio-resampler/Android.mk b/media/libaudioprocessing/audio-resampler/Android.mk
similarity index 100%
rename from services/audioflinger/audio-resampler/Android.mk
rename to media/libaudioprocessing/audio-resampler/Android.mk
diff --git a/services/audioflinger/audio-resampler/AudioResamplerCoefficients.cpp b/media/libaudioprocessing/audio-resampler/AudioResamplerCoefficients.cpp
similarity index 100%
rename from services/audioflinger/audio-resampler/AudioResamplerCoefficients.cpp
rename to media/libaudioprocessing/audio-resampler/AudioResamplerCoefficients.cpp
diff --git a/services/audioflinger/audio-resampler/filter_coefficients.h b/media/libaudioprocessing/audio-resampler/filter_coefficients.h
similarity index 100%
rename from services/audioflinger/audio-resampler/filter_coefficients.h
rename to media/libaudioprocessing/audio-resampler/filter_coefficients.h
diff --git a/media/libaudioprocessing/tests/Android.mk b/media/libaudioprocessing/tests/Android.mk
new file mode 100644
index 0000000..23e1c3a
--- /dev/null
+++ b/media/libaudioprocessing/tests/Android.mk
@@ -0,0 +1,87 @@
+# Build the unit tests for libaudioprocessing
+
+LOCAL_PATH := $(call my-dir)
+
+#
+# resampler unit test
+#
+include $(CLEAR_VARS)
+
+LOCAL_SHARED_LIBRARIES := \
+ libaudioutils \
+ libaudioprocessing \
+ libcutils \
+ liblog \
+ libutils \
+
+LOCAL_C_INCLUDES := \
+ $(call include-path-for, audio-utils) \
+
+LOCAL_SRC_FILES := \
+ resampler_tests.cpp
+
+LOCAL_MODULE := resampler_tests
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_CFLAGS := -Werror -Wall
+
+include $(BUILD_NATIVE_TEST)
+
+#
+# audio mixer test tool
+#
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ test-mixer.cpp \
+
+LOCAL_C_INCLUDES := \
+ $(call include-path-for, audio-utils) \
+
+LOCAL_STATIC_LIBRARIES := \
+ libsndfile \
+
+LOCAL_SHARED_LIBRARIES := \
+ libaudioprocessing \
+ libaudioutils \
+ libcutils \
+ liblog \
+ libutils \
+
+LOCAL_MODULE := test-mixer
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CFLAGS := -Werror -Wall
+
+include $(BUILD_EXECUTABLE)
+
+#
+# build audio resampler test tool
+#
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ test-resampler.cpp \
+
+LOCAL_C_INCLUDES := \
+ $(call include-path-for, audio-utils) \
+
+LOCAL_STATIC_LIBRARIES := \
+ libsndfile \
+
+LOCAL_SHARED_LIBRARIES := \
+ libaudioprocessing \
+ libaudioutils \
+ libcutils \
+ liblog \
+ libutils \
+
+LOCAL_MODULE := test-resampler
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CFLAGS := -Werror -Wall
+
+include $(BUILD_EXECUTABLE)
diff --git a/services/audioflinger/tests/README b/media/libaudioprocessing/tests/README
similarity index 61%
rename from services/audioflinger/tests/README
rename to media/libaudioprocessing/tests/README
index 508e960..ed7e2ed 100644
--- a/services/audioflinger/tests/README
+++ b/media/libaudioprocessing/tests/README
@@ -1,9 +1,9 @@
For libsonic dependency:
-pushd external/sonic
+pushd $ANDROID_BUILD_TOP/external/sonic
mm
popd
-To build resampler library:
+To build audio processing library:
pushd ..
Optionally uncomment USE_NEON=false in Android.mk
mm
diff --git a/services/audioflinger/tests/build_and_run_all_unit_tests.sh b/media/libaudioprocessing/tests/build_and_run_all_unit_tests.sh
similarity index 79%
rename from services/audioflinger/tests/build_and_run_all_unit_tests.sh
rename to media/libaudioprocessing/tests/build_and_run_all_unit_tests.sh
index 9a71096..704d095 100755
--- a/services/audioflinger/tests/build_and_run_all_unit_tests.sh
+++ b/media/libaudioprocessing/tests/build_and_run_all_unit_tests.sh
@@ -8,7 +8,7 @@
# ensure we have mm
. $ANDROID_BUILD_TOP/build/envsetup.sh
-pushd $ANDROID_BUILD_TOP/frameworks/av/services/audioflinger/
+pushd $ANDROID_BUILD_TOP/frameworks/av/media/libaudioprocessing
pwd
mm
@@ -19,6 +19,6 @@
adb push $OUT/data/nativetest/resampler_tests/resampler_tests /data/nativetest/resampler_tests/resampler_tests
adb push $OUT/data/nativetest64/resampler_tests/resampler_tests /data/nativetest64/resampler_tests/resampler_tests
-sh $ANDROID_BUILD_TOP/frameworks/av/services/audioflinger/tests/run_all_unit_tests.sh
+sh $ANDROID_BUILD_TOP/frameworks/av/media/libaudioprocessing/tests/run_all_unit_tests.sh
popd
diff --git a/services/audioflinger/tests/mixer_to_wav_tests.sh b/media/libaudioprocessing/tests/mixer_to_wav_tests.sh
similarity index 95%
rename from services/audioflinger/tests/mixer_to_wav_tests.sh
rename to media/libaudioprocessing/tests/mixer_to_wav_tests.sh
index d0482a1..72b02fc 100755
--- a/services/audioflinger/tests/mixer_to_wav_tests.sh
+++ b/media/libaudioprocessing/tests/mixer_to_wav_tests.sh
@@ -37,7 +37,7 @@
# ensure we have mm
. $ANDROID_BUILD_TOP/build/envsetup.sh
-pushd $ANDROID_BUILD_TOP/frameworks/av/services/audioflinger/
+pushd $ANDROID_BUILD_TOP/frameworks/av/media/libaudioprocessing
# build
pwd
@@ -46,7 +46,8 @@
# send to device
echo "waiting for device"
adb root && adb wait-for-device remount
-adb push $OUT/system/lib/libaudioresampler.so /system/lib
+adb push $OUT/system/lib/libaudioprocessing.so /system/lib
+adb push $OUT/system/lib64/libaudioprocessing.so /system/lib64
adb push $OUT/system/bin/test-mixer /system/bin
# createwav creates a series of WAV files testing various
diff --git a/services/audioflinger/tests/resampler_tests.cpp b/media/libaudioprocessing/tests/resampler_tests.cpp
similarity index 99%
rename from services/audioflinger/tests/resampler_tests.cpp
rename to media/libaudioprocessing/tests/resampler_tests.cpp
index 77a265f..8d5e016 100644
--- a/services/audioflinger/tests/resampler_tests.cpp
+++ b/media/libaudioprocessing/tests/resampler_tests.cpp
@@ -36,7 +36,7 @@
#include <gtest/gtest.h>
#include <media/AudioBufferProvider.h>
-#include "AudioResampler.h"
+#include <media/AudioResampler.h>
#include "test_utils.h"
template <typename T>
diff --git a/services/audioflinger/tests/run_all_unit_tests.sh b/media/libaudioprocessing/tests/run_all_unit_tests.sh
similarity index 100%
rename from services/audioflinger/tests/run_all_unit_tests.sh
rename to media/libaudioprocessing/tests/run_all_unit_tests.sh
diff --git a/services/audioflinger/tests/test-mixer.cpp b/media/libaudioprocessing/tests/test-mixer.cpp
similarity index 99%
rename from services/audioflinger/tests/test-mixer.cpp
rename to media/libaudioprocessing/tests/test-mixer.cpp
index 65e22da..75dbf91 100644
--- a/services/audioflinger/tests/test-mixer.cpp
+++ b/media/libaudioprocessing/tests/test-mixer.cpp
@@ -21,7 +21,7 @@
#include <audio_utils/primitives.h>
#include <audio_utils/sndfile.h>
#include <media/AudioBufferProvider.h>
-#include "AudioMixer.h"
+#include <media/AudioMixer.h>
#include "test_utils.h"
/* Testing is typically through creation of an output WAV file from several
diff --git a/services/audioflinger/test-resample.cpp b/media/libaudioprocessing/tests/test-resampler.cpp
similarity index 98%
rename from services/audioflinger/test-resample.cpp
rename to media/libaudioprocessing/tests/test-resampler.cpp
index bae3c5b..fbc9326 100644
--- a/services/audioflinger/test-resample.cpp
+++ b/media/libaudioprocessing/tests/test-resampler.cpp
@@ -29,7 +29,7 @@
#include <audio_utils/sndfile.h>
#include <utils/Vector.h>
#include <media/AudioBufferProvider.h>
-#include "AudioResampler.h"
+#include <media/AudioResampler.h>
using namespace android;
diff --git a/services/audioflinger/tests/test_utils.h b/media/libaudioprocessing/tests/test_utils.h
similarity index 98%
rename from services/audioflinger/tests/test_utils.h
rename to media/libaudioprocessing/tests/test_utils.h
index 283c768..b61a929 100644
--- a/services/audioflinger/tests/test_utils.h
+++ b/media/libaudioprocessing/tests/test_utils.h
@@ -17,6 +17,12 @@
#ifndef ANDROID_AUDIO_TEST_UTILS_H
#define ANDROID_AUDIO_TEST_UTILS_H
+#ifndef LOG_TAG
+#define LOG_TAG "test_utils"
+#endif
+
+#include <log/log.h>
+
#include <audio_utils/sndfile.h>
#ifndef ARRAY_SIZE
diff --git a/media/libeffects/downmix/EffectDownmix.c b/media/libeffects/downmix/EffectDownmix.c
index 323930a..f27d5ca 100644
--- a/media/libeffects/downmix/EffectDownmix.c
+++ b/media/libeffects/downmix/EffectDownmix.c
@@ -22,7 +22,7 @@
#include <stdlib.h>
#include <string.h>
-#include <android/log.h>
+#include <log/log.h>
#include "EffectDownmix.h"
diff --git a/media/libeffects/factory/EffectsFactory.c b/media/libeffects/factory/EffectsFactory.c
index 74d489b..554c14d 100644
--- a/media/libeffects/factory/EffectsFactory.c
+++ b/media/libeffects/factory/EffectsFactory.c
@@ -24,10 +24,10 @@
#include <string.h>
#include <unistd.h>
-#include <android/log.h>
#include <cutils/config_utils.h>
#include <cutils/misc.h>
#include <cutils/properties.h>
+#include <log/log.h>
#include <system/audio_effects/audio_effects_conf.h>
diff --git a/media/libeffects/loudness/dsp/core/dynamic_range_compression-inl.h b/media/libeffects/loudness/dsp/core/dynamic_range_compression-inl.h
index 4f9f438..7ea0593 100644
--- a/media/libeffects/loudness/dsp/core/dynamic_range_compression-inl.h
+++ b/media/libeffects/loudness/dsp/core/dynamic_range_compression-inl.h
@@ -21,7 +21,7 @@
#endif
//#define LOG_NDEBUG 0
-#include <android/log.h>
+#include <log/log.h>
namespace le_fx {
diff --git a/media/libeffects/loudness/dsp/core/interpolator_base-inl.h b/media/libeffects/loudness/dsp/core/interpolator_base-inl.h
index bdb6818..fb87c79 100644
--- a/media/libeffects/loudness/dsp/core/interpolator_base-inl.h
+++ b/media/libeffects/loudness/dsp/core/interpolator_base-inl.h
@@ -21,7 +21,7 @@
#endif
//#define LOG_NDEBUG 0
-#include <android/log.h>
+#include <log/log.h>
#include "dsp/core/basic.h"
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index f8a6a4e..d1ade1d 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -16,6 +16,9 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "NuPlayer"
+
+#include <inttypes.h>
+
#include <utils/Log.h>
#include "NuPlayer.h"
@@ -1287,6 +1290,8 @@
} else {
ALOGW("resume called when renderer is gone or not set");
}
+
+ mLastStartedPlayingTimeNs = systemTime();
}
status_t NuPlayer::onInstantiateSecureDecoders() {
@@ -1342,26 +1347,26 @@
flags |= Renderer::FLAG_REAL_TIME;
}
- sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */);
- sp<MetaData> videoMeta = mSource->getFormatMeta(false /* audio */);
- if (audioMeta == NULL && videoMeta == NULL) {
+ bool hasAudio = (mSource->getFormat(true /* audio */) != NULL);
+ bool hasVideo = (mSource->getFormat(false /* audio */) != NULL);
+ if (!hasAudio && !hasVideo) {
ALOGE("no metadata for either audio or video source");
mSource->stop();
mSourceStarted = false;
notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_MALFORMED);
return;
}
- ALOGV_IF(audioMeta == NULL, "no metadata for audio source"); // video only stream
+ ALOGV_IF(!hasAudio, "no metadata for audio source"); // video only stream
+
+ sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */);
audio_stream_type_t streamType = AUDIO_STREAM_MUSIC;
if (mAudioSink != NULL) {
streamType = mAudioSink->getAudioStreamType();
}
- sp<AMessage> videoFormat = mSource->getFormat(false /* audio */);
-
mOffloadAudio =
- canOffloadStream(audioMeta, (videoFormat != NULL), mSource->isStreaming(), streamType)
+ canOffloadStream(audioMeta, hasVideo, mSource->isStreaming(), streamType)
&& (mPlaybackSettings.mSpeed == 1.f && mPlaybackSettings.mPitch == 1.f);
if (mOffloadAudio) {
flags |= Renderer::FLAG_OFFLOAD_AUDIO;
@@ -1396,6 +1401,8 @@
mAudioDecoder->setRenderer(mRenderer);
}
+ mLastStartedPlayingTimeNs = systemTime();
+
postScanSources();
}
@@ -1414,6 +1421,16 @@
} else {
ALOGW("pause called when renderer is gone or not set");
}
+
+ sp<NuPlayerDriver> driver = mDriver.promote();
+ if (driver != NULL) {
+ int64_t now = systemTime();
+ int64_t played = now - mLastStartedPlayingTimeNs;
+ ALOGD("played from %" PRId64 " to %" PRId64 " = %" PRId64 ,
+ mLastStartedPlayingTimeNs, now, played);
+
+ driver->notifyMorePlayingTimeUs((played+500)/1000);
+ }
}
bool NuPlayer::audioDecoderStillNeeded() {
@@ -1697,6 +1714,16 @@
notifyListener(MEDIA_SET_VIDEO_SIZE, 0, 0);
return;
}
+ int32_t err = OK;
+ inputFormat->findInt32("err", &err);
+ if (err == -EWOULDBLOCK) {
+ ALOGW("Video meta is not available yet!");
+ return;
+ }
+ if (err != OK) {
+ ALOGW("Something is wrong with video meta!");
+ return;
+ }
int32_t displayWidth, displayHeight;
if (outputFormat != NULL) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index c8b0102..6f737bb 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -158,6 +158,8 @@
int32_t mVideoDecoderGeneration;
int32_t mRendererGeneration;
+ int64_t mLastStartedPlayingTimeNs;
+
int64_t mPreviousSeekTimeUs;
List<sp<Action> > mDeferredActions;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 6ec79e6..f7e56e4 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -31,8 +31,14 @@
#include <media/stagefright/MetaData.h>
#include <media/stagefright/Utils.h>
+#include <media/IMediaAnalyticsService.h>
+
+static const int kDumpLockRetries = 50;
+static const int kDumpLockSleepUs = 20000;
+
namespace android {
+
NuPlayerDriver::NuPlayerDriver(pid_t pid)
: mState(STATE_IDLE),
mIsAsyncPrepare(false),
@@ -41,14 +47,20 @@
mDurationUs(-1),
mPositionUs(-1),
mSeekInProgress(false),
+ mPlayingTimeUs(0),
mLooper(new ALooper),
mPlayerFlags(0),
+ mAnalyticsItem(NULL),
mAtEOS(false),
mLooping(false),
mAutoLoop(false) {
- ALOGV("NuPlayerDriver(%p)", this);
+ ALOGD("NuPlayerDriver(%p) created, clientPid(%d)", this, pid);
mLooper->setName("NuPlayerDriver Looper");
+ // set up an analytics record
+ mAnalyticsItem = new MediaAnalyticsItem("nuplayer");
+ mAnalyticsItem->generateSessionID();
+
mLooper->start(
false, /* runOnCallingThread */
true, /* canCallJava */
@@ -63,6 +75,15 @@
NuPlayerDriver::~NuPlayerDriver() {
ALOGV("~NuPlayerDriver(%p)", this);
mLooper->stop();
+
+ // finalize any pending metrics, usually a no-op.
+ finalizeMetrics("destructor");
+ logMetrics("destructor");
+
+ if (mAnalyticsItem != NULL) {
+ delete mAnalyticsItem;
+ mAnalyticsItem = NULL;
+ }
}
status_t NuPlayerDriver::initCheck() {
@@ -450,8 +471,103 @@
return OK;
}
+void NuPlayerDriver::finalizeMetrics(const char *where) {
+ if (where == NULL) {
+ where = "unknown";
+ }
+ ALOGD("finalizeMetrics(%p) from %s at state %d", this, where, mState);
+
+ // gather the final stats for this record
+ Vector<sp<AMessage>> trackStats;
+ mPlayer->getStats(&trackStats);
+
+ if (trackStats.size() > 0) {
+ for (size_t i = 0; i < trackStats.size(); ++i) {
+ const sp<AMessage> &stats = trackStats.itemAt(i);
+
+ AString mime;
+ stats->findString("mime", &mime);
+
+ AString name;
+ stats->findString("component-name", &name);
+
+ if (mime.startsWith("video/")) {
+ int32_t width, height;
+ mAnalyticsItem->setCString("video/mime", mime.c_str());
+ if (!name.empty()) {
+ mAnalyticsItem->setCString("video/codec", name.c_str());
+ }
+
+ if (stats->findInt32("width", &width)
+ && stats->findInt32("height", &height)) {
+ mAnalyticsItem->setInt32("wid", width);
+ mAnalyticsItem->setInt32("ht", height);
+ }
+
+ int64_t numFramesTotal = 0;
+ int64_t numFramesDropped = 0;
+ stats->findInt64("frames-total", &numFramesTotal);
+ stats->findInt64("frames-dropped-output", &numFramesDropped);
+
+ mAnalyticsItem->setInt64("frames", numFramesTotal);
+ mAnalyticsItem->setInt64("dropped", numFramesDropped);
+
+
+ } else if (mime.startsWith("audio/")) {
+ mAnalyticsItem->setCString("audio/mime", mime.c_str());
+ if (!name.empty()) {
+ mAnalyticsItem->setCString("audio/codec", name.c_str());
+ }
+ }
+ }
+
+ // getDuration() uses mLock for mutex -- careful where we use it.
+ int duration_ms = -1;
+ getDuration(&duration_ms);
+ if (duration_ms != -1) {
+ mAnalyticsItem->setInt64("duration", duration_ms);
+ }
+
+ if (mPlayingTimeUs > 0) {
+ mAnalyticsItem->setInt64("playing", (mPlayingTimeUs+500)/1000 );
+ }
+ }
+}
+
+
+void NuPlayerDriver::logMetrics(const char *where) {
+ if (where == NULL) {
+ where = "unknown";
+ }
+ ALOGD("logMetrics(%p) from %s at state %d", this, where, mState);
+
+ if (mAnalyticsItem == NULL || mAnalyticsItem->isEnabled() == false) {
+ return;
+ }
+
+ // only bother to log non-empty records
+ if (mAnalyticsItem->count() > 0) {
+
+ mAnalyticsItem->setFinalized(true);
+ mAnalyticsItem->selfrecord();
+
+ // re-init in case we prepare() and start() again.
+ delete mAnalyticsItem ;
+ mAnalyticsItem = new MediaAnalyticsItem("nuplayer");
+ if (mAnalyticsItem) {
+ mAnalyticsItem->generateSessionID();
+ }
+ } else {
+ ALOGV("did not have anything to record");
+ }
+}
+
status_t NuPlayerDriver::reset() {
ALOGD("reset(%p) at state %d", this, mState);
+
+ finalizeMetrics("reset");
+ logMetrics("reset");
+
Mutex::Autolock autoLock(mLock);
switch (mState) {
@@ -493,6 +609,7 @@
mDurationUs = -1;
mPositionUs = -1;
mLooping = false;
+ mPlayingTimeUs = 0;
return OK;
}
@@ -624,6 +741,11 @@
mDurationUs = durationUs;
}
+void NuPlayerDriver::notifyMorePlayingTimeUs(int64_t playingUs) {
+ Mutex::Autolock autoLock(mLock);
+ mPlayingTimeUs += playingUs;
+}
+
void NuPlayerDriver::notifySeekComplete() {
ALOGV("notifySeekComplete(%p)", this);
Mutex::Autolock autoLock(mLock);
@@ -657,6 +779,24 @@
AString logString(" NuPlayer\n");
char buf[256] = {0};
+ bool locked = false;
+ for (int i = 0; i < kDumpLockRetries; ++i) {
+ if (mLock.tryLock() == NO_ERROR) {
+ locked = true;
+ break;
+ }
+ usleep(kDumpLockSleepUs);
+ }
+
+ if (locked) {
+ snprintf(buf, sizeof(buf), " state(%d), atEOS(%d), looping(%d), autoLoop(%d)\n",
+ mState, mAtEOS, mLooping, mAutoLoop);
+ mLock.unlock();
+ } else {
+ snprintf(buf, sizeof(buf), " NPD(%p) lock is taken\n", this);
+ }
+ logString.append(buf);
+
for (size_t i = 0; i < trackStats.size(); ++i) {
const sp<AMessage> &stats = trackStats.itemAt(i);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index 317b34c..9b784ae 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -16,6 +16,7 @@
#include <media/MediaPlayerInterface.h>
+#include <media/MediaAnalyticsItem.h>
#include <media/stagefright/foundation/ABase.h>
namespace android {
@@ -75,6 +76,7 @@
void notifyResetComplete();
void notifySetSurfaceComplete();
void notifyDuration(int64_t durationUs);
+ void notifyMorePlayingTimeUs(int64_t timeUs);
void notifySeekComplete();
void notifySeekComplete_l();
void notifyListener(int msg, int ext1 = 0, int ext2 = 0, const Parcel *in = NULL);
@@ -112,6 +114,7 @@
int64_t mDurationUs;
int64_t mPositionUs;
bool mSeekInProgress;
+ int64_t mPlayingTimeUs;
// <<<
sp<ALooper> mLooper;
@@ -119,10 +122,15 @@
sp<AudioSink> mAudioSink;
uint32_t mPlayerFlags;
+ MediaAnalyticsItem *mAnalyticsItem;
+
bool mAtEOS;
bool mLooping;
bool mAutoLoop;
+ void finalizeMetrics(const char *where);
+ void logMetrics(const char *where);
+
status_t prepare_l();
status_t start_l();
void notifyListener_l(int msg, int ext1 = 0, int ext2 = 0, const Parcel *in = NULL);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
index 5197167..6006730 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
@@ -77,7 +77,11 @@
// an error or ERROR_END_OF_STREAM if not.
virtual status_t feedMoreTSData() = 0;
+ // Returns non-NULL format when the specified track exists.
+ // When the format has "err" set to -EWOULDBLOCK, source needs more time to get valid meta data.
+ // Returns NULL if the specified track doesn't exist or is invalid;
virtual sp<AMessage> getFormat(bool audio);
+
virtual sp<MetaData> getFormatMeta(bool /* audio */) { return NULL; }
virtual sp<MetaData> getFileFormatMeta() const { return NULL; }
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
index 7f9f913..d6b1e8c 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
@@ -234,8 +234,7 @@
}
status_t err = convertMetaDataToMessage(meta, &format);
if (err != OK) { // format may have been cleared on error
- format = new AMessage;
- format->setInt32("err", err);
+ return NULL;
}
return format;
}
diff --git a/media/liboboe/include/oboe/OboeAudio.h b/media/liboboe/include/oboe/OboeAudio.h
index 788cf5f..2181b8c 100644
--- a/media/liboboe/include/oboe/OboeAudio.h
+++ b/media/liboboe/include/oboe/OboeAudio.h
@@ -372,7 +372,7 @@
*
* @param stream A stream created using OboeStreamBuilder_openStream().
* @param periodNanoseconds the estimated period at which the audio thread will need to wake up
- * @param start_routine your thread entry point
+ * @param startRoutine your thread entry point
* @param arg an argument that will be passed to your thread entry point
* @return OBOE_OK or a negative error.
*/
@@ -408,7 +408,7 @@
*
* @param stream handle provided by OboeStreamBuilder_openStream()
* @param requestedFrames requested number of frames that can be filled without blocking
- * @return actualFrames receives final number of frames
+ * @param actualFrames receives final number of frames
* @return OBOE_OK or a negative error
*/
OBOE_API oboe_result_t OboeStream_setBufferSize(OboeStream stream,
diff --git a/media/liboboe/src/utility/HandleTracker.h b/media/liboboe/src/utility/HandleTracker.h
index da5b654..37dbac8 100644
--- a/media/liboboe/src/utility/HandleTracker.h
+++ b/media/liboboe/src/utility/HandleTracker.h
@@ -53,7 +53,7 @@
/**
* Store a pointer and return a handle that can be used to retrieve the pointer.
*
- * @param type the type of the object to be tracked
+ * @param expectedType the type of the object to be tracked
* @param address pointer to be converted to a handle
* @return a valid handle or a negative error
*/
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 13401fc..f247475 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -53,6 +53,7 @@
#include <OMX_AsString.h>
#include "include/avc_utils.h"
+#include "include/ACodecBufferChannel.h"
#include "include/DataConverter.h"
#include "include/SecureBuffer.h"
#include "include/SharedMemoryBuffer.h"
@@ -564,16 +565,21 @@
ACodec::~ACodec() {
}
-void ACodec::setNotificationMessage(const sp<AMessage> &msg) {
- mNotify = msg;
-}
-
void ACodec::initiateSetup(const sp<AMessage> &msg) {
msg->setWhat(kWhatSetup);
msg->setTarget(this);
msg->post();
}
+std::shared_ptr<BufferChannelBase> ACodec::getBufferChannel() {
+ if (!mBufferChannel) {
+ mBufferChannel = std::make_shared<ACodecBufferChannel>(
+ new AMessage(kWhatInputBufferFilled, this),
+ new AMessage(kWhatOutputBufferDrained, this));
+ }
+ return mBufferChannel;
+}
+
void ACodec::signalSetParameters(const sp<AMessage> ¶ms) {
sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
msg->setMessage("params", params);
@@ -936,12 +942,17 @@
return err;
}
- sp<PortDescription> desc = new PortDescription;
+ std::vector<ACodecBufferChannel::BufferAndId> array(mBuffers[portIndex].size());
for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
- const BufferInfo &info = mBuffers[portIndex][i];
- desc->addBuffer(info.mBufferID, info.mData);
+ array[i] = {mBuffers[portIndex][i].mData, mBuffers[portIndex][i].mBufferID};
}
- mCallback->onBuffersAllocated(portIndex, desc);
+ if (portIndex == kPortIndexInput) {
+ mBufferChannel->setInputBufferArray(array);
+ } else if (portIndex == kPortIndexOutput) {
+ mBufferChannel->setOutputBufferArray(array);
+ } else {
+ TRESPASS();
+ }
return OK;
}
@@ -1432,6 +1443,12 @@
}
status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
+ if (portIndex == kPortIndexInput) {
+ mBufferChannel->setInputBufferArray({});
+ } else {
+ mBufferChannel->setOutputBufferArray({});
+ }
+
status_t err = OK;
for (size_t i = mBuffers[portIndex].size(); i > 0;) {
i--;
@@ -5076,25 +5093,6 @@
}
}
-void ACodec::addKeyFormatChangesToRenderBufferNotification(sp<AMessage> ¬ify) {
- AString mime;
- CHECK(mOutputFormat->findString("mime", &mime));
-
- if (mime == MEDIA_MIMETYPE_VIDEO_RAW && mNativeWindow != NULL) {
- // notify renderer of the crop change and dataspace change
- // NOTE: native window uses extended right-bottom coordinate
- int32_t left, top, right, bottom;
- if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
- notify->setRect("crop", left, top, right + 1, bottom + 1);
- }
-
- int32_t dataSpace;
- if (mOutputFormat->findInt32("android._dataspace", &dataSpace)) {
- notify->setInt32("dataspace", dataSpace);
- }
- }
-}
-
void ACodec::sendFormatChange() {
AString mime;
CHECK(mOutputFormat->findString("mime", &mime));
@@ -5156,29 +5154,6 @@
////////////////////////////////////////////////////////////////////////////////
-ACodec::PortDescription::PortDescription() {
-}
-
-void ACodec::PortDescription::addBuffer(
- IOMX::buffer_id id, const sp<MediaCodecBuffer> &buffer) {
- mBufferIDs.push_back(id);
- mBuffers.push_back(buffer);
-}
-
-size_t ACodec::PortDescription::countBuffers() {
- return mBufferIDs.size();
-}
-
-IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const {
- return mBufferIDs.itemAt(index);
-}
-
-sp<MediaCodecBuffer> ACodec::PortDescription::bufferAt(size_t index) const {
- return mBuffers.itemAt(index);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
: AState(parentState),
mCodec(codec) {
@@ -5486,9 +5461,7 @@
CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
info->mData->setFormat(mCodec->mInputFormat);
- sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec);
- reply->setInt32("buffer-id", info->mBufferID);
- mCodec->mCallback->fillThisBuffer(info->mBufferID, info->mData, reply);
+ mCodec->mBufferChannel->fillThisBuffer(info->mBufferID);
info->mData.clear();
info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
}
@@ -5502,17 +5475,9 @@
PortMode mode = getPortMode(kPortIndexInput);
int32_t discarded = 0;
if (msg->findInt32("discarded", &discarded) && discarded) {
- /* these are unfilled buffers returned by client */
- CHECK(msg->findInt32("err", &err));
-
- if (err == OK) {
- /* buffers with no errors are returned on MediaCodec.flush */
- mode = KEEP_BUFFERS;
- } else {
- ALOGV("[%s] saw error %d instead of an input buffer",
- mCodec->mComponentName.c_str(), err);
- eos = true;
- }
+ // these are unfilled buffers returned by client
+ // buffers are returned on MediaCodec.flush
+ mode = KEEP_BUFFERS;
}
sp<RefBase> obj;
CHECK(msg->findObject("buffer", &obj));
@@ -5839,7 +5804,6 @@
break;
}
- sp<AMessage> reply = new AMessage(kWhatOutputBufferDrained, mCodec);
sp<MediaCodecBuffer> buffer = info->mData;
if (mCodec->mOutputFormat != mCodec->mLastOutputFormat && rangeLength > 0) {
@@ -5847,12 +5811,7 @@
if (mCodec->mBaseOutputFormat == mCodec->mOutputFormat) {
mCodec->onOutputFormatChanged(mCodec->mOutputFormat);
}
- mCodec->addKeyFormatChangesToRenderBufferNotification(reply);
mCodec->sendFormatChange();
- } else if (rangeLength > 0 && mCodec->mNativeWindow != NULL) {
- // If potentially rendering onto a surface, always save key format data (crop &
- // data space) so that we can set it if and once the buffer is rendered.
- mCodec->addKeyFormatChangesToRenderBufferNotification(reply);
}
buffer->setFormat(mCodec->mOutputFormat);
@@ -5897,9 +5856,7 @@
info->mData.clear();
- reply->setInt32("buffer-id", info->mBufferID);
-
- mCodec->mCallback->drainThisBuffer(info->mBufferID, buffer, flags, reply);
+ mCodec->mBufferChannel->drainThisBuffer(info->mBufferID, flags);
info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
@@ -5947,24 +5904,6 @@
return;
}
info->mData = buffer;
-
- android_native_rect_t crop;
- if (msg->findRect("crop", &crop.left, &crop.top, &crop.right, &crop.bottom)
- && memcmp(&crop, &mCodec->mLastNativeWindowCrop, sizeof(crop)) != 0) {
- mCodec->mLastNativeWindowCrop = crop;
- status_t err = native_window_set_crop(mCodec->mNativeWindow.get(), &crop);
- ALOGW_IF(err != NO_ERROR, "failed to set crop: %d", err);
- }
-
- int32_t dataSpace;
- if (msg->findInt32("dataspace", &dataSpace)
- && dataSpace != mCodec->mLastNativeWindowDataSpace) {
- status_t err = native_window_set_buffers_data_space(
- mCodec->mNativeWindow.get(), (android_dataspace)dataSpace);
- mCodec->mLastNativeWindowDataSpace = dataSpace;
- ALOGW_IF(err != NO_ERROR, "failed to set dataspace: %d", err);
- }
-
int32_t render;
if (mCodec->mNativeWindow != NULL
&& msg->findInt32("render", &render) && render != 0
@@ -5972,6 +5911,27 @@
ATRACE_NAME("render");
// The client wants this buffer to be rendered.
+ android_native_rect_t crop;
+ if (buffer->format()->findRect("crop", &crop.left, &crop.top, &crop.right, &crop.bottom)) {
+ // NOTE: native window uses extended right-bottom coordinate
+ ++crop.right;
+ ++crop.bottom;
+ if (memcmp(&crop, &mCodec->mLastNativeWindowCrop, sizeof(crop)) != 0) {
+ mCodec->mLastNativeWindowCrop = crop;
+ status_t err = native_window_set_crop(mCodec->mNativeWindow.get(), &crop);
+ ALOGW_IF(err != NO_ERROR, "failed to set crop: %d", err);
+ }
+ }
+
+ int32_t dataSpace;
+ if (buffer->format()->findInt32("android._dataspace", &dataSpace)
+ && dataSpace != mCodec->mLastNativeWindowDataSpace) {
+ status_t err = native_window_set_buffers_data_space(
+ mCodec->mNativeWindow.get(), (android_dataspace)dataSpace);
+ mCodec->mLastNativeWindowDataSpace = dataSpace;
+ ALOGW_IF(err != NO_ERROR, "failed to set dataspace: %d", err);
+ }
+
// save buffers sent to the surface so we can get render time when they return
int64_t mediaTimeUs = -1;
buffer->meta()->findInt64("timeUs", &mediaTimeUs);
@@ -6613,12 +6573,18 @@
status_t ACodec::LoadedToIdleState::allocateBuffers() {
status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
-
if (err != OK) {
return err;
}
- return mCodec->allocateBuffersOnPort(kPortIndexOutput);
+ err = mCodec->allocateBuffersOnPort(kPortIndexOutput);
+ if (err != OK) {
+ return err;
+ }
+
+ mCodec->mCallback->onStartCompleted();
+
+ return OK;
}
bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
@@ -7226,6 +7192,7 @@
err = mCodec->allocateBuffersOnPort(kPortIndexOutput);
ALOGE_IF(err != OK, "Failed to allocate output port buffers after port "
"reconfiguration: (%d)", err);
+ mCodec->mCallback->onOutputBuffersChanged();
}
if (err != OK) {
diff --git a/media/libstagefright/ACodecBufferChannel.cpp b/media/libstagefright/ACodecBufferChannel.cpp
new file mode 100644
index 0000000..1db7ab0
--- /dev/null
+++ b/media/libstagefright/ACodecBufferChannel.cpp
@@ -0,0 +1,308 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ACodecBufferChannel"
+#include <utils/Log.h>
+
+#include <numeric>
+
+#include <binder/MemoryDealer.h>
+#include <media/openmax/OMX_Core.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AUtils.h>
+#include <media/stagefright/MediaCodec.h>
+#include <media/MediaCodecBuffer.h>
+#include <system/window.h>
+
+#include "include/ACodecBufferChannel.h"
+#include "include/SecureBuffer.h"
+#include "include/SharedMemoryBuffer.h"
+
+namespace android {
+
+using BufferInfo = ACodecBufferChannel::BufferInfo;
+using BufferInfoIterator = std::vector<const BufferInfo>::const_iterator;
+
+static BufferInfoIterator findClientBuffer(
+ const std::shared_ptr<const std::vector<const BufferInfo>> &array,
+ const sp<MediaCodecBuffer> &buffer) {
+ return std::find_if(
+ array->begin(), array->end(),
+ [buffer](const BufferInfo &info) { return info.mClientBuffer == buffer; });
+}
+
+static BufferInfoIterator findBufferId(
+ const std::shared_ptr<const std::vector<const BufferInfo>> &array,
+ IOMX::buffer_id bufferId) {
+ return std::find_if(
+ array->begin(), array->end(),
+ [bufferId](const BufferInfo &info) { return bufferId == info.mBufferId; });
+}
+
+ACodecBufferChannel::BufferInfo::BufferInfo(
+ const sp<MediaCodecBuffer> &buffer,
+ IOMX::buffer_id bufferId,
+ const sp<IMemory> &sharedEncryptedBuffer)
+ : mClientBuffer(
+ (sharedEncryptedBuffer == nullptr)
+ ? buffer
+ : new SharedMemoryBuffer(buffer->format(), sharedEncryptedBuffer)),
+ mCodecBuffer(buffer),
+ mBufferId(bufferId),
+ mSharedEncryptedBuffer(sharedEncryptedBuffer) {
+}
+
+ACodecBufferChannel::ACodecBufferChannel(
+ const sp<AMessage> &inputBufferFilled, const sp<AMessage> &outputBufferDrained)
+ : mInputBufferFilled(inputBufferFilled),
+ mOutputBufferDrained(outputBufferDrained) {
+}
+
+status_t ACodecBufferChannel::queueInputBuffer(const sp<MediaCodecBuffer> &buffer) {
+ std::shared_ptr<const std::vector<const BufferInfo>> array(
+ std::atomic_load(&mInputBuffers));
+ BufferInfoIterator it = findClientBuffer(array, buffer);
+ if (it == array->end()) {
+ return -ENOENT;
+ }
+ ALOGV("queueInputBuffer #%d", it->mBufferId);
+ sp<AMessage> msg = mInputBufferFilled->dup();
+ msg->setObject("buffer", it->mCodecBuffer);
+ msg->setInt32("buffer-id", it->mBufferId);
+ msg->post();
+ return OK;
+}
+
+status_t ACodecBufferChannel::queueSecureInputBuffer(
+ const sp<MediaCodecBuffer> &buffer,
+ bool secure,
+ const uint8_t *key,
+ const uint8_t *iv,
+ CryptoPlugin::Mode mode,
+ CryptoPlugin::Pattern pattern,
+ const CryptoPlugin::SubSample *subSamples,
+ size_t numSubSamples,
+ AString *errorDetailMsg) {
+ if (mCrypto == nullptr) {
+ return -ENOSYS;
+ }
+ std::shared_ptr<const std::vector<const BufferInfo>> array(
+ std::atomic_load(&mInputBuffers));
+ BufferInfoIterator it = findClientBuffer(array, buffer);
+ if (it == array->end()) {
+ return -ENOENT;
+ }
+
+ void *dst_pointer = nullptr;
+ ICrypto::DestinationType dst_type = ICrypto::kDestinationTypeOpaqueHandle;
+
+ if (secure) {
+ sp<SecureBuffer> secureData = static_cast<SecureBuffer *>(it->mCodecBuffer.get());
+ dst_pointer = secureData->getDestinationPointer();
+ dst_type = secureData->getDestinationType();
+ } else {
+ dst_pointer = it->mCodecBuffer->base();
+ dst_type = ICrypto::kDestinationTypeVmPointer;
+ }
+
+ ssize_t result = mCrypto->decrypt(
+ dst_type,
+ key,
+ iv,
+ mode,
+ pattern,
+ it->mSharedEncryptedBuffer,
+ it->mClientBuffer->offset(),
+ subSamples,
+ numSubSamples,
+ dst_pointer,
+ errorDetailMsg);
+
+ if (result < 0) {
+ return result;
+ }
+
+ it->mCodecBuffer->setRange(0, result);
+
+ // Copy metadata from client to codec buffer.
+ it->mCodecBuffer->meta()->clear();
+ int64_t timeUs;
+ CHECK(it->mClientBuffer->meta()->findInt64("timeUs", &timeUs));
+ it->mCodecBuffer->meta()->setInt64("timeUs", timeUs);
+ int32_t eos;
+ if (it->mClientBuffer->meta()->findInt32("eos", &eos)) {
+ it->mCodecBuffer->meta()->setInt32("eos", eos);
+ }
+ int32_t csd;
+ if (it->mClientBuffer->meta()->findInt32("csd", &csd)) {
+ it->mCodecBuffer->meta()->setInt32("csd", csd);
+ }
+
+ ALOGV("queueSecureInputBuffer #%d", it->mBufferId);
+ sp<AMessage> msg = mInputBufferFilled->dup();
+ msg->setObject("buffer", it->mCodecBuffer);
+ msg->setInt32("buffer-id", it->mBufferId);
+ msg->post();
+ return OK;
+}
+
+status_t ACodecBufferChannel::renderOutputBuffer(
+ const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) {
+ std::shared_ptr<const std::vector<const BufferInfo>> array(
+ std::atomic_load(&mOutputBuffers));
+ BufferInfoIterator it = findClientBuffer(array, buffer);
+ if (it == array->end()) {
+ return -ENOENT;
+ }
+
+ ALOGV("renderOutputBuffer #%d", it->mBufferId);
+ sp<AMessage> msg = mOutputBufferDrained->dup();
+ msg->setObject("buffer", buffer);
+ msg->setInt32("buffer-id", it->mBufferId);
+ msg->setInt32("render", true);
+ msg->setInt64("timestampNs", timestampNs);
+ msg->post();
+ return OK;
+}
+
+status_t ACodecBufferChannel::discardBuffer(const sp<MediaCodecBuffer> &buffer) {
+ std::shared_ptr<const std::vector<const BufferInfo>> array(
+ std::atomic_load(&mInputBuffers));
+ bool input = true;
+ BufferInfoIterator it = findClientBuffer(array, buffer);
+ if (it == array->end()) {
+ array = std::atomic_load(&mOutputBuffers);
+ input = false;
+ it = findClientBuffer(array, buffer);
+ if (it == array->end()) {
+ return -ENOENT;
+ }
+ }
+ ALOGV("discardBuffer #%d", it->mBufferId);
+ sp<AMessage> msg = input ? mInputBufferFilled->dup() : mOutputBufferDrained->dup();
+ msg->setObject("buffer", it->mCodecBuffer);
+ msg->setInt32("buffer-id", it->mBufferId);
+ msg->setInt32("discarded", true);
+ msg->post();
+ return OK;
+}
+
+void ACodecBufferChannel::getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
+ std::shared_ptr<const std::vector<const BufferInfo>> inputBuffers(
+ std::atomic_load(&mInputBuffers));
+ array->clear();
+ for (const BufferInfo &elem : *inputBuffers) {
+ array->push_back(elem.mClientBuffer);
+ }
+}
+
+void ACodecBufferChannel::getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
+ std::shared_ptr<const std::vector<const BufferInfo>> outputBuffers(
+ std::atomic_load(&mOutputBuffers));
+ array->clear();
+ for (const BufferInfo &elem : *outputBuffers) {
+ array->push_back(elem.mClientBuffer);
+ }
+}
+
+void ACodecBufferChannel::setInputBufferArray(const std::vector<BufferAndId> &array) {
+ bool secure = (mCrypto != nullptr);
+ if (secure) {
+ size_t totalSize = std::accumulate(
+ array.begin(), array.end(), 0u,
+ [alignment = MemoryDealer::getAllocationAlignment()]
+ (size_t sum, const BufferAndId& elem) {
+ return sum + align(elem.mBuffer->capacity(), alignment);
+ });
+ mDealer = new MemoryDealer(totalSize, "ACodecBufferChannel");
+ }
+ std::vector<const BufferInfo> inputBuffers;
+ for (const BufferAndId &elem : array) {
+ sp<IMemory> sharedEncryptedBuffer;
+ if (secure) {
+ sharedEncryptedBuffer = mDealer->allocate(elem.mBuffer->capacity());
+ }
+ inputBuffers.emplace_back(elem.mBuffer, elem.mBufferId, sharedEncryptedBuffer);
+ }
+ std::atomic_store(
+ &mInputBuffers,
+ std::make_shared<const std::vector<const BufferInfo>>(inputBuffers));
+}
+
+void ACodecBufferChannel::setOutputBufferArray(const std::vector<BufferAndId> &array) {
+ std::vector<const BufferInfo> outputBuffers;
+ for (const BufferAndId &elem : array) {
+ outputBuffers.emplace_back(elem.mBuffer, elem.mBufferId, nullptr);
+ }
+ std::atomic_store(
+ &mOutputBuffers,
+ std::make_shared<const std::vector<const BufferInfo>>(outputBuffers));
+}
+
+void ACodecBufferChannel::fillThisBuffer(IOMX::buffer_id bufferId) {
+ ALOGV("fillThisBuffer #%d", bufferId);
+ std::shared_ptr<const std::vector<const BufferInfo>> array(
+ std::atomic_load(&mInputBuffers));
+ BufferInfoIterator it = findBufferId(array, bufferId);
+
+ if (it == array->end()) {
+ ALOGE("fillThisBuffer: unrecognized buffer #%d", bufferId);
+ return;
+ }
+ if (it->mClientBuffer != it->mCodecBuffer) {
+ it->mClientBuffer->setFormat(it->mCodecBuffer->format());
+ }
+
+ mCallback->onInputBufferAvailable(
+ std::distance(array->begin(), it),
+ it->mClientBuffer);
+}
+
+void ACodecBufferChannel::drainThisBuffer(
+ IOMX::buffer_id bufferId,
+ OMX_U32 omxFlags) {
+ ALOGV("drainThisBuffer #%d", bufferId);
+ std::shared_ptr<const std::vector<const BufferInfo>> array(
+ std::atomic_load(&mOutputBuffers));
+ BufferInfoIterator it = findBufferId(array, bufferId);
+
+ if (it == array->end()) {
+ ALOGE("drainThisBuffer: unrecognized buffer #%d", bufferId);
+ return;
+ }
+ if (it->mClientBuffer != it->mCodecBuffer) {
+ it->mClientBuffer->setFormat(it->mCodecBuffer->format());
+ }
+
+ uint32_t flags = 0;
+ if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
+ flags |= MediaCodec::BUFFER_FLAG_SYNCFRAME;
+ }
+ if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
+ flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
+ }
+ if (omxFlags & OMX_BUFFERFLAG_EOS) {
+ flags |= MediaCodec::BUFFER_FLAG_EOS;
+ }
+ it->mClientBuffer->meta()->setInt32("flags", flags);
+
+ mCallback->onOutputBufferAvailable(
+ std::distance(array->begin(), it),
+ it->mClientBuffer);
+}
+
+} // namespace android
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 8c42cfd..f3d622b 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -4,6 +4,7 @@
LOCAL_SRC_FILES:= \
ACodec.cpp \
+ ACodecBufferChannel.cpp \
AACExtractor.cpp \
AACWriter.cpp \
AMRExtractor.cpp \
@@ -14,7 +15,6 @@
CallbackDataSource.cpp \
CameraSource.cpp \
CameraSourceTimeLapse.cpp \
- CodecBase.cpp \
DataConverter.cpp \
DataSource.cpp \
DataURISource.cpp \
diff --git a/media/libstagefright/CodecBase.cpp b/media/libstagefright/CodecBase.cpp
deleted file mode 100644
index 3eca52a..0000000
--- a/media/libstagefright/CodecBase.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2014 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 "CodecBase"
-
-#include <inttypes.h>
-
-#include <media/stagefright/CodecBase.h>
-
-namespace android {
-
-CodecBase::CodecBase() {
-}
-
-CodecBase::~CodecBase() {
-}
-
-CodecBase::PortDescription::PortDescription() {
-}
-
-CodecBase::PortDescription::~PortDescription() {
-}
-
-void CodecBase::setCallback(std::shared_ptr<Callback> &&callback) {
- mCallback = callback;
-}
-
-} // namespace android
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
old mode 100644
new mode 100755
index 0d61bf5..716f5d8
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -3309,13 +3309,22 @@
void MPEG4Writer::Track::writeMdhdBox(uint32_t now) {
int64_t trakDurationUs = getDurationUs();
+ int64_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
mOwner->beginBox("mdhd");
- mOwner->writeInt32(0); // version=0, flags=0
- mOwner->writeInt32(now); // creation time
- mOwner->writeInt32(now); // modification time
- mOwner->writeInt32(mTimeScale); // media timescale
- int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
- mOwner->writeInt32(mdhdDuration); // use media timescale
+
+ if (mdhdDuration > UINT32_MAX) {
+ mOwner->writeInt32((1 << 24)); // version=1, flags=0
+ mOwner->writeInt64((int64_t)now); // creation time
+ mOwner->writeInt64((int64_t)now); // modification time
+ mOwner->writeInt32(mTimeScale); // media timescale
+ mOwner->writeInt64(mdhdDuration); // media timescale
+ } else {
+ mOwner->writeInt32(0); // version=0, flags=0
+ mOwner->writeInt32(now); // creation time
+ mOwner->writeInt32(now); // modification time
+ mOwner->writeInt32(mTimeScale); // media timescale
+ mOwner->writeInt32((int32_t)mdhdDuration); // use media timescale
+ }
// Language follows the three letter standard ISO-639-2/T
// 'e', 'n', 'g' for "English", for instance.
// Each character is packed as the difference between its ASCII value and 0x60.
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index f29f786..9eca982 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -37,6 +37,7 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/ACodec.h>
#include <media/stagefright/BufferProducerWrapper.h>
@@ -66,6 +67,7 @@
static const int kMaxRetry = 2;
static const int kMaxReclaimWaitTimeInUs = 500000; // 0.5s
+static const int kNumBuffersAlign = 16;
////////////////////////////////////////////////////////////////////////////////
@@ -175,12 +177,17 @@
////////////////////////////////////////////////////////////////////////////////
+MediaCodec::BufferInfo::BufferInfo() : mOwnedByClient(false) {}
+
+////////////////////////////////////////////////////////////////////////////////
+
namespace {
enum {
kWhatFillThisBuffer = 'fill',
kWhatDrainThisBuffer = 'drai',
kWhatEOS = 'eos ',
+ kWhatStartCompleted = 'Scom',
kWhatStopCompleted = 'scom',
kWhatReleaseCompleted = 'rcom',
kWhatFlushCompleted = 'fcom',
@@ -190,20 +197,51 @@
kWhatInputSurfaceCreated = 'isfc',
kWhatInputSurfaceAccepted = 'isfa',
kWhatSignaledInputEOS = 'seos',
- kWhatBuffersAllocated = 'allc',
kWhatOutputFramesRendered = 'outR',
+ kWhatOutputBuffersChanged = 'outC',
};
-class MediaCodecCallback : public CodecBase::Callback {
+class BufferCallback : public CodecBase::BufferCallback {
public:
- explicit MediaCodecCallback(const sp<AMessage> ¬ify);
- virtual ~MediaCodecCallback();
+ explicit BufferCallback(const sp<AMessage> ¬ify);
+ virtual ~BufferCallback() = default;
- virtual void fillThisBuffer(IOMX::buffer_id bufferId, const sp<MediaCodecBuffer> &buffer,
- const sp<AMessage> &reply) override;
- virtual void drainThisBuffer(IOMX::buffer_id bufferId, const sp<MediaCodecBuffer> &buffer,
- int32_t flags, const sp<AMessage> &reply) override;
+ virtual void onInputBufferAvailable(
+ size_t index, const sp<MediaCodecBuffer> &buffer) override;
+ virtual void onOutputBufferAvailable(
+ size_t index, const sp<MediaCodecBuffer> &buffer) override;
+private:
+ const sp<AMessage> mNotify;
+};
+
+BufferCallback::BufferCallback(const sp<AMessage> ¬ify)
+ : mNotify(notify) {}
+
+void BufferCallback::onInputBufferAvailable(
+ size_t index, const sp<MediaCodecBuffer> &buffer) {
+ sp<AMessage> notify(mNotify->dup());
+ notify->setInt32("what", kWhatFillThisBuffer);
+ notify->setSize("index", index);
+ notify->setObject("buffer", buffer);
+ notify->post();
+}
+
+void BufferCallback::onOutputBufferAvailable(
+ size_t index, const sp<MediaCodecBuffer> &buffer) {
+ sp<AMessage> notify(mNotify->dup());
+ notify->setInt32("what", kWhatDrainThisBuffer);
+ notify->setSize("index", index);
+ notify->setObject("buffer", buffer);
+ notify->post();
+}
+
+class CodecCallback : public CodecBase::CodecCallback {
+public:
+ explicit CodecCallback(const sp<AMessage> ¬ify);
+ virtual ~CodecCallback() = default;
+
virtual void onEos(status_t err) override;
+ virtual void onStartCompleted() override;
virtual void onStopCompleted() override;
virtual void onReleaseCompleted() override;
virtual void onFlushCompleted() override;
@@ -221,69 +259,46 @@
const sp<AMessage> &outputFormat) override;
virtual void onInputSurfaceDeclined(status_t err) override;
virtual void onSignaledInputEOS(status_t err) override;
- virtual void onBuffersAllocated(
- int32_t portIndex, const sp<CodecBase::PortDescription> &portDesc) override;
virtual void onOutputFramesRendered(const std::list<FrameRenderTracker::Info> &done) override;
+ virtual void onOutputBuffersChanged() override;
private:
const sp<AMessage> mNotify;
};
-MediaCodecCallback::MediaCodecCallback(const sp<AMessage> ¬ify) : mNotify(notify) {}
+CodecCallback::CodecCallback(const sp<AMessage> ¬ify) : mNotify(notify) {}
-MediaCodecCallback::~MediaCodecCallback() {}
-
-void MediaCodecCallback::fillThisBuffer(
- IOMX::buffer_id bufferId,
- const sp<MediaCodecBuffer> &buffer,
- const sp<AMessage> &reply) {
- sp<AMessage> notify(mNotify->dup());
- notify->setInt32("what", kWhatFillThisBuffer);
- notify->setInt32("buffer-id", bufferId);
- notify->setObject("buffer", buffer);
- notify->setMessage("reply", reply);
- notify->post();
-}
-
-void MediaCodecCallback::drainThisBuffer(
- IOMX::buffer_id bufferId,
- const sp<MediaCodecBuffer> &buffer,
- int32_t flags,
- const sp<AMessage> &reply) {
- sp<AMessage> notify(mNotify->dup());
- notify->setInt32("what", kWhatDrainThisBuffer);
- notify->setInt32("buffer-id", bufferId);
- notify->setObject("buffer", buffer);
- notify->setInt32("flags", flags);
- notify->setMessage("reply", reply);
- notify->post();
-}
-
-void MediaCodecCallback::onEos(status_t err) {
+void CodecCallback::onEos(status_t err) {
sp<AMessage> notify(mNotify->dup());
notify->setInt32("what", kWhatEOS);
notify->setInt32("err", err);
notify->post();
}
-void MediaCodecCallback::onStopCompleted() {
+void CodecCallback::onStartCompleted() {
+ sp<AMessage> notify(mNotify->dup());
+ notify->setInt32("what", kWhatStartCompleted);
+ notify->post();
+}
+
+void CodecCallback::onStopCompleted() {
sp<AMessage> notify(mNotify->dup());
notify->setInt32("what", kWhatStopCompleted);
notify->post();
}
-void MediaCodecCallback::onReleaseCompleted() {
+void CodecCallback::onReleaseCompleted() {
sp<AMessage> notify(mNotify->dup());
notify->setInt32("what", kWhatReleaseCompleted);
notify->post();
}
-void MediaCodecCallback::onFlushCompleted() {
+void CodecCallback::onFlushCompleted() {
sp<AMessage> notify(mNotify->dup());
notify->setInt32("what", kWhatFlushCompleted);
notify->post();
}
-void MediaCodecCallback::onError(status_t err, enum ActionCode actionCode) {
+void CodecCallback::onError(status_t err, enum ActionCode actionCode) {
sp<AMessage> notify(mNotify->dup());
notify->setInt32("what", kWhatError);
notify->setInt32("err", err);
@@ -291,14 +306,14 @@
notify->post();
}
-void MediaCodecCallback::onComponentAllocated(const char *componentName) {
+void CodecCallback::onComponentAllocated(const char *componentName) {
sp<AMessage> notify(mNotify->dup());
notify->setInt32("what", kWhatComponentAllocated);
notify->setString("componentName", componentName);
notify->post();
}
-void MediaCodecCallback::onComponentConfigured(
+void CodecCallback::onComponentConfigured(
const sp<AMessage> &inputFormat, const sp<AMessage> &outputFormat) {
sp<AMessage> notify(mNotify->dup());
notify->setInt32("what", kWhatComponentConfigured);
@@ -307,7 +322,7 @@
notify->post();
}
-void MediaCodecCallback::onInputSurfaceCreated(
+void CodecCallback::onInputSurfaceCreated(
const sp<AMessage> &inputFormat,
const sp<AMessage> &outputFormat,
const sp<BufferProducerWrapper> &inputSurface) {
@@ -319,14 +334,14 @@
notify->post();
}
-void MediaCodecCallback::onInputSurfaceCreationFailed(status_t err) {
+void CodecCallback::onInputSurfaceCreationFailed(status_t err) {
sp<AMessage> notify(mNotify->dup());
notify->setInt32("what", kWhatInputSurfaceCreated);
notify->setInt32("err", err);
notify->post();
}
-void MediaCodecCallback::onInputSurfaceAccepted(
+void CodecCallback::onInputSurfaceAccepted(
const sp<AMessage> &inputFormat,
const sp<AMessage> &outputFormat) {
sp<AMessage> notify(mNotify->dup());
@@ -336,14 +351,14 @@
notify->post();
}
-void MediaCodecCallback::onInputSurfaceDeclined(status_t err) {
+void CodecCallback::onInputSurfaceDeclined(status_t err) {
sp<AMessage> notify(mNotify->dup());
notify->setInt32("what", kWhatInputSurfaceAccepted);
notify->setInt32("err", err);
notify->post();
}
-void MediaCodecCallback::onSignaledInputEOS(status_t err) {
+void CodecCallback::onSignaledInputEOS(status_t err) {
sp<AMessage> notify(mNotify->dup());
notify->setInt32("what", kWhatSignaledInputEOS);
if (err != OK) {
@@ -352,16 +367,7 @@
notify->post();
}
-void MediaCodecCallback::onBuffersAllocated(
- int32_t portIndex, const sp<CodecBase::PortDescription> &portDesc) {
- sp<AMessage> notify(mNotify->dup());
- notify->setInt32("what", kWhatBuffersAllocated);
- notify->setInt32("portIndex", portIndex);
- notify->setObject("portDesc", portDesc);
- notify->post();
-}
-
-void MediaCodecCallback::onOutputFramesRendered(const std::list<FrameRenderTracker::Info> &done) {
+void CodecCallback::onOutputFramesRendered(const std::list<FrameRenderTracker::Info> &done) {
sp<AMessage> notify(mNotify->dup());
notify->setInt32("what", kWhatOutputFramesRendered);
if (MediaCodec::CreateFramesRenderedMessage(done, notify)) {
@@ -369,6 +375,12 @@
}
}
+void CodecCallback::onOutputBuffersChanged() {
+ sp<AMessage> notify(mNotify->dup());
+ notify->setInt32("what", kWhatOutputBuffersChanged);
+ notify->post();
+}
+
} // namespace
////////////////////////////////////////////////////////////////////////////////
@@ -573,7 +585,12 @@
mLooper->registerHandler(this);
mCodec->setCallback(
- std::make_shared<MediaCodecCallback>(new AMessage(kWhatCodecNotify, this)));
+ std::unique_ptr<CodecBase::CodecCallback>(
+ new CodecCallback(new AMessage(kWhatCodecNotify, this))));
+ mBufferChannel = mCodec->getBufferChannel();
+ mBufferChannel->setCallback(
+ std::unique_ptr<CodecBase::BufferCallback>(
+ new BufferCallback(new AMessage(kWhatCodecNotify, this))));
sp<AMessage> msg = new AMessage(kWhatInit, this);
msg->setString("name", name);
@@ -800,14 +817,9 @@
}
bool MediaCodec::hasPendingBuffer(int portIndex) {
- const Vector<BufferInfo> &buffers = mPortBuffers[portIndex];
- for (size_t i = 0; i < buffers.size(); ++i) {
- const BufferInfo &info = buffers.itemAt(i);
- if (info.mOwnedByClient) {
- return true;
- }
- }
- return false;
+ return std::any_of(
+ mPortBuffers[portIndex].begin(), mPortBuffers[portIndex].end(),
+ [](const BufferInfo &info) { return info.mOwnedByClient; });
}
bool MediaCodec::hasPendingBuffer() {
@@ -1114,14 +1126,14 @@
// we also don't want mOwnedByClient to change during this
Mutex::Autolock al(mBufferLock);
- Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
- if (index >= buffers->size()) {
+ std::vector<BufferInfo> &buffers = mPortBuffers[portIndex];
+ if (index >= buffers.size()) {
ALOGE("getBufferAndFormat - trying to get buffer with "
- "bad index (index=%zu buffer_size=%zu)", index, buffers->size());
+ "bad index (index=%zu buffer_size=%zu)", index, buffers.size());
return INVALID_OPERATION;
}
- const BufferInfo &info = buffers->itemAt(index);
+ const BufferInfo &info = buffers[index];
if (!info.mOwnedByClient) {
ALOGE("getBufferAndFormat - invalid operation "
"(the index %zu is not owned by client)", index);
@@ -1219,7 +1231,7 @@
}
const sp<MediaCodecBuffer> &buffer =
- mPortBuffers[kPortIndexOutput].itemAt(index).mData;
+ mPortBuffers[kPortIndexOutput][index].mData;
response->setSize("index", index);
response->setSize("offset", buffer->offset());
@@ -1230,19 +1242,8 @@
response->setInt64("timeUs", timeUs);
- int32_t omxFlags;
- CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
-
- uint32_t flags = 0;
- if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
- flags |= BUFFER_FLAG_SYNCFRAME;
- }
- if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
- flags |= BUFFER_FLAG_CODECCONFIG;
- }
- if (omxFlags & OMX_BUFFERFLAG_EOS) {
- flags |= BUFFER_FLAG_EOS;
- }
+ int32_t flags;
+ CHECK(buffer->meta()->findInt32("flags", &flags));
response->setInt32("flags", flags);
response->postReply(replyID);
@@ -1507,75 +1508,24 @@
break;
}
-
- case kWhatBuffersAllocated:
+ case kWhatStartCompleted:
{
- Mutex::Autolock al(mBufferLock);
- int32_t portIndex;
- CHECK(msg->findInt32("portIndex", &portIndex));
-
- ALOGV("%s buffers allocated",
- portIndex == kPortIndexInput ? "input" : "output");
-
- CHECK(portIndex == kPortIndexInput
- || portIndex == kPortIndexOutput);
-
- mPortBuffers[portIndex].clear();
- mPortBufferArrays[portIndex].clear();
-
- Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
-
- sp<RefBase> obj;
- CHECK(msg->findObject("portDesc", &obj));
-
- sp<CodecBase::PortDescription> portDesc =
- static_cast<CodecBase::PortDescription *>(obj.get());
-
- size_t numBuffers = portDesc->countBuffers();
-
- size_t totalSize = 0;
- for (size_t i = 0; i < numBuffers; ++i) {
- if (portIndex == kPortIndexInput && mCrypto != NULL) {
- totalSize += portDesc->bufferAt(i)->capacity();
- }
+ CHECK_EQ(mState, STARTING);
+ if (mIsVideo) {
+ addResource(
+ MediaResource::kGraphicMemory,
+ MediaResource::kUnspecifiedSubType,
+ getGraphicBufferSize());
}
+ setState(STARTED);
+ (new AMessage)->postReply(mReplyID);
+ break;
+ }
- if (totalSize) {
- mDealer = new MemoryDealer(totalSize, "MediaCodec");
- }
-
- for (size_t i = 0; i < numBuffers; ++i) {
- BufferInfo info;
- info.mBufferID = portDesc->bufferIDAt(i);
- info.mOwnedByClient = false;
- sp<MediaCodecBuffer> buffer = portDesc->bufferAt(i);
- if (portIndex == kPortIndexInput && mCrypto != NULL) {
- info.mSharedEncryptedBuffer = mDealer->allocate(buffer->capacity());
- buffer = new SharedMemoryBuffer(
- mInputFormat, info.mSharedEncryptedBuffer);
- }
- buffers->push_back(info);
- mPortBufferArrays[portIndex].push_back(buffer);
- }
-
- if (portIndex == kPortIndexOutput) {
- if (mState == STARTING) {
- // We're always allocating output buffers after
- // allocating input buffers, so this is a good
- // indication that now all buffers are allocated.
- if (mIsVideo) {
- addResource(
- MediaResource::kGraphicMemory,
- MediaResource::kUnspecifiedSubType,
- getGraphicBufferSize());
- }
- setState(STARTED);
- (new AMessage)->postReply(mReplyID);
- } else {
- mFlags |= kFlagOutputBuffersChanged;
- postActivityNotificationIfPossible();
- }
- }
+ case kWhatOutputBuffersChanged:
+ {
+ mFlags |= kFlagOutputBuffersChanged;
+ postActivityNotificationIfPossible();
break;
}
@@ -1602,9 +1552,6 @@
break;
}
- // TODO: hold reference of buffer from downstream when
- // mPortBuffers is removed.
-
if (!mCSD.empty()) {
ssize_t index = dequeuePortBuffer(kPortIndexInput);
CHECK_GE(index, 0);
@@ -1663,12 +1610,7 @@
sp<RefBase> obj;
CHECK(msg->findObject("buffer", &obj));
sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
- // TODO: hold buffer's reference when we remove mPortBuffers
- int32_t omxFlags;
- CHECK(msg->findInt32("flags", &omxFlags));
-
- buffer->meta()->setInt32("omxFlags", omxFlags);
if (mOutputFormat != buffer->format()) {
mOutputFormat = buffer->format();
ALOGV("[%s] output format changed to: %s",
@@ -1701,7 +1643,9 @@
// Before we announce the format change we should
// collect codec specific data and amend the output
// format as necessary.
- if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
+ int32_t flags = 0;
+ (void) buffer->meta()->findInt32("flags", &flags);
+ if (flags & BUFFER_FLAG_CODECCONFIG) {
status_t err =
amendOutputFormatWithCodecSpecificData(buffer);
@@ -1924,6 +1868,7 @@
}
mCrypto = static_cast<ICrypto *>(crypto);
+ mBufferChannel->setCrypto(mCrypto);
uint32_t flags;
CHECK(msg->findInt32("flags", (int32_t *)&flags));
@@ -2351,10 +2296,10 @@
// createInputSurface(), or persistent set by setInputSurface()),
// give the client an empty input buffers array.
if (portIndex != kPortIndexInput || !mHaveInputSurface) {
- const Vector<sp<MediaCodecBuffer>> &srcBuffers = mPortBufferArrays[portIndex];
-
- for (size_t i = 0; i < srcBuffers.size(); ++i) {
- dstBuffers->push_back(srcBuffers[i]);
+ if (portIndex == kPortIndexInput) {
+ mBufferChannel->getInputBufferArray(dstBuffers);
+ } else {
+ mBufferChannel->getOutputBufferArray(dstBuffers);
}
}
@@ -2483,13 +2428,12 @@
status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) {
CHECK(!mCSD.empty());
- const BufferInfo *info =
- &mPortBuffers[kPortIndexInput].itemAt(bufferIndex);
+ const BufferInfo &info = mPortBuffers[kPortIndexInput][bufferIndex];
sp<ABuffer> csd = *mCSD.begin();
mCSD.erase(mCSD.begin());
- const sp<MediaCodecBuffer> &codecInputData = info->mData;
+ const sp<MediaCodecBuffer> &codecInputData = info.mData;
if (csd->size() > codecInputData->capacity()) {
return -EINVAL;
@@ -2557,31 +2501,19 @@
CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
Mutex::Autolock al(mBufferLock);
- Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
+ for (size_t i = 0; i < mPortBuffers[portIndex].size(); ++i) {
+ BufferInfo *info = &mPortBuffers[portIndex][i];
- for (size_t i = 0; i < buffers->size(); ++i) {
- BufferInfo *info = &buffers->editItemAt(i);
-
- if (info->mNotify != NULL) {
- sp<AMessage> msg = info->mNotify;
- msg->setObject("buffer", (info->mSecureData != nullptr)
- ? info->mSecureData : info->mData);
- msg->setInt32("discarded", true);
- info->mNotify = NULL;
+ if (info->mData != nullptr) {
+ sp<MediaCodecBuffer> buffer = info->mData;
if (isReclaim && info->mOwnedByClient) {
ALOGD("port %d buffer %zu still owned by client when codec is reclaimed",
portIndex, i);
} else {
info->mOwnedByClient = false;
info->mData.clear();
- info->mSecureData.clear();
}
-
- if (portIndex == kPortIndexInput) {
- /* no error, just returning buffers */
- msg->setInt32("err", OK);
- }
- msg->post();
+ mBufferChannel->discardBuffer(buffer);
}
}
@@ -2591,37 +2523,22 @@
size_t MediaCodec::updateBuffers(
int32_t portIndex, const sp<AMessage> &msg) {
CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
-
- uint32_t bufferID;
- CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
+ size_t index;
+ CHECK(msg->findSize("index", &index));
sp<RefBase> obj;
CHECK(msg->findObject("buffer", &obj));
sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
- Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
-
- for (size_t i = 0; i < buffers->size(); ++i) {
- BufferInfo *info = &buffers->editItemAt(i);
-
- if (info->mBufferID == bufferID) {
- CHECK(info->mNotify == NULL);
- CHECK(msg->findMessage("reply", &info->mNotify));
-
- if (portIndex == kPortIndexInput && mCrypto != NULL) {
- info->mSecureData = buffer;
- info->mData = mPortBufferArrays[portIndex][i];
- } else {
- info->mData = buffer;
- }
- mAvailPortBuffers[portIndex].push_back(i);
-
- return i;
+ {
+ Mutex::Autolock al(mBufferLock);
+ if (mPortBuffers[portIndex].size() <= index) {
+ mPortBuffers[portIndex].resize(align(index + 1, kNumBuffersAlign));
}
+ mPortBuffers[portIndex][index].mData = buffer;
}
+ mAvailPortBuffers[portIndex].push_back(index);
- TRESPASS();
-
- return 0;
+ return index;
}
status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
@@ -2686,9 +2603,9 @@
return -ERANGE;
}
- BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index);
+ BufferInfo *info = &mPortBuffers[kPortIndexInput][index];
- if (info->mNotify == NULL || !info->mOwnedByClient) {
+ if (info->mData == nullptr || !info->mOwnedByClient) {
return -EACCES;
}
@@ -2696,69 +2613,44 @@
return -EINVAL;
}
- sp<AMessage> reply = info->mNotify;
info->mData->setRange(offset, size);
+ info->mData->meta()->setInt64("timeUs", timeUs);
+ if (flags & BUFFER_FLAG_EOS) {
+ info->mData->meta()->setInt32("eos", true);
+ }
+
+ if (flags & BUFFER_FLAG_CODECCONFIG) {
+ info->mData->meta()->setInt32("csd", true);
+ }
sp<MediaCodecBuffer> buffer = info->mData;
+ status_t err = OK;
if (mCrypto != NULL) {
AString *errorDetailMsg;
CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
- void *dst_pointer = nullptr;
- ICrypto::DestinationType dst_type = ICrypto::kDestinationTypeOpaqueHandle;
-
- if ((mFlags & kFlagIsSecure) == 0) {
- dst_pointer = info->mSecureData->base();
- dst_type = ICrypto::kDestinationTypeVmPointer;
- } else {
- sp<SecureBuffer> secureData = static_cast<SecureBuffer *>(info->mSecureData.get());
- dst_pointer = secureData->getDestinationPointer();
- dst_type = secureData->getDestinationType();
- }
-
- ssize_t result = mCrypto->decrypt(
- dst_type,
+ err = mBufferChannel->queueSecureInputBuffer(
+ buffer,
+ (mFlags & kFlagIsSecure),
key,
iv,
mode,
pattern,
- info->mSharedEncryptedBuffer,
- offset,
subSamples,
numSubSamples,
- dst_pointer,
errorDetailMsg);
-
- if (result < 0) {
- return result;
- }
-
- info->mSecureData->setRange(0, result);
- buffer = info->mSecureData;
- }
- buffer->meta()->setInt64("timeUs", timeUs);
-
- if (flags & BUFFER_FLAG_EOS) {
- buffer->meta()->setInt32("eos", true);
+ } else {
+ err = mBufferChannel->queueInputBuffer(buffer);
}
- if (flags & BUFFER_FLAG_CODECCONFIG) {
- buffer->meta()->setInt32("csd", true);
- }
-
- // synchronization boundary for getBufferAndFormat
- {
+ if (err == OK) {
+ // synchronization boundary for getBufferAndFormat
Mutex::Autolock al(mBufferLock);
info->mOwnedByClient = false;
+ info->mData.clear();
}
- info->mData.clear();
- info->mSecureData.clear();
- reply->setObject("buffer", buffer);
- reply->post();
- info->mNotify = NULL;
-
- return OK;
+ return err;
}
//static
@@ -2795,23 +2687,24 @@
return -ERANGE;
}
- BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
+ BufferInfo *info = &mPortBuffers[kPortIndexOutput][index];
- if (info->mNotify == NULL || !info->mOwnedByClient) {
+ if (info->mData == nullptr || !info->mOwnedByClient) {
return -EACCES;
}
// synchronization boundary for getBufferAndFormat
+ sp<MediaCodecBuffer> buffer;
{
Mutex::Autolock al(mBufferLock);
info->mOwnedByClient = false;
+ buffer = info->mData;
+ info->mData.clear();
}
- if (render && info->mData != NULL && info->mData->size() != 0) {
- info->mNotify->setInt32("render", true);
-
+ if (render && buffer->size() != 0) {
int64_t mediaTimeUs = -1;
- info->mData->meta()->findInt64("timeUs", &mediaTimeUs);
+ buffer->meta()->findInt64("timeUs", &mediaTimeUs);
int64_t renderTimeNs = 0;
if (!msg->findInt64("timestampNs", &renderTimeNs)) {
@@ -2819,12 +2712,11 @@
ALOGV("using buffer PTS of %lld", (long long)mediaTimeUs);
renderTimeNs = mediaTimeUs * 1000;
}
- info->mNotify->setInt64("timestampNs", renderTimeNs);
if (mSoftRenderer != NULL) {
std::list<FrameRenderTracker::Info> doneFrames = mSoftRenderer->render(
- info->mData->data(), info->mData->size(),
- mediaTimeUs, renderTimeNs, NULL, info->mData->format());
+ buffer->data(), buffer->size(),
+ mediaTimeUs, renderTimeNs, NULL, buffer->format());
// if we are running, notify rendered frames
if (!doneFrames.empty() && mState == STARTED && mOnFrameRenderedNotification != NULL) {
@@ -2836,13 +2728,11 @@
}
}
}
+ mBufferChannel->renderOutputBuffer(buffer, renderTimeNs);
+ } else {
+ mBufferChannel->discardBuffer(buffer);
}
- info->mNotify->setObject("buffer", info->mData);
- info->mData.clear();
- info->mNotify->post();
- info->mNotify.clear();
-
return OK;
}
@@ -2858,7 +2748,7 @@
size_t index = *availBuffers->begin();
availBuffers->erase(availBuffers->begin());
- BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index);
+ BufferInfo *info = &mPortBuffers[portIndex][index];
CHECK(!info->mOwnedByClient);
{
Mutex::Autolock al(mBufferLock);
@@ -2962,7 +2852,7 @@
int32_t index;
while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) {
const sp<MediaCodecBuffer> &buffer =
- mPortBuffers[kPortIndexOutput].itemAt(index).mData;
+ mPortBuffers[kPortIndexOutput][index].mData;
sp<AMessage> msg = mCallback->dup();
msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE);
msg->setInt32("index", index);
@@ -2974,19 +2864,8 @@
msg->setInt64("timeUs", timeUs);
- int32_t omxFlags;
- CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
-
- uint32_t flags = 0;
- if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
- flags |= BUFFER_FLAG_SYNCFRAME;
- }
- if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
- flags |= BUFFER_FLAG_CODECCONFIG;
- }
- if (omxFlags & OMX_BUFFERFLAG_EOS) {
- flags |= BUFFER_FLAG_EOS;
- }
+ int32_t flags;
+ CHECK(buffer->meta()->findInt32("flags", &flags));
msg->setInt32("flags", flags);
@@ -3018,7 +2897,6 @@
}
}
-
void MediaCodec::postActivityNotificationIfPossible() {
if (mActivityNotify == NULL) {
return;
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index de4d06f..5981b35 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -689,7 +689,9 @@
sp<MediaCodecBuffer> inbuf;
status_t err = mEncoder->getInputBuffer(bufferIndex, &inbuf);
- if (err != OK || inbuf == NULL) {
+
+ if (err != OK || inbuf == NULL || inbuf->data() == NULL
+ || mbuf->data() == NULL || mbuf->size() == 0) {
mbuf->release();
signalEOS();
break;
@@ -851,7 +853,8 @@
sp<MediaCodecBuffer> outbuf;
status_t err = mEncoder->getOutputBuffer(index, &outbuf);
- if (err != OK || outbuf == NULL) {
+ if (err != OK || outbuf == NULL || outbuf->data() == NULL
+ || outbuf->size() == 0) {
signalEOS();
break;
}
diff --git a/media/libstagefright/codecs/amrnb/dec/src/a_refl.cpp b/media/libstagefright/codecs/amrnb/dec/src/a_refl.cpp
index 9d9cd3b..5a47510 100644
--- a/media/libstagefright/codecs/amrnb/dec/src/a_refl.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/src/a_refl.cpp
@@ -60,7 +60,7 @@
; INCLUDES
----------------------------------------------------------------------------*/
#define LOG_TAG "a_refl"
-#include <android/log.h>
+#include <log/log.h>
#include "a_refl.h"
#include "typedef.h"
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/conceal.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/conceal.cpp
index 5baa2a2..8393d79 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/conceal.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/conceal.cpp
@@ -18,7 +18,7 @@
#define LOG_TAG "conceal"
-#include "android/log.h"
+#include "log/log.h"
#include "mp4dec_lib.h" /* video decoder function prototypes */
#include "vlc_decode.h"
diff --git a/media/libstagefright/filters/MediaFilter.cpp b/media/libstagefright/filters/MediaFilter.cpp
index 7290193..777ab5b 100644
--- a/media/libstagefright/filters/MediaFilter.cpp
+++ b/media/libstagefright/filters/MediaFilter.cpp
@@ -42,6 +42,7 @@
#include "SaturationFilter.h"
#include "ZeroFilter.h"
+#include "../include/ACodecBufferChannel.h"
#include "../include/SharedMemoryBuffer.h"
namespace android {
@@ -53,6 +54,9 @@
: mState(UNINITIALIZED),
mGeneration(0),
mGraphicBufferListener(NULL) {
+ mBufferChannel = std::make_shared<ACodecBufferChannel>(
+ new AMessage(kWhatInputBufferFilled, this),
+ new AMessage(kWhatOutputBufferDrained, this));
}
MediaFilter::~MediaFilter() {
@@ -60,6 +64,10 @@
//////////////////// PUBLIC FUNCTIONS //////////////////////////////////////////
+std::shared_ptr<BufferChannelBase> MediaFilter::getBufferChannel() {
+ return mBufferChannel;
+}
+
void MediaFilter::initiateAllocateComponent(const sp<AMessage> &msg) {
msg->setWhat(kWhatAllocateComponent);
msg->setTarget(this);
@@ -189,29 +197,6 @@
}
}
-//////////////////// PORT DESCRIPTION //////////////////////////////////////////
-
-MediaFilter::PortDescription::PortDescription() {
-}
-
-void MediaFilter::PortDescription::addBuffer(
- IOMX::buffer_id id, const sp<MediaCodecBuffer> &buffer) {
- mBufferIDs.push_back(id);
- mBuffers.push_back(buffer);
-}
-
-size_t MediaFilter::PortDescription::countBuffers() {
- return mBufferIDs.size();
-}
-
-IOMX::buffer_id MediaFilter::PortDescription::bufferIDAt(size_t index) const {
- return mBufferIDs.itemAt(index);
-}
-
-sp<MediaCodecBuffer> MediaFilter::PortDescription::bufferAt(size_t index) const {
- return mBuffers.itemAt(index);
-}
-
//////////////////// HELPER FUNCTIONS //////////////////////////////////////////
void MediaFilter::signalProcessBuffers() {
@@ -259,14 +244,15 @@
}
}
- sp<PortDescription> desc = new PortDescription;
-
+ std::vector<ACodecBufferChannel::BufferAndId> array(mBuffers[portIndex].size());
for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
- const BufferInfo &info = mBuffers[portIndex][i];
-
- desc->addBuffer(info.mBufferID, info.mData);
+ array[i] = {mBuffers[portIndex][i].mData, mBuffers[portIndex][i].mBufferID};
}
- mCallback->onBuffersAllocated(portIndex, desc);
+ if (portIndex == kPortIndexInput) {
+ mBufferChannel->setInputBufferArray(array);
+ } else {
+ mBufferChannel->setOutputBufferArray(array);
+ }
return OK;
}
@@ -307,7 +293,7 @@
info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
- mCallback->fillThisBuffer(info->mBufferID, info->mData, reply);
+ mBufferChannel->fillThisBuffer(info->mBufferID);
}
void MediaFilter::postDrainThisBuffer(BufferInfo *info) {
@@ -318,8 +304,7 @@
sp<AMessage> reply = new AMessage(kWhatOutputBufferDrained, this);
reply->setInt32("buffer-id", info->mBufferID);
- mCallback->drainThisBuffer(
- info->mBufferID, info->mData, info->mOutputFlags, reply);
+ mBufferChannel->drainThisBuffer(info->mBufferID, info->mOutputFlags);
info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
}
@@ -505,6 +490,8 @@
allocateBuffersOnPort(kPortIndexOutput);
+ mCallback->onStartCompleted();
+
status_t err = mFilter->start();
if (err != (status_t)OK) {
ALOGE("Failed to start filter component, err %d", err);
diff --git a/media/libstagefright/include/ACodecBufferChannel.h b/media/libstagefright/include/ACodecBufferChannel.h
new file mode 100644
index 0000000..d52ce53
--- /dev/null
+++ b/media/libstagefright/include/ACodecBufferChannel.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright 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 A_BUFFER_CHANNEL_H_
+
+#define A_BUFFER_CHANNEL_H_
+
+#include <map>
+#include <memory>
+#include <mutex>
+#include <vector>
+
+#include <media/openmax/OMX_Types.h>
+#include <media/stagefright/CodecBase.h>
+#include <media/ICrypto.h>
+#include <media/IOMX.h>
+
+namespace android {
+
+/**
+ * BufferChannelBase implementation for ACodec.
+ */
+class ACodecBufferChannel : public BufferChannelBase {
+public:
+ struct BufferAndId {
+ sp<MediaCodecBuffer> mBuffer;
+ IOMX::buffer_id mBufferId;
+ };
+
+ struct BufferInfo {
+ BufferInfo(
+ const sp<MediaCodecBuffer> &buffer,
+ IOMX::buffer_id bufferId,
+ const sp<IMemory> &sharedEncryptedBuffer);
+
+ BufferInfo() = delete;
+
+ // Buffer facing MediaCodec and its clients.
+ const sp<MediaCodecBuffer> mClientBuffer;
+ // Buffer facing CodecBase.
+ const sp<MediaCodecBuffer> mCodecBuffer;
+ // OMX buffer ID.
+ const IOMX::buffer_id mBufferId;
+ // Encrypted buffer in case of secure input.
+ const sp<IMemory> mSharedEncryptedBuffer;
+ };
+
+ ACodecBufferChannel(
+ const sp<AMessage> &inputBufferFilled, const sp<AMessage> &outputBufferDrained);
+ virtual ~ACodecBufferChannel() = default;
+
+ // BufferChannelBase interface
+ virtual status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) override;
+ virtual status_t queueSecureInputBuffer(
+ const sp<MediaCodecBuffer> &buffer,
+ bool secure,
+ const uint8_t *key,
+ const uint8_t *iv,
+ CryptoPlugin::Mode mode,
+ CryptoPlugin::Pattern pattern,
+ const CryptoPlugin::SubSample *subSamples,
+ size_t numSubSamples,
+ AString *errorDetailMsg) override;
+ virtual status_t renderOutputBuffer(
+ const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) override;
+ virtual status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override;
+ virtual void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
+ virtual void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
+
+ // Methods below are interface for ACodec to use.
+
+ /**
+ * Set input buffer array.
+ *
+ * @param array Newly allocated buffers. Empty if buffers are
+ * deallocated.
+ */
+ void setInputBufferArray(const std::vector<BufferAndId> &array);
+ /**
+ * Set output buffer array.
+ *
+ * @param array Newly allocated buffers. Empty if buffers are
+ * deallocated.
+ */
+ void setOutputBufferArray(const std::vector<BufferAndId> &array);
+ /**
+ * Request MediaCodec to fill the specified input buffer.
+ *
+ * @param bufferId ID of the buffer, assigned by underlying component.
+ */
+ void fillThisBuffer(IOMX::buffer_id bufferID);
+ /**
+ * Request MediaCodec to drain the specified output buffer.
+ *
+ * @param bufferId ID of the buffer, assigned by underlying component.
+ * @param omxFlags flags associated with this buffer (e.g. EOS).
+ */
+ void drainThisBuffer(IOMX::buffer_id bufferID, OMX_U32 omxFlags);
+
+private:
+ const sp<AMessage> mInputBufferFilled;
+ const sp<AMessage> mOutputBufferDrained;
+
+ sp<MemoryDealer> mDealer;
+
+ // These should only be accessed via std::atomic_* functions.
+ //
+ // Note on thread safety: since the vector and BufferInfo are const, it's
+ // safe to read them at any thread once the shared_ptr object is atomically
+ // obtained. Inside BufferInfo, mBufferId and mSharedEncryptedBuffer are
+ // immutable objects. We write internal states of mClient/CodecBuffer when
+ // the caller has given up the reference, so that access is also safe.
+ std::shared_ptr<const std::vector<const BufferInfo>> mInputBuffers;
+ std::shared_ptr<const std::vector<const BufferInfo>> mOutputBuffers;
+};
+
+} // namespace android
+
+#endif // A_BUFFER_CHANNEL_H_
diff --git a/media/libstagefright/omx/hal/1.0/Conversion.h b/media/libstagefright/omx/hal/1.0/Conversion.h
index 44d2c84..d42e5bf 100644
--- a/media/libstagefright/omx/hal/1.0/Conversion.h
+++ b/media/libstagefright/omx/hal/1.0/Conversion.h
@@ -2,7 +2,6 @@
#define ANDROID_HARDWARE_MEDIA_OMX_V1_0__CONVERSION_H
#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
#include <unistd.h>
#include <vector>
@@ -147,13 +146,13 @@
*/
/**
- * \brief Convert `binder::Status` to `hardware::Status`.
+ * \brief Convert `binder::Status` to `Return<void>`.
*
* \param[in] l The source `binder::Status`.
- * \return The corresponding `hardware::Status`.
+ * \return The corresponding `Return<void>`.
*/
-// convert: ::android::binder::Status -> ::android::hardware::Status
-inline ::android::hardware::Status toHardwareStatus(
+// convert: ::android::binder::Status -> Return<void>
+inline Return<void> toHardwareStatus(
::android::binder::Status const& l) {
if (l.exceptionCode() == ::android::binder::Status::EX_SERVICE_SPECIFIC) {
return ::android::hardware::Status::fromServiceSpecificError(
@@ -166,36 +165,17 @@
}
/**
- * \brief Convert `hardware::Status` to `binder::Status`.
+ * \brief Convert `Return<void>` to `binder::Status`.
*
- * \param[in] t The source `hardware::Status`.
+ * \param[in] t The source `Return<void>`.
* \return The corresponding `binder::Status`.
*/
-// convert: ::android::hardware::Status -> ::android::binder::Status
+// convert: Return<void> -> ::android::binder::Status
inline ::android::binder::Status toBinderStatus(
- ::android::hardware::Status const& t) {
- if (t.exceptionCode() == ::android::hardware::Status::EX_SERVICE_SPECIFIC) {
- return ::android::binder::Status::fromServiceSpecificError(
- t.serviceSpecificErrorCode(),
- t.exceptionMessage());
- }
+ Return<void> const& t) {
return ::android::binder::Status::fromExceptionCode(
- t.exceptionCode(),
- t.exceptionMessage());
-}
-
-/**
- * \brief Convert `hardware::Return<void>` to `binder::Status`.
- *
- * \param[in] t The source `hardware::Return<void>`.
- * \return The corresponding `binder::Status`.
- *
- * This function simply calls `toBinderStatus(::android::hardware::Status
- * const&)`.
- */
-// convert: ::android::hardware::Return<void> -> ::android::binder::Status
-inline ::android::binder::Status toBinderStatus(Return<void> const& t) {
- return toBinderStatus(t.getStatus());
+ t.isOk() ? OK : UNKNOWN_ERROR,
+ t.description().c_str());
}
/**
@@ -215,8 +195,7 @@
*/
// convert: Status -> status_t
inline status_t toStatusT(Return<Status> const& t) {
- return t.isOk() ? static_cast<status_t>(static_cast<Status>(t)) :
- t.getStatus().transactionError();
+ return t.isOk() ? static_cast<status_t>(static_cast<Status>(t)) : UNKNOWN_ERROR;
}
/**
@@ -227,7 +206,7 @@
*/
// convert: Return<void> -> status_t
inline status_t toStatusT(Return<void> const& t) {
- return t.getStatus().transactionError();
+ return t.isOk() ? OK : UNKNOWN_ERROR;
}
/**
diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp
index 10314e9..d11a10d 100644
--- a/media/mtp/MtpFfsHandle.cpp
+++ b/media/mtp/MtpFfsHandle.cpp
@@ -38,6 +38,8 @@
#define cpu_to_le16(x) htole16(x)
#define cpu_to_le32(x) htole32(x)
+#define FUNCTIONFS_ENDPOINT_ALLOC _IOR('g', 131, __u32)
+
namespace {
constexpr char FFS_MTP_EP_IN[] = "/dev/usb-ffs/mtp/ep1";
@@ -467,6 +469,24 @@
mLock.unlock();
}
+class ScopedEndpointBufferAlloc {
+private:
+ const int mFd;
+ const unsigned int mAllocSize;
+public:
+ ScopedEndpointBufferAlloc(int fd, unsigned alloc_size) :
+ mFd(fd),
+ mAllocSize(alloc_size) {
+ if (ioctl(mFd, FUNCTIONFS_ENDPOINT_ALLOC, static_cast<__u32>(mAllocSize)))
+ PLOG(DEBUG) << "FFS endpoint alloc failed!";
+ }
+
+ ~ScopedEndpointBufferAlloc() {
+ if (ioctl(mFd, FUNCTIONFS_ENDPOINT_ALLOC, static_cast<__u32>(0)))
+ PLOG(DEBUG) << "FFS endpoint alloc reset failed!";
+ }
+};
+
/* Read from USB and write to a local file. */
int MtpFfsHandle::receiveFile(mtp_file_range mfr) {
// When receiving files, the incoming length is given in 32 bits.
@@ -494,6 +514,7 @@
bool write = false;
posix_fadvise(mfr.fd, 0, 0, POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE);
+ ScopedEndpointBufferAlloc(mBulkOut, mMaxRead);
// Break down the file into pieces that fit in buffers
while (file_length > 0 || write) {
@@ -609,6 +630,8 @@
if (writeHandle(mBulkIn, data, packet_size) == -1) return -1;
if (file_length == 0) return 0;
+ ScopedEndpointBufferAlloc(mBulkIn, mMaxWrite);
+
// Break down the file into pieces that fit in buffers
while(file_length > 0) {
if (read) {
diff --git a/radio/IRadio.cpp b/radio/IRadio.cpp
index ebf3859..5bbe7cb 100644
--- a/radio/IRadio.cpp
+++ b/radio/IRadio.cpp
@@ -172,16 +172,11 @@
virtual status_t getProgramInformation(struct radio_program_info *info)
{
Parcel data, reply;
- if (info == NULL) {
+ if (info == nullptr || info->metadata == nullptr) {
return BAD_VALUE;
}
radio_metadata_t *metadata = info->metadata;
data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
- if (metadata != NULL) {
- data.writeUint32(1);
- } else {
- data.writeUint32(0);
- }
status_t status = remote()->transact(GET_PROGRAM_INFORMATION, data, &reply);
if (status == NO_ERROR) {
status = (status_t)reply.readInt32();
@@ -190,13 +185,13 @@
// restore local metadata pointer
info->metadata = metadata;
- uint32_t metatataSize = reply.readUint32();
- if ((metadata != NULL) && (metatataSize != 0)) {
- radio_metadata_t *newMetadata = (radio_metadata_t *)malloc(metatataSize);
+ uint32_t metadataSize = reply.readUint32();
+ if (metadataSize != 0) {
+ radio_metadata_t *newMetadata = (radio_metadata_t *)malloc(metadataSize);
if (newMetadata == NULL) {
return NO_MEMORY;
}
- reply.read(newMetadata, metatataSize);
+ reply.read(newMetadata, metadataSize);
status = radio_metadata_add_metadata(&info->metadata, newMetadata);
free(newMetadata);
}
@@ -306,21 +301,17 @@
CHECK_INTERFACE(IRadio, data, reply);
struct radio_program_info info;
status_t status;
- // query metadata only if requested by remote side
- if (data.readUint32() == 1) {
- status = radio_metadata_allocate(&info.metadata, 0, 0);
- if (status != NO_ERROR) {
- return status;
- }
- } else {
- info.metadata = NULL;
+
+ status = radio_metadata_allocate(&info.metadata, 0, 0);
+ if (status != NO_ERROR) {
+ return status;
}
status = getProgramInformation(&info);
reply->writeInt32(status);
if (status == NO_ERROR) {
reply->write(&info, sizeof(struct radio_program_info));
- if ((info.metadata != NULL) && (radio_metadata_get_count(info.metadata) > 0)) {
+ if (radio_metadata_get_count(info.metadata) > 0) {
size_t size = radio_metadata_get_size(info.metadata);
reply->writeUint32((uint32_t)size);
reply->write(info.metadata, size);
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 51d785a..aa2cd95 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -28,8 +28,6 @@
AudioStreamOut.cpp \
SpdifStreamOut.cpp \
Effects.cpp \
- AudioMixer.cpp.arm \
- BufferProviders.cpp \
PatchPanel.cpp \
StateQueue.cpp \
BufLog.cpp
@@ -37,12 +35,11 @@
LOCAL_C_INCLUDES := \
$(TOPDIR)frameworks/av/services/audiopolicy \
$(TOPDIR)frameworks/av/services/medialog \
- $(TOPDIR)external/sonic \
$(call include-path-for, audio-utils)
LOCAL_SHARED_LIBRARIES := \
libaudiohal \
- libaudioresampler \
+ libaudioprocessing \
libaudiospdif \
libaudioutils \
libcutils \
@@ -55,7 +52,6 @@
libnbaio \
libpowermanager \
libserviceutility \
- libsonic \
libmediautils \
libmemunreachable \
libmedia_helper
@@ -87,59 +83,4 @@
include $(BUILD_SHARED_LIBRARY)
-#
-# build audio resampler test tool
-#
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- test-resample.cpp \
-
-LOCAL_C_INCLUDES := \
- $(call include-path-for, audio-utils)
-
-LOCAL_STATIC_LIBRARIES := \
- libsndfile
-
-LOCAL_SHARED_LIBRARIES := \
- libaudioresampler \
- libaudioutils \
- libdl \
- libcutils \
- libutils \
- liblog
-
-LOCAL_MODULE:= test-resample
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CFLAGS := -Werror -Wall
-
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- AudioResampler.cpp.arm \
- AudioResamplerCubic.cpp.arm \
- AudioResamplerSinc.cpp.arm \
- AudioResamplerDyn.cpp.arm
-
-LOCAL_C_INCLUDES := \
- $(call include-path-for, audio-utils)
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libdl \
- liblog
-
-LOCAL_MODULE := libaudioresampler
-
-LOCAL_CFLAGS := -Werror -Wall
-
-# uncomment to disable NEON on architectures that actually do support NEON, for benchmarking
-#LOCAL_CFLAGS += -DUSE_NEON=false
-
-include $(BUILD_SHARED_LIBRARY)
-
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index e4b73c6..a248912 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -46,7 +46,6 @@
#include <system/audio.h>
-#include "AudioMixer.h"
#include "AudioFlinger.h"
#include "ServiceUtilities.h"
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index d18ca47..35eceb2 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -48,19 +48,20 @@
#include <system/audio.h>
#include <system/audio_policy.h>
+#include <media/audiohal/EffectBufferHalInterface.h>
#include <media/audiohal/StreamHalInterface.h>
#include <media/AudioBufferProvider.h>
+#include <media/AudioMixer.h>
#include <media/ExtendedAudioBufferProvider.h>
+#include <media/LinearMap.h>
#include "FastCapture.h"
#include "FastMixer.h"
#include <media/nbaio/NBAIO.h>
#include "AudioWatchdog.h"
-#include "AudioMixer.h"
#include "AudioStreamOut.h"
#include "SpdifStreamOut.h"
#include "AudioHwDevice.h"
-#include "LinearMap.h"
#include <powermanager/IPowerManager.h>
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 6c937a5..343ad25 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -188,6 +188,7 @@
// this object is released which can happen after next process is called.
if (mHandles.size() == 0 && !mPinned) {
mState = DESTROYED;
+ mEffectInterface->close();
}
return mHandles.size();
@@ -275,9 +276,7 @@
{
Mutex::Autolock _l(mLock);
- if (mState == DESTROYED || mEffectInterface == 0 ||
- mConfig.inputCfg.buffer.raw == NULL ||
- mConfig.outputCfg.buffer.raw == NULL) {
+ if (mState == DESTROYED || mEffectInterface == 0 || mInBuffer == 0 || mOutBuffer == 0) {
return;
}
@@ -291,7 +290,7 @@
int ret;
if (isProcessImplemented()) {
// do the actual processing in the effect engine
- ret = mEffectInterface->process(&mConfig.inputCfg.buffer, &mConfig.outputCfg.buffer);
+ ret = mEffectInterface->process();
} else {
if (mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
size_t frameCnt = mConfig.inputCfg.buffer.frameCount * FCC_2; //always stereo here
@@ -409,6 +408,12 @@
mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
mConfig.inputCfg.buffer.frameCount = thread->frameCount();
mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
+ if (mInBuffer != 0) {
+ mInBuffer->setFrameCount(mConfig.inputCfg.buffer.frameCount);
+ }
+ if (mOutBuffer != 0) {
+ mOutBuffer->setFrameCount(mConfig.outputCfg.buffer.frameCount);
+ }
ALOGV("configure() %p thread %p buffer %p framecount %zu",
this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
@@ -568,6 +573,7 @@
if (mEffectInterface != 0) {
remove_effect_from_hal_l();
// release effect engine
+ mEffectInterface->close();
mEffectInterface.clear();
}
}
@@ -762,6 +768,28 @@
}
}
+void AudioFlinger::EffectModule::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
+ if (buffer != 0) {
+ mConfig.inputCfg.buffer.raw = buffer->audioBuffer()->raw;
+ buffer->setFrameCount(mConfig.inputCfg.buffer.frameCount);
+ } else {
+ mConfig.inputCfg.buffer.raw = NULL;
+ }
+ mInBuffer = buffer;
+ mEffectInterface->setInBuffer(buffer);
+}
+
+void AudioFlinger::EffectModule::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
+ if (buffer != 0) {
+ mConfig.outputCfg.buffer.raw = buffer->audioBuffer()->raw;
+ buffer->setFrameCount(mConfig.outputCfg.buffer.frameCount);
+ } else {
+ mConfig.outputCfg.buffer.raw = NULL;
+ }
+ mOutBuffer = buffer;
+ mEffectInterface->setOutBuffer(buffer);
+}
+
status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
{
Mutex::Autolock _l(mLock);
@@ -1482,7 +1510,7 @@
AudioFlinger::EffectChain::EffectChain(ThreadBase *thread,
audio_session_t sessionId)
: mThread(thread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
- mOwnInBuffer(false), mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
+ mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX)
{
mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
@@ -1495,9 +1523,6 @@
AudioFlinger::EffectChain::~EffectChain()
{
- if (mOwnInBuffer) {
- delete[] mInBuffer;
- }
}
// getEffectFromDesc_l() must be called with ThreadBase::mLock held
@@ -1562,7 +1587,8 @@
// (4 bytes frame size)
const size_t frameSize =
audio_bytes_per_sample(AUDIO_FORMAT_PCM_16_BIT) * min(FCC_2, thread->channelCount());
- memset(mInBuffer, 0, thread->frameCount() * frameSize);
+ memset(mInBuffer->audioBuffer()->raw, 0, thread->frameCount() * frameSize);
+ mInBuffer->commit();
}
// Must be called with EffectChain::mLock locked
@@ -1600,9 +1626,15 @@
size_t size = mEffects.size();
if (doProcess) {
+ // Only the input and output buffers of the chain can be external,
+ // and 'update' / 'commit' do nothing for allocated buffers, thus
+ // it's not needed to consider any other buffers here.
+ mInBuffer->update();
+ mOutBuffer->update();
for (size_t i = 0; i < size; i++) {
mEffects[i]->process();
}
+ mOutBuffer->commit();
}
bool doResetVolume = false;
for (size_t i = 0; i < size; i++) {
@@ -1662,9 +1694,11 @@
// accumulation stage. Saturation is done in EffectModule::process() before
// calling the process in effect engine
size_t numSamples = thread->frameCount();
- int32_t *buffer = new int32_t[numSamples];
- memset(buffer, 0, numSamples * sizeof(int32_t));
- effect->setInBuffer((int16_t *)buffer);
+ sp<EffectBufferHalInterface> halBuffer;
+ status_t result = EffectBufferHalInterface::allocate(
+ numSamples * sizeof(int32_t), &halBuffer);
+ if (result != OK) return result;
+ effect->setInBuffer(halBuffer);
// auxiliary effects output samples to chain input buffer for further processing
// by insert effects
effect->setOutBuffer(mInBuffer);
@@ -1775,9 +1809,7 @@
mEffects[i]->release_l();
}
- if (type == EFFECT_FLAG_TYPE_AUXILIARY) {
- delete[] effect->inBuffer();
- } else {
+ if (type != EFFECT_FLAG_TYPE_AUXILIARY) {
if (i == size - 1 && i != 0) {
mEffects[i - 1]->setOutBuffer(mOutBuffer);
mEffects[i - 1]->configure();
@@ -1922,8 +1954,8 @@
result.append("\tIn buffer Out buffer Active tracks:\n");
snprintf(buffer, SIZE, "\t%p %p %d\n",
- mInBuffer,
- mOutBuffer,
+ mInBuffer->audioBuffer(),
+ mOutBuffer->audioBuffer(),
mActiveTrackCnt);
result.append(buffer);
write(fd, result.string(), result.size());
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index dc29ce0..0755c52 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -86,10 +86,14 @@
bool isEnabled() const;
bool isProcessEnabled() const;
- void setInBuffer(int16_t *buffer) { mConfig.inputCfg.buffer.s16 = buffer; }
- int16_t *inBuffer() { return mConfig.inputCfg.buffer.s16; }
- void setOutBuffer(int16_t *buffer) { mConfig.outputCfg.buffer.s16 = buffer; }
- int16_t *outBuffer() { return mConfig.outputCfg.buffer.s16; }
+ void setInBuffer(const sp<EffectBufferHalInterface>& buffer);
+ int16_t *inBuffer() const {
+ return mInBuffer != 0 ? reinterpret_cast<int16_t*>(mInBuffer->ptr()) : NULL;
+ }
+ void setOutBuffer(const sp<EffectBufferHalInterface>& buffer);
+ int16_t *outBuffer() const {
+ return mOutBuffer != 0 ? reinterpret_cast<int16_t*>(mOutBuffer->ptr()) : NULL;
+ }
void setChain(const wp<EffectChain>& chain) { mChain = chain; }
void setThread(const wp<ThreadBase>& thread) { mThread = thread; }
const wp<ThreadBase>& thread() { return mThread; }
@@ -153,6 +157,8 @@
const effect_descriptor_t mDescriptor;// effect descriptor received from effect engine
effect_config_t mConfig; // input and output audio configuration
sp<EffectHalInterface> mEffectInterface; // Effect module HAL
+ sp<EffectBufferHalInterface> mInBuffer; // Buffers for interacting with HAL
+ sp<EffectBufferHalInterface> mOutBuffer;
status_t mStatus; // initialization status
effect_state mState; // current activation state
Vector<EffectHandle *> mHandles; // list of client handles
@@ -301,18 +307,17 @@
void setMode_l(audio_mode_t mode);
void setAudioSource_l(audio_source_t source);
- void setInBuffer(int16_t *buffer, bool ownsBuffer = false) {
+ void setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
mInBuffer = buffer;
- mOwnInBuffer = ownsBuffer;
}
int16_t *inBuffer() const {
- return mInBuffer;
+ return mInBuffer != 0 ? reinterpret_cast<int16_t*>(mInBuffer->ptr()) : NULL;
}
- void setOutBuffer(int16_t *buffer) {
+ void setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
mOutBuffer = buffer;
}
int16_t *outBuffer() const {
- return mOutBuffer;
+ return mOutBuffer != 0 ? reinterpret_cast<int16_t*>(mOutBuffer->ptr()) : NULL;
}
void incTrackCnt() { android_atomic_inc(&mTrackCnt); }
@@ -394,8 +399,8 @@
mutable Mutex mLock; // mutex protecting effect list
Vector< sp<EffectModule> > mEffects; // list of effect modules
audio_session_t mSessionId; // audio session ID
- int16_t *mInBuffer; // chain input buffer
- int16_t *mOutBuffer; // chain output buffer
+ sp<EffectBufferHalInterface> mInBuffer; // chain input buffer
+ sp<EffectBufferHalInterface> mOutBuffer; // chain output buffer
// 'volatile' here means these are accessed with atomic operations instead of mutex
volatile int32_t mActiveTrackCnt; // number of active tracks connected
@@ -403,7 +408,6 @@
int32_t mTailBufferCount; // current effect tail buffer count
int32_t mMaxTailBuffers; // maximum effect tail buffers
- bool mOwnInBuffer; // true if the chain owns its input buffer
int mVolumeCtrlIdx; // index of insert effect having control over volume
uint32_t mLeftVolume; // previous volume on left channel
uint32_t mRightVolume; // previous volume on right channel
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index 93f7ce5..7182f32 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -39,7 +39,7 @@
#endif
#include <audio_utils/conversion.h>
#include <audio_utils/format.h>
-#include "AudioMixer.h"
+#include <media/AudioMixer.h>
#include "FastMixer.h"
namespace android {
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index abfbf0f..e025316 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -56,8 +56,6 @@
#include <powermanager/PowerManager.h>
#include "AudioFlinger.h"
-#include "AudioMixer.h"
-#include "BufferProviders.h"
#include "FastMixer.h"
#include "FastCapture.h"
#include "ServiceUtilities.h"
@@ -2759,9 +2757,14 @@
status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& chain)
{
audio_session_t session = chain->sessionId();
- int16_t* buffer = reinterpret_cast<int16_t*>(mEffectBufferEnabled
- ? mEffectBuffer : mSinkBuffer);
- bool ownsBuffer = false;
+ sp<EffectBufferHalInterface> halInBuffer, halOutBuffer;
+ status_t result = EffectBufferHalInterface::mirror(
+ mEffectBufferEnabled ? mEffectBuffer : mSinkBuffer,
+ mEffectBufferEnabled ? mEffectBufferSize : mSinkBufferSize,
+ &halInBuffer);
+ if (result != OK) return result;
+ halOutBuffer = halInBuffer;
+ int16_t *buffer = reinterpret_cast<int16_t*>(halInBuffer->externalData());
ALOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
if (session > AUDIO_SESSION_OUTPUT_MIX) {
@@ -2769,10 +2772,13 @@
// the sink buffer as input
if (mType != DIRECT) {
size_t numSamples = mNormalFrameCount * mChannelCount;
- buffer = new int16_t[numSamples];
- memset(buffer, 0, numSamples * sizeof(int16_t));
- ALOGV("addEffectChain_l() creating new input buffer %p session %d", buffer, session);
- ownsBuffer = true;
+ status_t result = EffectBufferHalInterface::allocate(
+ numSamples * sizeof(int16_t),
+ &halInBuffer);
+ if (result != OK) return result;
+ buffer = halInBuffer->audioBuffer()->s16;
+ ALOGV("addEffectChain_l() creating new input buffer %p session %d",
+ buffer, session);
}
// Attach all tracks with same session ID to this chain.
@@ -2795,9 +2801,8 @@
}
}
chain->setThread(this);
- chain->setInBuffer(buffer, ownsBuffer);
- chain->setOutBuffer(reinterpret_cast<int16_t*>(mEffectBufferEnabled
- ? mEffectBuffer : mSinkBuffer));
+ chain->setInBuffer(halInBuffer);
+ chain->setOutBuffer(halOutBuffer);
// Effect chain for session AUDIO_SESSION_OUTPUT_STAGE is inserted at end of effect
// chains list in order to be processed last as it contains output stage effects.
// Effect chain for session AUDIO_SESSION_OUTPUT_MIX is inserted before
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 9746075..48e09c7 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -27,7 +27,6 @@
#include <private/media/AudioTrackShared.h>
-#include "AudioMixer.h"
#include "AudioFlinger.h"
#include "ServiceUtilities.h"
diff --git a/services/audioflinger/tests/Android.mk b/services/audioflinger/tests/Android.mk
deleted file mode 100644
index a741079..0000000
--- a/services/audioflinger/tests/Android.mk
+++ /dev/null
@@ -1,68 +0,0 @@
-# Build the unit tests for audioflinger
-
-#
-# resampler unit test
-#
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SHARED_LIBRARIES := \
- liblog \
- libutils \
- libcutils \
- libaudioutils \
- libaudioresampler
-
-LOCAL_C_INCLUDES := \
- $(call include-path-for, audio-utils) \
- frameworks/av/services/audioflinger
-
-LOCAL_SRC_FILES := \
- resampler_tests.cpp
-
-LOCAL_MODULE := resampler_tests
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_CFLAGS := -Werror -Wall
-
-include $(BUILD_NATIVE_TEST)
-
-#
-# audio mixer test tool
-#
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- test-mixer.cpp \
- ../AudioMixer.cpp.arm \
- ../BufferProviders.cpp
-
-LOCAL_C_INCLUDES := \
- $(call include-path-for, audio-utils) \
- frameworks/av/services/audioflinger \
- external/sonic
-
-LOCAL_STATIC_LIBRARIES := \
- libsndfile
-
-LOCAL_SHARED_LIBRARIES := \
- libaudiohal \
- libeffects \
- libnbaio \
- libaudioresampler \
- libaudioutils \
- libdl \
- libcutils \
- libutils \
- liblog \
- libsonic
-
-LOCAL_MODULE:= test-mixer
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CXX_STL := libc++
-
-LOCAL_CFLAGS := -Werror -Wall
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 43c1b0a..923d4f6 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -342,6 +342,9 @@
ALOGV("handleDeviceConfigChange(() device: 0x%X, address %s name %s",
device, device_address, device_name);
+ // connect/disconnect only 1 device at a time
+ if (!audio_is_output_device(device) && !audio_is_input_device(device)) return BAD_VALUE;
+
// Check if the device is currently connected
sp<DeviceDescriptor> devDesc =
mHwModules.getDeviceDescriptor(device, device_address, device_name);
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 52aa143..1e63a05 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -37,9 +37,6 @@
if (!settingsAllowed()) {
return PERMISSION_DENIED;
}
- if (!audio_is_output_device(device) && !audio_is_input_device(device)) {
- return BAD_VALUE;
- }
if (state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE &&
state != AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
return BAD_VALUE;
@@ -72,9 +69,6 @@
if (!settingsAllowed()) {
return PERMISSION_DENIED;
}
- if (!audio_is_output_device(device) && !audio_is_input_device(device)) {
- return BAD_VALUE;
- }
ALOGV("handleDeviceConfigChange()");
Mutex::Autolock _l(mLock);
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 4a5250a..3aec562 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -68,13 +68,22 @@
mLegacyMode = legacyMode;
}
-status_t Camera2Client::initialize(CameraModule *module)
+status_t Camera2Client::initialize(CameraModule *module) {
+ return initializeImpl(module);
+}
+
+status_t Camera2Client::initialize(sp<CameraProviderManager> manager) {
+ return initializeImpl(manager);
+}
+
+template<typename TProviderPtr>
+status_t Camera2Client::initializeImpl(TProviderPtr providerPtr)
{
ATRACE_CALL();
ALOGV("%s: Initializing client for camera %d", __FUNCTION__, mCameraId);
status_t res;
- res = Camera2ClientBase::initialize(module);
+ res = Camera2ClientBase::initialize(providerPtr);
if (res != OK) {
return res;
}
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index e2129f5..87c91a0 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -98,7 +98,8 @@
virtual ~Camera2Client();
- status_t initialize(CameraModule *module);
+ virtual status_t initialize(CameraModule *module) override;
+ virtual status_t initialize(sp<CameraProviderManager> manager) override;
virtual status_t dump(int fd, const Vector<String16>& args);
@@ -219,6 +220,9 @@
// Video snapshot jpeg size overriding helper function
status_t overrideVideoSnapshotSize(Parameters ¶ms);
+
+ template<typename TProviderPtr>
+ status_t initializeImpl(TProviderPtr providerPtr);
};
}; // namespace android
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index 32b99ca..6efe4e3 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -917,6 +917,8 @@
} else {
allowZslMode = true;
}
+ // TODO (b/34131351): turn ZSL back on after fixing the issue
+ allowZslMode = false;
ALOGI("%s: allowZslMode: %d slowJpegMode %d", __FUNCTION__, allowZslMode, slowJpegMode);
diff --git a/services/radio/HidlUtils.cpp b/services/radio/HidlUtils.cpp
index bfced7a..3b33386 100644
--- a/services/radio/HidlUtils.cpp
+++ b/services/radio/HidlUtils.cpp
@@ -122,8 +122,7 @@
//static
void HidlUtils::convertProgramInfoFromHal(radio_program_info_t *info,
- const ProgramInfo *halInfo,
- bool withMetadata)
+ const ProgramInfo *halInfo)
{
info->channel = halInfo->channel;
info->sub_channel = halInfo->subChannel;
@@ -131,10 +130,8 @@
info->stereo = halInfo->stereo;
info->digital = halInfo->digital;
info->signal_strength = halInfo->signalStrength;
- if (withMetadata && halInfo->metadata.size() != 0) {
- convertMetaDataFromHal(&info->metadata, halInfo->metadata,
- halInfo->channel, halInfo->subChannel);
- }
+ convertMetaDataFromHal(&info->metadata, halInfo->metadata,
+ halInfo->channel, halInfo->subChannel);
}
//static
diff --git a/services/radio/HidlUtils.h b/services/radio/HidlUtils.h
index 091abb7..c771060 100644
--- a/services/radio/HidlUtils.h
+++ b/services/radio/HidlUtils.h
@@ -38,8 +38,7 @@
static void convertBandConfigToHal(BandConfig *halConfig,
const radio_hal_band_config_t *config);
static void convertProgramInfoFromHal(radio_program_info_t *info,
- const ProgramInfo *halInfo,
- bool withMetadata);
+ const ProgramInfo *halInfo);
static void convertMetaDataFromHal(radio_metadata_t **metadata,
const hidl_vec<MetaData>& halMetadata,
uint32_t channel,
diff --git a/services/radio/RadioHalHidl.cpp b/services/radio/RadioHalHidl.cpp
index c7a899a..34a6db7 100644
--- a/services/radio/RadioHalHidl.cpp
+++ b/services/radio/RadioHalHidl.cpp
@@ -39,11 +39,6 @@
return new RadioHalHidl(classId);
}
-void RadioHalHidl::crashIfHalIsDead(const Status& status) {
- LOG_ALWAYS_FATAL_IF(
- status.transactionError() == DEAD_OBJECT, "HAL server crashed, need to restart");
-}
-
int RadioHalHidl::getProperties(radio_hal_properties_t *properties)
{
ALOGV("%s IN", __FUNCTION__);
@@ -52,7 +47,7 @@
return -ENODEV;
}
Properties halProperties;
- Result halResult;
+ Result halResult = Result::NOT_INITIALIZED;
Return<void> hidlReturn =
module->getProperties([&](Result result, const Properties& properties) {
halResult = result;
@@ -61,7 +56,6 @@
}
});
- crashIfHalIsDead(hidlReturn.getStatus());
if (halResult == Result::OK) {
HidlUtils::convertPropertiesFromHal(properties, &halProperties);
}
@@ -80,7 +74,7 @@
sp<Tuner> tunerImpl = new Tuner(callback, this);
BandConfig halConfig;
- Result halResult;
+ Result halResult = Result::NOT_INITIALIZED;
sp<ITuner> halTuner;
HidlUtils::convertBandConfigToHal(&halConfig, config);
@@ -93,7 +87,6 @@
}
});
- crashIfHalIsDead(hidlReturn.getStatus());
if (halResult == Result::OK) {
tunerImpl->setHalTuner(halTuner);
tuner = tunerImpl;
@@ -154,7 +147,6 @@
HidlUtils::convertBandConfigToHal(&halConfig, config);
Return<Result> hidlResult = mHalTuner->setConfiguration(halConfig);
- checkHidlStatus(hidlResult.getStatus());
return HidlUtils::convertHalResult(hidlResult);
}
@@ -173,8 +165,7 @@
halConfig = config;
}
});
- status_t status = checkHidlStatus(hidlReturn.getStatus());
- if (status == NO_ERROR && halResult == Result::OK) {
+ if (hidlReturn.isOk() && halResult == Result::OK) {
HidlUtils::convertBandConfigFromHal(config, &halConfig);
}
return HidlUtils::convertHalResult(halResult);
@@ -188,7 +179,6 @@
}
Return<Result> hidlResult =
mHalTuner->scan(static_cast<Direction>(direction), skip_sub_channel);
- checkHidlStatus(hidlResult.getStatus());
return HidlUtils::convertHalResult(hidlResult);
}
@@ -200,7 +190,6 @@
}
Return<Result> hidlResult =
mHalTuner->step(static_cast<Direction>(direction), skip_sub_channel);
- checkHidlStatus(hidlResult.getStatus());
return HidlUtils::convertHalResult(hidlResult);
}
@@ -212,7 +201,6 @@
}
Return<Result> hidlResult =
mHalTuner->tune(channel, sub_channel);
- checkHidlStatus(hidlResult.getStatus());
return HidlUtils::convertHalResult(hidlResult);
}
@@ -223,7 +211,6 @@
return -ENODEV;
}
Return<Result> hidlResult = mHalTuner->cancel();
- checkHidlStatus(hidlResult.getStatus());
return HidlUtils::convertHalResult(hidlResult);
}
@@ -233,19 +220,20 @@
if (mHalTuner == 0) {
return -ENODEV;
}
+ if (info == nullptr || info->metadata == nullptr) {
+ return BAD_VALUE;
+ }
ProgramInfo halInfo;
Result halResult;
- bool withMetaData = (info->metadata != NULL);
Return<void> hidlReturn = mHalTuner->getProgramInformation(
- withMetaData, [&](Result result, const ProgramInfo& info) {
- halResult = result;
- if (result == Result::OK) {
- halInfo = info;
- }
- });
- status_t status = checkHidlStatus(hidlReturn.getStatus());
- if (status == NO_ERROR && halResult == Result::OK) {
- HidlUtils::convertProgramInfoFromHal(info, &halInfo, withMetaData);
+ [&](Result result, const ProgramInfo& info) {
+ halResult = result;
+ if (result == Result::OK) {
+ halInfo = info;
+ }
+ });
+ if (hidlReturn.isOk() && halResult == Result::OK) {
+ HidlUtils::convertProgramInfoFromHal(info, &halInfo);
}
return HidlUtils::convertHalResult(halResult);
}
@@ -276,11 +264,9 @@
memset(&event, 0, sizeof(radio_hal_event_t));
event.type = RADIO_EVENT_TUNED;
event.status = HidlUtils::convertHalResult(result);
- HidlUtils::convertProgramInfoFromHal(&event.info, &info, true);
+ HidlUtils::convertProgramInfoFromHal(&event.info, &info);
onCallback(&event);
- if (event.info.metadata != NULL) {
- radio_metadata_deallocate(event.info.metadata);
- }
+ radio_metadata_deallocate(event.info.metadata);
return Return<void>();
}
@@ -290,7 +276,7 @@
radio_hal_event_t event;
memset(&event, 0, sizeof(radio_hal_event_t));
event.type = RADIO_EVENT_AF_SWITCH;
- HidlUtils::convertProgramInfoFromHal(&event.info, &info, true);
+ HidlUtils::convertProgramInfoFromHal(&event.info, &info);
onCallback(&event);
if (event.info.metadata != NULL) {
radio_metadata_deallocate(event.info.metadata);
@@ -368,16 +354,6 @@
mHalTuner.clear();
}
-status_t RadioHalHidl::Tuner::checkHidlStatus(Status hidlStatus)
-{
- status_t status = hidlStatus.transactionError();
- if (status == DEAD_OBJECT) {
- handleHwFailure();
- }
- RadioHalHidl::crashIfHalIsDead(hidlStatus);
- return status;
-}
-
void RadioHalHidl::Tuner::onCallback(radio_hal_event_t *halEvent)
{
if (mCallback != 0) {
diff --git a/services/radio/RadioHalHidl.h b/services/radio/RadioHalHidl.h
index 1657a40..b60a95e 100644
--- a/services/radio/RadioHalHidl.h
+++ b/services/radio/RadioHalHidl.h
@@ -45,8 +45,6 @@
public:
RadioHalHidl(radio_class_t classId);
- static void crashIfHalIsDead(const Status& status);
-
// RadioInterface
virtual int getProperties(radio_hal_properties_t *properties);
virtual int openTuner(const radio_hal_band_config_t *config,
@@ -88,7 +86,6 @@
void onCallback(radio_hal_event_t *halEvent);
void handleHwFailure();
- status_t checkHidlStatus(Status hidlStatus);
sp<ITuner> mHalTuner;
sp<TunerCallbackInterface> mCallback;
diff --git a/services/soundtrigger/SoundTriggerHalHidl.cpp b/services/soundtrigger/SoundTriggerHalHidl.cpp
index c027799..eb9d38d 100644
--- a/services/soundtrigger/SoundTriggerHalHidl.cpp
+++ b/services/soundtrigger/SoundTriggerHalHidl.cpp
@@ -53,13 +53,13 @@
});
}
- if (hidlReturn.getStatus().isOk()) {
+ if (hidlReturn.isOk()) {
if (ret == 0) {
convertPropertiesFromHal(properties, &halProperties);
}
} else {
- ret = (int)hidlReturn.getStatus().transactionError();
- crashIfHalIsDead(ret);
+ ALOGE("getProperties error %s", hidlReturn.description().c_str());
+ return UNKNOWN_ERROR;
}
ALOGI("getProperties ret %d", ret);
return ret;
@@ -123,7 +123,7 @@
delete halSoundModel;
- if (hidlReturn.getStatus().isOk()) {
+ if (hidlReturn.isOk()) {
if (ret == 0) {
AutoMutex lock(mLock);
*handle = (sound_model_handle_t)modelId;
@@ -131,12 +131,10 @@
mSoundModels.add(*handle, model);
}
} else {
- ret = (int)hidlReturn.getStatus().transactionError();
- ALOGE("loadSoundModel error %d", ret);
- crashIfHalIsDead(ret);
+ ALOGE("loadSoundModel error %s", hidlReturn.description().c_str());
+ return UNKNOWN_ERROR;
}
-
return ret;
}
@@ -158,13 +156,13 @@
AutoMutex lock(mHalLock);
hidlReturn = soundtrigger->unloadSoundModel(model->mHalHandle);
}
- int ret = (int)hidlReturn.getStatus().transactionError();
- ALOGE_IF(ret != 0, "unloadSoundModel error %d", ret);
- crashIfHalIsDead(ret);
- if (ret == 0) {
- ret = hidlReturn;
+
+ if (!hidlReturn.isOk()) {
+ ALOGE("unloadSoundModel error %s", hidlReturn.description().c_str());
+ return UNKNOWN_ERROR;
}
- return ret;
+
+ return hidlReturn;
}
int SoundTriggerHalHidl::startRecognition(sound_model_handle_t handle,
@@ -197,13 +195,11 @@
delete halConfig;
- int ret = (int)hidlReturn.getStatus().transactionError();
- ALOGE_IF(ret != 0, "startRecognition error %d", ret);
- crashIfHalIsDead(ret);
- if (ret == 0) {
- ret = hidlReturn;
+ if (!hidlReturn.isOk()) {
+ ALOGE("startRecognition error %s", hidlReturn.description().c_str());
+ return UNKNOWN_ERROR;
}
- return ret;
+ return hidlReturn;
}
int SoundTriggerHalHidl::stopRecognition(sound_model_handle_t handle)
@@ -225,13 +221,11 @@
hidlReturn = soundtrigger->stopRecognition(model->mHalHandle);
}
- int ret = (int)hidlReturn.getStatus().transactionError();
- ALOGE_IF(ret != 0, "stopRecognition error %d", ret);
- crashIfHalIsDead(ret);
- if (ret == 0) {
- ret = hidlReturn;
+ if (!hidlReturn.isOk()) {
+ ALOGE("stopRecognition error %s", hidlReturn.description().c_str());
+ return UNKNOWN_ERROR;
}
- return ret;
+ return hidlReturn;
}
int SoundTriggerHalHidl::stopAllRecognitions()
@@ -247,13 +241,11 @@
hidlReturn = soundtrigger->stopAllRecognitions();
}
- int ret = (int)hidlReturn.getStatus().transactionError();
- ALOGE_IF(ret != 0, "stopAllRecognitions error %d", ret);
- crashIfHalIsDead(ret);
- if (ret == 0) {
- ret = hidlReturn;
+ if (!hidlReturn.isOk()) {
+ ALOGE("stopAllRecognitions error %s", hidlReturn.description().c_str());
+ return UNKNOWN_ERROR;
}
- return ret;
+ return hidlReturn;
}
SoundTriggerHalHidl::SoundTriggerHalHidl(const char *moduleName)
@@ -279,11 +271,6 @@
return mISoundTrigger;
}
-void SoundTriggerHalHidl::crashIfHalIsDead(int ret)
-{
- LOG_ALWAYS_FATAL_IF(ret == -EPIPE, "HAL server crashed, need to restart");
-}
-
sp<SoundTriggerHalHidl::SoundModel> SoundTriggerHalHidl::getModel(sound_model_handle_t handle)
{
AutoMutex lock(mLock);
diff --git a/services/soundtrigger/SoundTriggerHalHidl.h b/services/soundtrigger/SoundTriggerHalHidl.h
index b235e1c..916fcc4 100644
--- a/services/soundtrigger/SoundTriggerHalHidl.h
+++ b/services/soundtrigger/SoundTriggerHalHidl.h
@@ -25,7 +25,6 @@
#include <android/hardware/soundtrigger/2.0/types.h>
#include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
#include <android/hardware/soundtrigger/2.0/ISoundTriggerHwCallback.h>
-#include <android/hardware/soundtrigger/2.0/BnSoundTriggerHwCallback.h>
namespace android {
@@ -143,7 +142,6 @@
uint32_t nextUniqueId();
sp<ISoundTriggerHw> getService();
- void crashIfHalIsDead(int ret);
sp<SoundModel> getModel(sound_model_handle_t handle);
sp<SoundModel> removeModel(sound_model_handle_t handle);