Merge "Re-implement HIDL effect processing using FMQ and IMemory"
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/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/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 f2e3e7c..d1ade1d 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -1347,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;
@@ -1714,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/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index e190d07..f7e56e4 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -33,6 +33,9 @@
#include <media/IMediaAnalyticsService.h>
+static const int kDumpLockRetries = 50;
+static const int kDumpLockSleepUs = 20000;
+
namespace android {
@@ -51,7 +54,7 @@
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
@@ -776,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/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/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..ac15687
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -3260,8 +3260,8 @@
mOwner->writeInt32(0);
} else {
int32_t width, height;
- bool success = mMeta->findInt32(kKeyWidth, &width);
- success = success && mMeta->findInt32(kKeyHeight, &height);
+ bool success = mMeta->findInt32(kKeyDisplayWidth, &width);
+ success = success && mMeta->findInt32(kKeyDisplayHeight, &height);
CHECK(success);
mOwner->writeInt32(width << 16); // 32-bit fixed-point value
@@ -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/services/audioflinger/AudioResampler.cpp b/services/audioflinger/AudioResampler.cpp
index 43624a0..8b7259d 100644
--- a/services/audioflinger/AudioResampler.cpp
+++ b/services/audioflinger/AudioResampler.cpp
@@ -22,8 +22,8 @@
#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"
diff --git a/services/audioflinger/AudioResamplerCubic.cpp b/services/audioflinger/AudioResamplerCubic.cpp
index d27dce7..9fb6699 100644
--- a/services/audioflinger/AudioResamplerCubic.cpp
+++ b/services/audioflinger/AudioResamplerCubic.cpp
@@ -19,7 +19,8 @@
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
-#include <android/log.h>
+
+#include <log/log.h>
#include "AudioResampler.h"
#include "AudioResamplerCubic.h"
diff --git a/services/audioflinger/tests/test_utils.h b/services/audioflinger/tests/test_utils.h
index 283c768..b61a929 100644
--- a/services/audioflinger/tests/test_utils.h
+++ b/services/audioflinger/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/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);