Merge "audiohal: Support 64-bit audioflinger with 32-bit hal"
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 9a236fc..a98a207 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -3,19 +3,21 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- stagefright.cpp \
- jpeg.cpp \
- SineSource.cpp
+ stagefright.cpp \
+ jpeg.cpp \
+ SineSource.cpp
LOCAL_SHARED_LIBRARIES := \
- libstagefright libmedia libutils libbinder libstagefright_foundation \
- libjpeg libgui libcutils liblog
+ libstagefright libmedia libutils libbinder libstagefright_foundation \
+ libjpeg libgui libcutils liblog \
+ android.hardware.media.omx@1.0 \
+ android.hardware.media.omx@1.0-utils
LOCAL_C_INCLUDES:= \
- frameworks/av/media/libstagefright \
- frameworks/av/media/libstagefright/include \
- $(TOP)/frameworks/native/include/media/openmax \
- external/jpeg \
+ frameworks/av/media/libstagefright \
+ frameworks/av/media/libstagefright/include \
+ $(TOP)/frameworks/native/include/media/openmax \
+ external/jpeg \
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
@@ -30,16 +32,16 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- SineSource.cpp \
- record.cpp
+ SineSource.cpp \
+ record.cpp
LOCAL_SHARED_LIBRARIES := \
- libstagefright libmedia liblog libutils libbinder libstagefright_foundation
+ libstagefright libmedia liblog libutils libbinder libstagefright_foundation
LOCAL_C_INCLUDES:= \
- frameworks/av/media/libstagefright \
- $(TOP)/frameworks/native/include/media/openmax \
- $(TOP)/frameworks/native/include/media/hardware
+ frameworks/av/media/libstagefright \
+ $(TOP)/frameworks/native/include/media/openmax \
+ $(TOP)/frameworks/native/include/media/hardware
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
@@ -54,16 +56,16 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- SineSource.cpp \
- recordvideo.cpp
+ SineSource.cpp \
+ recordvideo.cpp
LOCAL_SHARED_LIBRARIES := \
- libstagefright libmedia liblog libutils libbinder libstagefright_foundation
+ libstagefright libmedia liblog libutils libbinder libstagefright_foundation
LOCAL_C_INCLUDES:= \
- frameworks/av/media/libstagefright \
- $(TOP)/frameworks/native/include/media/openmax \
- $(TOP)/frameworks/native/include/media/hardware
+ frameworks/av/media/libstagefright \
+ $(TOP)/frameworks/native/include/media/openmax \
+ $(TOP)/frameworks/native/include/media/hardware
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
@@ -79,15 +81,15 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- SineSource.cpp \
- audioloop.cpp
+ SineSource.cpp \
+ audioloop.cpp
LOCAL_SHARED_LIBRARIES := \
- libstagefright libmedia liblog libutils libbinder libstagefright_foundation
+ libstagefright libmedia liblog libutils libbinder libstagefright_foundation
LOCAL_C_INCLUDES:= \
- frameworks/av/media/libstagefright \
- $(TOP)/frameworks/native/include/media/openmax
+ frameworks/av/media/libstagefright \
+ $(TOP)/frameworks/native/include/media/openmax
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
@@ -105,12 +107,12 @@
stream.cpp \
LOCAL_SHARED_LIBRARIES := \
- libstagefright liblog libutils libbinder libgui \
- libstagefright_foundation libmedia libcutils
+ libstagefright liblog libutils libbinder libgui \
+ libstagefright_foundation libmedia libcutils
LOCAL_C_INCLUDES:= \
- frameworks/av/media/libstagefright \
- $(TOP)/frameworks/native/include/media/openmax
+ frameworks/av/media/libstagefright \
+ $(TOP)/frameworks/native/include/media/openmax
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
@@ -125,16 +127,16 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- codec.cpp \
- SimplePlayer.cpp \
+ codec.cpp \
+ SimplePlayer.cpp \
LOCAL_SHARED_LIBRARIES := \
- libstagefright liblog libutils libbinder libstagefright_foundation \
- libmedia libaudioclient libgui libcutils
+ libstagefright liblog libutils libbinder libstagefright_foundation \
+ libmedia libaudioclient libgui libcutils
LOCAL_C_INCLUDES:= \
- frameworks/av/media/libstagefright \
- $(TOP)/frameworks/native/include/media/openmax
+ frameworks/av/media/libstagefright \
+ $(TOP)/frameworks/native/include/media/openmax
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
@@ -149,33 +151,33 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- filters/argbtorgba.rs \
- filters/nightvision.rs \
- filters/saturation.rs \
- mediafilter.cpp \
+ filters/argbtorgba.rs \
+ filters/nightvision.rs \
+ filters/saturation.rs \
+ mediafilter.cpp \
LOCAL_SHARED_LIBRARIES := \
- libstagefright \
- liblog \
- libutils \
- libbinder \
- libstagefright_foundation \
- libmedia \
- libgui \
- libcutils \
- libRScpp \
+ libstagefright \
+ liblog \
+ libutils \
+ libbinder \
+ libstagefright_foundation \
+ libmedia \
+ libgui \
+ libcutils \
+ libRScpp \
LOCAL_C_INCLUDES:= \
- $(TOP)/frameworks/av/media/libstagefright \
- $(TOP)/frameworks/native/include/media/openmax \
- $(TOP)/frameworks/rs/cpp \
- $(TOP)/frameworks/rs \
+ $(TOP)/frameworks/av/media/libstagefright \
+ $(TOP)/frameworks/native/include/media/openmax \
+ $(TOP)/frameworks/rs/cpp \
+ $(TOP)/frameworks/rs \
intermediates := $(call intermediates-dir-for,STATIC_LIBRARIES,libRS,TARGET,)
LOCAL_C_INCLUDES += $(intermediates)
LOCAL_STATIC_LIBRARIES:= \
- libstagefright_mediafilter
+ libstagefright_mediafilter
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
@@ -190,15 +192,15 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- muxer.cpp \
+ muxer.cpp \
LOCAL_SHARED_LIBRARIES := \
- libstagefright liblog libutils libbinder libstagefright_foundation \
- libcutils libc
+ libstagefright liblog libutils libbinder libstagefright_foundation \
+ libcutils libc
LOCAL_C_INCLUDES:= \
- frameworks/av/media/libstagefright \
- $(TOP)/frameworks/native/include/media/openmax
+ frameworks/av/media/libstagefright \
+ $(TOP)/frameworks/native/include/media/openmax
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 5e3a859..ffa09eb 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -64,6 +64,9 @@
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
+#include <android/hardware/media/omx/1.0/IOmx.h>
+#include <omx/hal/1.0/utils/WOmx.h>
+
using namespace android;
static long gNumRepetitions;
@@ -904,13 +907,25 @@
}
if (listComponents) {
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder = sm->getService(String16("media.codec"));
- sp<IMediaCodecService> service = interface_cast<IMediaCodecService>(binder);
+ sp<IOMX> omx;
+ int32_t trebleOmx = property_get_int32("persist.media.treble_omx", -1);
+ if ((trebleOmx == 1) || ((trebleOmx == -1) &&
+ property_get_bool("persist.hal.binderization", 0))) {
+ using namespace ::android::hardware::media::omx::V1_0;
+ sp<IOmx> tOmx = IOmx::getService();
- CHECK(service.get() != NULL);
+ CHECK(tOmx.get() != NULL);
- sp<IOMX> omx = service->getOMX();
+ omx = new utils::LWOmx(tOmx);
+ } else {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16("media.codec"));
+ sp<IMediaCodecService> service = interface_cast<IMediaCodecService>(binder);
+
+ CHECK(service.get() != NULL);
+
+ omx = service->getOMX();
+ }
CHECK(omx.get() != NULL);
List<IOMX::ComponentInfo> list;
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 814a643..90d9942 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -94,9 +94,8 @@
static status_t getOMXChannelMapping(size_t numChannels, OMX_AUDIO_CHANNELTYPE map[]);
- // Read the flag from "media.use_treble_omx", save it locally, and return
- // it.
- bool updateTrebleFlag();
+ // Save the flag.
+ void setTrebleFlag(bool trebleFlag);
// Return the saved flag.
bool getTrebleFlag() const;
diff --git a/include/media/stagefright/MediaCodecSource.h b/include/media/stagefright/MediaCodecSource.h
index f9a46a9..5e99b78 100644
--- a/include/media/stagefright/MediaCodecSource.h
+++ b/include/media/stagefright/MediaCodecSource.h
@@ -54,7 +54,7 @@
// MediaSource
virtual status_t start(MetaData *params = NULL);
virtual status_t stop();
- virtual status_t pause();
+ virtual status_t pause(MetaData *params = NULL);
virtual sp<MetaData> getFormat();
virtual status_t read(
MediaBuffer **buffer,
@@ -66,6 +66,12 @@
// for AHandlerReflector
void onMessageReceived(const sp<AMessage> &msg);
+ // Set GraphicBufferSource stop time. GraphicBufferSource will stop
+ // after receiving a buffer with timestamp larger or equal than stopTimeUs.
+ // All the buffers with timestamp larger or equal to stopTimeUs will be
+ // discarded. stopTimeUs uses SYSTEM_TIME_MONOTONIC time base.
+ status_t setStopStimeUs(int64_t stopTimeUs);
+
protected:
virtual ~MediaCodecSource();
@@ -79,6 +85,7 @@
kWhatStop,
kWhatPause,
kWhatSetInputBufferTimeOffset,
+ kWhatSetStopTimeOffset,
kWhatGetFirstSampleSystemTimeUs,
kWhatStopStalled,
};
@@ -91,13 +98,23 @@
uint32_t flags = 0);
status_t onStart(MetaData *params);
- void onPause();
+
+ // Pause the source at pauseStartTimeUs. For non-surface input,
+ // buffers will be dropped immediately. For surface input, buffers
+ // with timestamp smaller than pauseStartTimeUs will still be encoded.
+ // Buffers with timestamp larger or queal to pauseStartTimeUs will be
+ // dropped. pauseStartTimeUs uses SYSTEM_TIME_MONOTONIC time base.
+ void onPause(int64_t pauseStartTimeUs);
+
status_t init();
status_t initEncoder();
void releaseEncoder();
status_t feedEncoderInputBuffers();
- void suspend();
- void resume(int64_t skipFramesBeforeUs = -1ll);
+ // Resume GraphicBufferSource at resumeStartTimeUs. Buffers
+ // from GraphicBufferSource with timestamp larger or equal to
+ // resumeStartTimeUs will be encoded. resumeStartTimeUs uses
+ // SYSTEM_TIME_MONOTONIC time base.
+ void resume(int64_t resumeStartTimeUs = -1ll);
void signalEOS(status_t err = ERROR_END_OF_STREAM);
bool reachedEOS();
status_t postSynchronouslyAndReturnError(const sp<AMessage> &msg);
diff --git a/include/media/stagefright/OMXClient.h b/include/media/stagefright/OMXClient.h
index 6b86cbf..315f19b 100644
--- a/include/media/stagefright/OMXClient.h
+++ b/include/media/stagefright/OMXClient.h
@@ -26,7 +26,8 @@
public:
OMXClient();
- status_t connect();
+ status_t connect(bool* trebleFlag = nullptr);
+ status_t connectLegacy();
status_t connectTreble();
void disconnect();
diff --git a/media/libmedia/aidl/android/IGraphicBufferSource.aidl b/media/libmedia/aidl/android/IGraphicBufferSource.aidl
index a8dd309..325c631 100644
--- a/media/libmedia/aidl/android/IGraphicBufferSource.aidl
+++ b/media/libmedia/aidl/android/IGraphicBufferSource.aidl
@@ -25,11 +25,12 @@
*/
interface IGraphicBufferSource {
void configure(IOMXNode omxNode, int dataSpace);
- void setSuspend(boolean suspend);
+ void setSuspend(boolean suspend, long suspendTimeUs);
void setRepeatPreviousFrameDelayUs(long repeatAfterUs);
void setMaxFps(float maxFps);
void setTimeLapseConfig(long timePerFrameUs, long timePerCaptureUs);
void setStartTimeUs(long startTimeUs);
+ void setStopTimeUs(long stopTimeUs);
void setColorAspects(int aspects);
void setTimeOffsetUs(long timeOffsetsUs);
void signalEndOfInputStream();
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index 64627fb..e6d9b71 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -36,6 +36,8 @@
libstagefright_omx \
libstagefright_wfd \
libutils \
+ libhidlbase \
+ android.hardware.media.omx@1.0 \
LOCAL_STATIC_LIBRARIES := \
libstagefright_nuplayer \
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 62e5ec8..dbc7e21 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -597,6 +597,7 @@
if (mAudioAttributes != NULL) {
free(mAudioAttributes);
}
+ clearDeathNotifiers();
}
void MediaPlayerService::Client::disconnect()
@@ -654,12 +655,22 @@
const sp<MediaPlayerBase>& listener,
int which) {
mService = service;
+ mOmx = nullptr;
+ mListener = listener;
+ mWhich = which;
+}
+
+MediaPlayerService::Client::ServiceDeathNotifier::ServiceDeathNotifier(
+ const sp<IOmx>& omx,
+ const sp<MediaPlayerBase>& listener,
+ int which) {
+ mService = nullptr;
+ mOmx = omx;
mListener = listener;
mWhich = which;
}
MediaPlayerService::Client::ServiceDeathNotifier::~ServiceDeathNotifier() {
- mService->unlinkToDeath(this);
}
void MediaPlayerService::Client::ServiceDeathNotifier::binderDied(const wp<IBinder>& /*who*/) {
@@ -671,10 +682,43 @@
}
}
+void MediaPlayerService::Client::ServiceDeathNotifier::serviceDied(
+ uint64_t /* cookie */,
+ const wp<::android::hidl::base::V1_0::IBase>& /* who */) {
+ sp<MediaPlayerBase> listener = mListener.promote();
+ if (listener != NULL) {
+ listener->sendEvent(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, mWhich);
+ } else {
+ ALOGW("listener for process %d death is gone", mWhich);
+ }
+}
+
+void MediaPlayerService::Client::ServiceDeathNotifier::unlinkToDeath() {
+ if (mService != nullptr) {
+ mService->unlinkToDeath(this);
+ mService = nullptr;
+ } else if (mOmx != nullptr) {
+ mOmx->unlinkToDeath(this);
+ mOmx = nullptr;
+ }
+}
+
+void MediaPlayerService::Client::clearDeathNotifiers() {
+ if (mExtractorDeathListener != nullptr) {
+ mExtractorDeathListener->unlinkToDeath();
+ mExtractorDeathListener = nullptr;
+ }
+ if (mCodecDeathListener != nullptr) {
+ mCodecDeathListener->unlinkToDeath();
+ mCodecDeathListener = nullptr;
+ }
+}
+
sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre(
player_type playerType)
{
ALOGV("player type = %d", playerType);
+ clearDeathNotifiers();
// create the right type of player
sp<MediaPlayerBase> p = createPlayer(playerType);
@@ -691,13 +735,27 @@
mExtractorDeathListener = new ServiceDeathNotifier(binder, p, MEDIAEXTRACTOR_PROCESS_DEATH);
binder->linkToDeath(mExtractorDeathListener);
- binder = sm->getService(String16("media.codec"));
- if (binder == NULL) {
- ALOGE("codec service not available");
- return NULL;
+ int32_t trebleOmx = property_get_int32("persist.media.treble_omx", -1);
+ if ((trebleOmx == 1) || ((trebleOmx == -1) &&
+ property_get_bool("persist.hal.binderization", 0))) {
+ // Treble IOmx
+ sp<IOmx> omx = IOmx::getService();
+ if (omx == nullptr) {
+ ALOGE("Treble IOmx not available");
+ return NULL;
+ }
+ mCodecDeathListener = new ServiceDeathNotifier(omx, p, MEDIACODEC_PROCESS_DEATH);
+ omx->linkToDeath(mCodecDeathListener, 0);
+ } else {
+ // Legacy IOMX
+ binder = sm->getService(String16("media.codec"));
+ if (binder == NULL) {
+ ALOGE("codec service not available");
+ return NULL;
+ }
+ mCodecDeathListener = new ServiceDeathNotifier(binder, p, MEDIACODEC_PROCESS_DEATH);
+ binder->linkToDeath(mCodecDeathListener);
}
- mCodecDeathListener = new ServiceDeathNotifier(binder, p, MEDIACODEC_PROCESS_DEATH);
- binder->linkToDeath(mCodecDeathListener);
if (!p->hardwareOutput()) {
Mutex::Autolock l(mLock);
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index f5a540b..dff7322 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -30,6 +30,8 @@
#include <media/Metadata.h>
#include <media/stagefright/foundation/ABase.h>
+#include <android/hardware/media/omx/1.0/IOmx.h>
+
#include <system/audio.h>
namespace android {
@@ -69,6 +71,7 @@
class MediaPlayerService : public BnMediaPlayerService
{
class Client;
+ typedef ::android::hardware::media::omx::V1_0::IOmx IOmx;
class AudioOutput : public MediaPlayerBase::AudioSink
{
@@ -362,22 +365,35 @@
virtual status_t releaseDrm();
private:
- class ServiceDeathNotifier: public IBinder::DeathRecipient
+ class ServiceDeathNotifier:
+ public IBinder::DeathRecipient,
+ public ::android::hardware::hidl_death_recipient
{
public:
ServiceDeathNotifier(
const sp<IBinder>& service,
const sp<MediaPlayerBase>& listener,
int which);
+ ServiceDeathNotifier(
+ const sp<IOmx>& omx,
+ const sp<MediaPlayerBase>& listener,
+ int which);
virtual ~ServiceDeathNotifier();
virtual void binderDied(const wp<IBinder>& who);
+ virtual void serviceDied(
+ uint64_t cookie,
+ const wp<::android::hidl::base::V1_0::IBase>& who);
+ void unlinkToDeath();
private:
int mWhich;
sp<IBinder> mService;
+ sp<IOmx> mOmx;
wp<MediaPlayerBase> mListener;
};
+ void clearDeathNotifiers();
+
friend class MediaPlayerService;
Client( const sp<MediaPlayerService>& service,
pid_t pid,
@@ -437,8 +453,8 @@
// getMetadata clears this set.
media::Metadata::Filter mMetadataUpdated; // protected by mLock
- sp<IBinder::DeathRecipient> mExtractorDeathListener;
- sp<IBinder::DeathRecipient> mCodecDeathListener;
+ sp<ServiceDeathNotifier> mExtractorDeathListener;
+ sp<ServiceDeathNotifier> mCodecDeathListener;
#if CALLBACK_ANTAGONIZER
Antagonizer* mAntagonizer;
#endif
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index bb2d28b..763f509 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -328,6 +328,7 @@
wp<MediaRecorderClient> client(this);
mMediaPlayerService->removeMediaRecorderClient(client);
}
+ clearDeathNotifiers();
return NO_ERROR;
}
@@ -351,15 +352,25 @@
const sp<IMediaRecorderClient>& listener,
int which) {
mService = service;
+ mOmx = nullptr;
+ mListener = listener;
+ mWhich = which;
+}
+
+MediaRecorderClient::ServiceDeathNotifier::ServiceDeathNotifier(
+ const sp<IOmx>& omx,
+ const sp<IMediaRecorderClient>& listener,
+ int which) {
+ mService = nullptr;
+ mOmx = omx;
mListener = listener;
mWhich = which;
}
MediaRecorderClient::ServiceDeathNotifier::~ServiceDeathNotifier() {
- mService->unlinkToDeath(this);
}
-void MediaRecorderClient::ServiceDeathNotifier::binderDied(const wp<IBinder>& /*who*/) {
+void MediaRecorderClient::ServiceDeathNotifier::binderDied(const wp<IBinder>& /*who*/) {
sp<IMediaRecorderClient> listener = mListener.promote();
if (listener != NULL) {
listener->notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, mWhich);
@@ -368,9 +379,42 @@
}
}
+void MediaRecorderClient::ServiceDeathNotifier::serviceDied(
+ uint64_t /* cookie */,
+ const wp<::android::hidl::base::V1_0::IBase>& /* who */) {
+ sp<IMediaRecorderClient> listener = mListener.promote();
+ if (listener != NULL) {
+ listener->notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, mWhich);
+ } else {
+ ALOGW("listener for process %d death is gone", mWhich);
+ }
+}
+
+void MediaRecorderClient::ServiceDeathNotifier::unlinkToDeath() {
+ if (mService != nullptr) {
+ mService->unlinkToDeath(this);
+ mService = nullptr;
+ } else if (mOmx != nullptr) {
+ mOmx->unlinkToDeath(this);
+ mOmx = nullptr;
+ }
+}
+
+void MediaRecorderClient::clearDeathNotifiers() {
+ if (mCameraDeathListener != nullptr) {
+ mCameraDeathListener->unlinkToDeath();
+ mCameraDeathListener = nullptr;
+ }
+ if (mCodecDeathListener != nullptr) {
+ mCodecDeathListener->unlinkToDeath();
+ mCodecDeathListener = nullptr;
+ }
+}
+
status_t MediaRecorderClient::setListener(const sp<IMediaRecorderClient>& listener)
{
ALOGV("setListener");
+ clearDeathNotifiers();
Mutex::Autolock lock(mLock);
if (mRecorder == NULL) {
ALOGE("recorder is not initialized");
@@ -395,10 +439,25 @@
}
sCameraChecked = true;
- binder = sm->getService(String16("media.codec"));
- mCodecDeathListener = new ServiceDeathNotifier(binder, listener,
- MediaPlayerService::MEDIACODEC_PROCESS_DEATH);
- binder->linkToDeath(mCodecDeathListener);
+ int32_t trebleOmx = property_get_int32("persist.media.treble_omx", -1);
+ if ((trebleOmx == 1) || ((trebleOmx == -1) &&
+ property_get_bool("persist.hal.binderization", 0))) {
+ // Treble IOmx
+ sp<IOmx> omx = IOmx::getService();
+ if (omx == nullptr) {
+ ALOGE("Treble IOmx not available");
+ return NO_INIT;
+ }
+ mCodecDeathListener = new ServiceDeathNotifier(omx, listener,
+ MediaPlayerService::MEDIACODEC_PROCESS_DEATH);
+ omx->linkToDeath(mCodecDeathListener, 0);
+ } else {
+ // Legacy IOMX
+ binder = sm->getService(String16("media.codec"));
+ mCodecDeathListener = new ServiceDeathNotifier(binder, listener,
+ MediaPlayerService::MEDIACODEC_PROCESS_DEATH);
+ binder->linkToDeath(mCodecDeathListener);
+ }
return OK;
}
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index 8ddd680..101b8f6 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -20,6 +20,8 @@
#include <media/IMediaRecorder.h>
+#include <android/hardware/media/omx/1.0/IOmx.h>
+
namespace android {
struct MediaRecorderBase;
@@ -28,22 +30,36 @@
class MediaRecorderClient : public BnMediaRecorder
{
- class ServiceDeathNotifier: public IBinder::DeathRecipient
+ typedef ::android::hardware::media::omx::V1_0::IOmx IOmx;
+
+ class ServiceDeathNotifier :
+ public IBinder::DeathRecipient,
+ public ::android::hardware::hidl_death_recipient
{
public:
ServiceDeathNotifier(
const sp<IBinder>& service,
const sp<IMediaRecorderClient>& listener,
int which);
+ ServiceDeathNotifier(
+ const sp<IOmx>& omx,
+ const sp<IMediaRecorderClient>& listener,
+ int which);
virtual ~ServiceDeathNotifier();
virtual void binderDied(const wp<IBinder>& who);
-
+ virtual void serviceDied(
+ uint64_t cookie,
+ const wp<::android::hidl::base::V1_0::IBase>& who);
+ void unlinkToDeath();
private:
int mWhich;
sp<IBinder> mService;
+ sp<IOmx> mOmx;
wp<IMediaRecorderClient> mListener;
};
+ void clearDeathNotifiers();
+
public:
virtual status_t setCamera(const sp<hardware::ICamera>& camera,
const sp<ICameraRecordingProxy>& proxy);
@@ -84,8 +100,8 @@
const String16& opPackageName);
virtual ~MediaRecorderClient();
- sp<IBinder::DeathRecipient> mCameraDeathListener;
- sp<IBinder::DeathRecipient> mCodecDeathListener;
+ sp<ServiceDeathNotifier> mCameraDeathListener;
+ sp<ServiceDeathNotifier> mCodecDeathListener;
pid_t mPid;
Mutex mLock;
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index d00e377..170659a 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -1812,15 +1812,17 @@
return OK;
}
+ mPauseStartTimeUs = systemTime() / 1000;
+ sp<MetaData> meta = new MetaData;
+ meta->setInt64(kKeyTime, mPauseStartTimeUs);
+
if (mAudioEncoderSource != NULL) {
mAudioEncoderSource->pause();
}
if (mVideoEncoderSource != NULL) {
- mVideoEncoderSource->pause();
+ mVideoEncoderSource->pause(meta.get());
}
- mPauseStartTimeUs = systemTime() / 1000;
-
return OK;
}
@@ -1835,6 +1837,8 @@
return OK;
}
+ int64_t resumeStartTimeUs = systemTime() / 1000;
+
int64_t bufferStartTimeUs = 0;
bool allSourcesStarted = true;
for (const auto &source : { mAudioEncoderSource, mVideoEncoderSource }) {
@@ -1855,18 +1859,20 @@
mPauseStartTimeUs = bufferStartTimeUs;
}
// 30 ms buffer to avoid timestamp overlap
- mTotalPausedDurationUs += (systemTime() / 1000) - mPauseStartTimeUs - 30000;
+ mTotalPausedDurationUs += resumeStartTimeUs - mPauseStartTimeUs - 30000;
}
double timeOffset = -mTotalPausedDurationUs;
if (mCaptureFpsEnable) {
timeOffset *= mCaptureFps / mFrameRate;
}
+ sp<MetaData> meta = new MetaData;
+ meta->setInt64(kKeyTime, resumeStartTimeUs);
for (const auto &source : { mAudioEncoderSource, mVideoEncoderSource }) {
if (source == nullptr) {
continue;
}
source->setInputBufferTimeOffset((int64_t)timeOffset);
- source->start();
+ source->start(meta.get());
}
mPauseStartTimeUs = 0;
@@ -1883,6 +1889,12 @@
mCameraSourceTimeLapse = NULL;
}
+ if (mVideoEncoderSource != NULL) {
+ int64_t stopTimeUs = systemTime() / 1000;
+ sp<MetaData> meta = new MetaData;
+ err = mVideoEncoderSource->setStopStimeUs(stopTimeUs);
+ }
+
if (mWriter != NULL) {
err = mWriter->stop();
mWriter.clear();
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 3235e81..3f56725 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -575,7 +575,7 @@
changeState(mUninitializedState);
- updateTrebleFlag();
+ mTrebleFlag = false;
}
ACodec::~ACodec() {
@@ -6229,11 +6229,12 @@
CHECK(mCodec->mOMXNode == NULL);
OMXClient client;
- if ((mCodec->updateTrebleFlag() ?
- client.connectTreble() : client.connect()) != OK) {
+ bool trebleFlag;
+ if (client.connect(&trebleFlag) != OK) {
mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
return false;
}
+ mCodec->setTrebleFlag(trebleFlag);
sp<IOMX> omx = client.interface();
@@ -6553,7 +6554,7 @@
if (mCodec->mCreateInputBuffersSuspended) {
err = statusFromBinderStatus(
- mCodec->mGraphicBufferSource->setSuspend(true));
+ mCodec->mGraphicBufferSource->setSuspend(true, -1));
if (err != OK) {
ALOGE("[%s] Unable to configure option to suspend (err %d)",
@@ -7117,8 +7118,10 @@
return INVALID_OPERATION;
}
+ int64_t suspendStartTimeUs = -1;
+ (void) params->findInt64("drop-start-time-us", &suspendStartTimeUs);
status_t err = statusFromBinderStatus(
- mGraphicBufferSource->setSuspend(dropInputFrames != 0));
+ mGraphicBufferSource->setSuspend(dropInputFrames != 0, suspendStartTimeUs));
if (err != OK) {
ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err);
@@ -7126,6 +7129,22 @@
}
}
+ int64_t stopTimeUs;
+ if (params->findInt64("stop-time-us", &stopTimeUs)) {
+ if (mGraphicBufferSource == NULL) {
+ ALOGE("[%s] Invalid to set stop time without surface",
+ mComponentName.c_str());
+ return INVALID_OPERATION;
+ }
+ status_t err = statusFromBinderStatus(
+ mGraphicBufferSource->setStopTimeUs(stopTimeUs));
+
+ if (err != OK) {
+ ALOGE("Failed to set parameter 'stop-time-us' (err %d)", err);
+ return err;
+ }
+ }
+
int32_t dummy;
if (params->findInt32("request-sync", &dummy)) {
status_t err = requestIDRFrame();
@@ -7676,8 +7695,7 @@
}
OMXClient client;
- status_t err = getTrebleFlag() ?
- client.connectTreble() : client.connect();
+ status_t err = client.connect();
if (err != OK) {
return err;
}
@@ -7893,11 +7911,8 @@
return OK;
}
-bool ACodec::updateTrebleFlag() {
- mTrebleFlag = bool(property_get_bool("debug.treble_omx", 0));
- ALOGV("updateTrebleFlag() returns %s",
- mTrebleFlag ? "true" : "false");
- return mTrebleFlag;
+void ACodec::setTrebleFlag(bool trebleFlag) {
+ mTrebleFlag = trebleFlag;
}
bool ACodec::getTrebleFlag() const {
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 5981b35..059a730 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -363,8 +363,20 @@
return postSynchronouslyAndReturnError(msg);
}
-status_t MediaCodecSource::pause() {
- (new AMessage(kWhatPause, mReflector))->post();
+
+status_t MediaCodecSource::setStopStimeUs(int64_t stopTimeUs) {
+ if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
+ return OK;
+ }
+ sp<AMessage> msg = new AMessage(kWhatSetStopTimeOffset, mReflector);
+ msg->setInt64("stop-time-us", stopTimeUs);
+ return postSynchronouslyAndReturnError(msg);
+}
+
+status_t MediaCodecSource::pause(MetaData* params) {
+ sp<AMessage> msg = new AMessage(kWhatPause, mReflector);
+ msg->setObject("meta", params);
+ msg->post();
return OK;
}
@@ -624,22 +636,13 @@
}
}
-void MediaCodecSource::suspend() {
- CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
- if (mEncoder != NULL) {
- sp<AMessage> params = new AMessage;
- params->setInt32("drop-input-frames", true);
- mEncoder->setParameters(params);
- }
-}
-
-void MediaCodecSource::resume(int64_t skipFramesBeforeUs) {
+void MediaCodecSource::resume(int64_t resumeStartTimeUs) {
CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
if (mEncoder != NULL) {
sp<AMessage> params = new AMessage;
params->setInt32("drop-input-frames", false);
- if (skipFramesBeforeUs > 0) {
- params->setInt64("skip-frames-before", skipFramesBeforeUs);
+ if (resumeStartTimeUs > 0) {
+ params->setInt64("drop-start-time-us", resumeStartTimeUs);
}
mEncoder->setParameters(params);
}
@@ -661,7 +664,7 @@
mFirstSampleSystemTimeUs = systemTime() / 1000;
if (mPausePending) {
mPausePending = false;
- onPause();
+ onPause(mFirstSampleSystemTimeUs);
mbuf->release();
mAvailEncoderInputIndices.push_back(bufferIndex);
return OK;
@@ -728,6 +731,10 @@
ALOGE("Failed to start while we're stopping");
return INVALID_OPERATION;
}
+ int64_t startTimeUs;
+ if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
+ startTimeUs = -1ll;
+ }
if (mStarted) {
ALOGI("MediaCodecSource (%s) resuming", mIsVideo ? "video" : "audio");
@@ -739,7 +746,7 @@
mEncoder->requestIDRFrame();
}
if (mFlags & FLAG_USE_SURFACE_INPUT) {
- resume();
+ resume(startTimeUs);
} else {
CHECK(mPuller != NULL);
mPuller->resume();
@@ -752,11 +759,14 @@
status_t err = OK;
if (mFlags & FLAG_USE_SURFACE_INPUT) {
- int64_t startTimeUs;
- if (!params || !params->findInt64(kKeyTime, &startTimeUs)) {
- startTimeUs = -1ll;
+ if (mEncoder != NULL) {
+ sp<AMessage> params = new AMessage;
+ params->setInt32("drop-input-frames", false);
+ if (startTimeUs >= 0) {
+ params->setInt64("skip-frames-before", startTimeUs);
+ }
+ mEncoder->setParameters(params);
}
- resume(startTimeUs);
} else {
CHECK(mPuller != NULL);
sp<MetaData> meta = params;
@@ -781,9 +791,12 @@
return OK;
}
-void MediaCodecSource::onPause() {
- if (mFlags & FLAG_USE_SURFACE_INPUT) {
- suspend();
+void MediaCodecSource::onPause(int64_t pauseStartTimeUs) {
+ if ((mFlags & FLAG_USE_SURFACE_INPUT) && (mEncoder != NULL)) {
+ sp<AMessage> params = new AMessage;
+ params->setInt32("drop-input-frames", true);
+ params->setInt64("drop-start-time-us", pauseStartTimeUs);
+ mEncoder->setParameters(params);
} else {
CHECK(mPuller != NULL);
mPuller->pause();
@@ -871,7 +884,7 @@
mFirstSampleSystemTimeUs = systemTime() / 1000;
if (mPausePending) {
mPausePending = false;
- onPause();
+ onPause(mFirstSampleSystemTimeUs);
mbuf->release();
break;
}
@@ -1000,6 +1013,7 @@
ALOGV("source (%s) stopped", mIsVideo ? "video" : "audio");
}
signalEOS();
+ break;
}
case kWhatPause:
@@ -1007,7 +1021,14 @@
if (mFirstSampleSystemTimeUs < 0) {
mPausePending = true;
} else {
- onPause();
+ sp<RefBase> obj;
+ CHECK(msg->findObject("meta", &obj));
+ MetaData *params = static_cast<MetaData *>(obj.get());
+ int64_t pauseStartTimeUs = -1;
+ if (params == NULL || !params->findInt64(kKeyTime, &pauseStartTimeUs)) {
+ pauseStartTimeUs = -1ll;
+ }
+ onPause(pauseStartTimeUs);
}
break;
}
@@ -1030,6 +1051,26 @@
response->postReply(replyID);
break;
}
+ case kWhatSetStopTimeOffset:
+ {
+ sp<AReplyToken> replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+ status_t err = OK;
+ int64_t stopTimeUs;
+ CHECK(msg->findInt64("stop-time-us", &stopTimeUs));
+
+ // Propagate the timestamp offset to GraphicBufferSource.
+ if (mFlags & FLAG_USE_SURFACE_INPUT) {
+ sp<AMessage> params = new AMessage;
+ params->setInt64("stop-time-us", stopTimeUs);
+ err = mEncoder->setParameters(params);
+ }
+
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", err);
+ response->postReply(replyID);
+ break;
+ }
case kWhatGetFirstSampleSystemTimeUs:
{
sp<AReplyToken> replyID;
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index b4e694c..b77ee1d 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -22,6 +22,7 @@
#endif
#include <utils/Log.h>
+#include <cutils/properties.h>
#include <binder/IServiceManager.h>
#include <media/IMediaCodecService.h>
@@ -36,7 +37,22 @@
OMXClient::OMXClient() {
}
-status_t OMXClient::connect() {
+status_t OMXClient::connect(bool* trebleFlag) {
+ int32_t trebleOmx = property_get_int32("persist.media.treble_omx", -1);
+ if ((trebleOmx == 1) || ((trebleOmx == -1) &&
+ property_get_bool("persist.hal.binderization", 0))) {
+ if (trebleFlag != nullptr) {
+ *trebleFlag = true;
+ }
+ return connectTreble();
+ }
+ if (trebleFlag != nullptr) {
+ *trebleFlag = false;
+ }
+ return connectLegacy();
+}
+
+status_t OMXClient::connectLegacy() {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> codecbinder = sm->getService(String16("media.codec"));
sp<IMediaCodecService> codecservice = interface_cast<IMediaCodecService>(codecbinder);
@@ -67,6 +83,7 @@
return NO_INIT;
}
mOMX = new utils::LWOmx(tOmx);
+ ALOGI("Treble IOmx obtained");
return OK;
}
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index a0ddc28..2f457ac 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -76,11 +76,13 @@
mInitCheck(UNKNOWN_ERROR),
mExecuting(false),
mSuspended(false),
+ mStopTimeUs(-1),
mLastDataSpace(HAL_DATASPACE_UNKNOWN),
mNumFramesAvailable(0),
mNumBufferAcquired(0),
mEndOfStream(false),
mEndOfStreamSent(false),
+ mLastActionTimeUs(-1ll),
mPrevOriginalTimeUs(-1ll),
mSkipFramesBeforeNs(-1ll),
mRepeatAfterUs(-1ll),
@@ -171,7 +173,7 @@
// If EOS has already been signaled, and there are no more frames to
// submit, try to send EOS now as well.
- if (mEndOfStream && mNumFramesAvailable == 0) {
+ if (mStopTimeUs == -1 && mEndOfStream && mNumFramesAvailable == 0) {
submitEndOfInputStream_l();
}
@@ -348,8 +350,8 @@
ALOGV("buffer freed, %zu frames avail (eos=%d)",
mNumFramesAvailable, mEndOfStream);
fillCodecBuffer_l();
- } else if (mEndOfStream) {
- // No frames available, but EOS is pending, so use this buffer to
+ } else if (mEndOfStream && mStopTimeUs == -1) {
+ // No frames available, but EOS is pending and no stop time, so use this buffer to
// send that.
ALOGV("buffer freed, EOS pending");
submitEndOfInputStream_l();
@@ -387,7 +389,7 @@
bool GraphicBufferSource::fillCodecBuffer_l() {
CHECK(mExecuting && mNumFramesAvailable > 0);
- if (mSuspended) {
+ if (mSuspended && mActionQueue.empty()) {
return false;
}
@@ -408,8 +410,85 @@
return false;
}
+ int64_t itemTimeUs = item.mTimestamp / 1000;
+
mNumFramesAvailable--;
+ // Process ActionItem in the Queue if there is any. If a buffer's timestamp
+ // is smaller than the first action's timestamp, no action need to be performed.
+ // If buffer's timestamp is larger or equal than the last action's timestamp,
+ // only the last action needs to be performed as all the acitions before the
+ // the action are overridden by the last action. For the other cases, traverse
+ // the Queue to find the newest action that with timestamp smaller or equal to
+ // the buffer's timestamp. For example, an action queue like
+ // [pause, 1s], [resume 2us], [pause 3us], [resume 4us], [pause 5us].... Upon
+ // receiving a buffer with timestamp 3.5us, only the action [pause, 3us] needs
+ // to be handled and [pause, 1us], [resume 2us] will be discarded.
+ bool dropped = false;
+ bool done = false;
+ if (!mActionQueue.empty()) {
+ // First scan to check if bufferTimestamp is smaller than first action's timestamp.
+ ActionItem nextAction = *(mActionQueue.begin());
+ if (itemTimeUs < nextAction.mActionTimeUs) {
+ ALOGV("No action. buffer timestamp %lld us < action timestamp: %lld us",
+ (long long)itemTimeUs, (long long)nextAction.mActionTimeUs);
+ // All the actions are ahead. No action need to perform now.
+ // Release the buffer if is in suspended state, or process the buffer
+ // if not in suspended state.
+ dropped = mSuspended;
+ done = true;
+ }
+
+ if (!done) {
+ List<ActionItem>::iterator it = mActionQueue.begin();
+ while(it != mActionQueue.end()) {
+ nextAction = *it;
+ mActionQueue.erase(it);
+ if (nextAction.mActionTimeUs > itemTimeUs) {
+ break;
+ }
+ ++it;
+ }
+
+ CHECK(itemTimeUs >= nextAction.mActionTimeUs);
+ switch (nextAction.mAction) {
+ case ActionItem::PAUSE:
+ {
+ mSuspended = true;
+ dropped = true;
+ ALOGV("RUNNING/PAUSE -> PAUSE at buffer %lld us PAUSE Time: %lld us",
+ (long long)itemTimeUs, (long long)nextAction.mActionTimeUs);
+ break;
+ }
+ case ActionItem::RESUME:
+ {
+ mSuspended = false;
+ ALOGV("PAUSE/RUNNING -> RUNNING at buffer %lld us RESUME Time: %lld us",
+ (long long)itemTimeUs, (long long)nextAction.mActionTimeUs);
+ break;
+ }
+ case ActionItem::STOP:
+ {
+ ALOGV("RUNNING/PAUSE -> STOP at buffer %lld us STOP Time: %lld us",
+ (long long)itemTimeUs, (long long)nextAction.mActionTimeUs);
+ dropped = true;
+ // Clear the whole ActionQueue as recording is done
+ mActionQueue.clear();
+ submitEndOfInputStream_l();
+ break;
+ }
+ default:
+ ALOGE("Unknown action type");
+ return false;
+ }
+ }
+ }
+
+ if (dropped) {
+ releaseBuffer(item.mSlot, item.mFrameNumber, item.mFence);
+ return true;
+ }
+
if (item.mDataSpace != mLastDataSpace) {
onDataSpaceChanged_l(
item.mDataSpace, (android_pixel_format)mBufferSlot[item.mSlot]->getPixelFormat());
@@ -419,7 +498,6 @@
// only submit sample if start time is unspecified, or sample
// is queued after the specified start time
- bool dropped = false;
if (mSkipFramesBeforeNs < 0ll || item.mTimestamp >= mSkipFramesBeforeNs) {
// if start time is set, offset time stamp by start time
if (mSkipFramesBeforeNs > 0) {
@@ -719,12 +797,12 @@
ALOGV("onFrameAvailable exec=%d avail=%zu",
mExecuting, mNumFramesAvailable);
- if (mOMXNode == NULL || mEndOfStream || mSuspended) {
- if (mEndOfStream) {
+ if (mOMXNode == NULL || mEndOfStreamSent || (mSuspended && mActionQueue.empty())) {
+ if (mEndOfStreamSent) {
// This should only be possible if a new buffer was queued after
// EOS was signaled, i.e. the app is misbehaving.
- ALOGW("onFrameAvailable: EOS is set, ignoring frame");
+ ALOGW("onFrameAvailable: EOS is sent, ignoring frame");
} else {
ALOGV("onFrameAvailable: suspended, ignoring frame");
}
@@ -875,44 +953,74 @@
mPrevCaptureUs = -1ll;
mPrevFrameUs = -1ll;
mInputBufferTimeOffsetUs = 0;
+ mStopTimeUs = -1;
+ mActionQueue.clear();
}
return Status::ok();
}
-Status GraphicBufferSource::setSuspend(bool suspend) {
- ALOGV("setSuspend=%d", suspend);
+Status GraphicBufferSource::setSuspend(bool suspend, int64_t suspendStartTimeUs) {
+ ALOGV("setSuspend=%d at time %lld us", suspend, (long long)suspendStartTimeUs);
Mutex::Autolock autoLock(mMutex);
- if (suspend) {
- mSuspended = true;
-
- while (mNumFramesAvailable > 0) {
- BufferItem item;
- status_t err = acquireBuffer(&item);
-
- if (err != OK) {
- ALOGE("setSuspend: acquireBuffer returned err=%d", err);
- break;
- }
-
- --mNumFramesAvailable;
-
- releaseBuffer(item.mSlot, item.mFrameNumber, item.mFence);
- }
- return Status::ok();
+ if (mStopTimeUs != -1) {
+ ALOGE("setSuspend failed as STOP action is pending");
+ return Status::fromServiceSpecificError(INVALID_OPERATION);
}
- mSuspended = false;
+ // Push the action to the queue.
+ if (suspendStartTimeUs != -1) {
+ // suspendStartTimeUs must be smaller or equal to current systemTime.
+ int64_t currentSystemTimeUs = systemTime() / 1000;
+ if (suspendStartTimeUs > currentSystemTimeUs) {
+ ALOGE("setSuspend failed. %lld is larger than current system time %lld us",
+ (long long)suspendStartTimeUs, (long long)currentSystemTimeUs);
+ return Status::fromServiceSpecificError(INVALID_OPERATION);
+ }
+ if (mLastActionTimeUs != -1 && suspendStartTimeUs < mLastActionTimeUs) {
+ ALOGE("setSuspend failed. %lld is smaller than last action time %lld us",
+ (long long)suspendStartTimeUs, (long long)mLastActionTimeUs);
+ return Status::fromServiceSpecificError(INVALID_OPERATION);
+ }
+ mLastActionTimeUs = suspendStartTimeUs;
+ ActionItem action;
+ action.mAction = suspend ? ActionItem::PAUSE : ActionItem::RESUME;
+ action.mActionTimeUs = suspendStartTimeUs;
+ ALOGV("Push %s action into actionQueue", suspend ? "PAUSE" : "RESUME");
+ mActionQueue.push_back(action);
+ } else {
+ if (suspend) {
+ mSuspended = true;
- if (mExecuting && mNumFramesAvailable == 0 && mRepeatBufferDeferred) {
- if (repeatLatestBuffer_l()) {
- ALOGV("suspend/deferred repeatLatestBuffer_l SUCCESS");
+ while (mNumFramesAvailable > 0) {
+ BufferItem item;
+ status_t err = acquireBuffer(&item);
- mRepeatBufferDeferred = false;
+ if (err != OK) {
+ ALOGE("setSuspend: acquireBuffer returned err=%d", err);
+ break;
+ }
+
+ --mNumFramesAvailable;
+
+ releaseBuffer(item.mSlot, item.mFrameNumber, item.mFence);
+ }
+ return Status::ok();
} else {
- ALOGV("suspend/deferred repeatLatestBuffer_l FAILURE");
+
+ mSuspended = false;
+
+ if (mExecuting && mNumFramesAvailable == 0 && mRepeatBufferDeferred) {
+ if (repeatLatestBuffer_l()) {
+ ALOGV("suspend/deferred repeatLatestBuffer_l SUCCESS");
+
+ mRepeatBufferDeferred = false;
+ } else {
+ ALOGV("suspend/deferred repeatLatestBuffer_l FAILURE");
+ }
+ }
}
}
return Status::ok();
@@ -973,6 +1081,36 @@
return Status::ok();
}
+Status GraphicBufferSource::setStopTimeUs(int64_t stopTimeUs) {
+ ALOGV("setStopTimeUs: %lld us", (long long)stopTimeUs);
+ Mutex::Autolock autoLock(mMutex);
+
+ if (mStopTimeUs != -1) {
+ // Ignore if stop time has already been set
+ return Status::ok();
+ }
+
+ // stopTimeUs must be smaller or equal to current systemTime.
+ int64_t currentSystemTimeUs = systemTime() / 1000;
+ if (stopTimeUs > currentSystemTimeUs) {
+ ALOGE("setStopTimeUs failed. %lld is larger than current system time %lld us",
+ (long long)stopTimeUs, (long long)currentSystemTimeUs);
+ return Status::fromServiceSpecificError(INVALID_OPERATION);
+ }
+ if (mLastActionTimeUs != -1 && stopTimeUs < mLastActionTimeUs) {
+ ALOGE("setSuspend failed. %lld is smaller than last action time %lld us",
+ (long long)stopTimeUs, (long long)mLastActionTimeUs);
+ return Status::fromServiceSpecificError(INVALID_OPERATION);
+ }
+ mLastActionTimeUs = stopTimeUs;
+ ActionItem action;
+ action.mAction = ActionItem::STOP;
+ action.mActionTimeUs = stopTimeUs;
+ mActionQueue.push_back(action);
+ mStopTimeUs = stopTimeUs;
+ return Status::ok();
+}
+
Status GraphicBufferSource::setTimeLapseConfig(int64_t timePerFrameUs, int64_t timePerCaptureUs) {
ALOGV("setTimeLapseConfig: timePerFrameUs=%lld, timePerCaptureUs=%lld",
(long long)timePerFrameUs, (long long)timePerCaptureUs);
@@ -1013,15 +1151,15 @@
// Set the end-of-stream flag. If no frames are pending from the
// BufferQueue, and a codec buffer is available, and we're executing,
- // we initiate the EOS from here. Otherwise, we'll let
- // codecBufferEmptied() (or omxExecuting) do it.
+ // and there is no stop timestamp, we initiate the EOS from here.
+ // Otherwise, we'll let codecBufferEmptied() (or omxExecuting) do it.
//
// Note: if there are no pending frames and all codec buffers are
// available, we *must* submit the EOS from here or we'll just
// stall since no future events are expected.
mEndOfStream = true;
- if (mExecuting && mNumFramesAvailable == 0) {
+ if (mStopTimeUs == -1 && mExecuting && mNumFramesAvailable == 0) {
submitEndOfInputStream_l();
}
diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h
index 153a035..475548e 100644
--- a/media/libstagefright/omx/GraphicBufferSource.h
+++ b/media/libstagefright/omx/GraphicBufferSource.h
@@ -101,14 +101,18 @@
// data space.
Status configure(const sp<IOMXNode>& omxNode, int32_t dataSpace) override;
- // This is called after the last input frame has been submitted. We
- // need to submit an empty buffer with the EOS flag set. If we don't
- // have a codec buffer ready, we just set the mEndOfStream flag.
+ // This is called after the last input frame has been submitted or buffer
+ // timestamp is greater or equal than stopTimeUs. We need to submit an empty
+ // buffer with the EOS flag set. If we don't have a codec buffer ready,
+ // we just set the mEndOfStream flag.
Status signalEndOfInputStream() override;
// If suspend is true, all incoming buffers (including those currently
- // in the BufferQueue) will be discarded until the suspension is lifted.
- Status setSuspend(bool suspend) override;
+ // in the BufferQueue) with timestamp larger than timeUs will be discarded
+ // until the suspension is lifted. If suspend is false, all incoming buffers
+ // including those currently in the BufferQueue) with timestamp larger than
+ // timeUs will be processed. timeUs uses SYSTEM_TIME_MONOTONIC time base.
+ Status setSuspend(bool suspend, int64_t timeUs) override;
// Specifies the interval after which we requeue the buffer previously
// queued to the encoder. This is useful in the case of surface flinger
@@ -135,6 +139,10 @@
// be dropped and not submitted to encoder
Status setStartTimeUs(int64_t startTimeUs) override;
+ // Sets the stop time us (in system time), samples after which should be dropped
+ // and not submitted to encoder. timeUs uses SYSTEM_TIME_MONOTONIC time base.
+ Status setStopTimeUs(int64_t stopTimeUs) override;
+
// Sets the desired color aspects, e.g. to be used when producer does not specify a dataspace.
Status setColorAspects(int32_t aspectsPacked) override;
@@ -229,6 +237,9 @@
bool mSuspended;
+ // The time to stop sending buffers.
+ int64_t mStopTimeUs;
+
// Last dataspace seen
android_dataspace mLastDataSpace;
@@ -259,6 +270,25 @@
// Tracks codec buffers.
Vector<CodecBuffer> mCodecBuffers;
+ struct ActionItem {
+ typedef enum {
+ PAUSE,
+ RESUME,
+ STOP
+ } ActionType;
+ ActionType mAction;
+ int64_t mActionTimeUs;
+ };
+
+ // Maintain last action timestamp to ensure all the action timestamps are
+ // monotonically increasing.
+ int64_t mLastActionTimeUs;
+
+ // An action queue that queue up all the actions sent to GraphicBufferSource.
+ // STOP action should only show up at the end of the list as all the actions
+ // after a STOP action will be discarded. mActionQueue is protected by mMutex.
+ List<ActionItem> mActionQueue;
+
////
friend struct AHandlerReflector<GraphicBufferSource>;
diff --git a/media/libstagefright/omx/hal/1.0/impl/Conversion.h b/media/libstagefright/omx/hal/1.0/impl/Conversion.h
index 3433bb4..d164faa 100644
--- a/media/libstagefright/omx/hal/1.0/impl/Conversion.h
+++ b/media/libstagefright/omx/hal/1.0/impl/Conversion.h
@@ -560,6 +560,76 @@
}
/**
+ * \brief Wrap `GraphicBuffer` in `AnwBuffer`.
+ *
+ * \param[out] t The wrapper of type `AnwBuffer`.
+ * \param[in] l The source `GraphicBuffer`.
+ */
+// wrap: GraphicBuffer -> AnwBuffer
+inline void wrapAs(AnwBuffer* t, GraphicBuffer const& l) {
+ t->attr.width = l.getWidth();
+ t->attr.height = l.getHeight();
+ t->attr.stride = l.getStride();
+ t->attr.format = static_cast<PixelFormat>(l.getPixelFormat());
+ t->attr.layerCount = l.getLayerCount();
+ t->attr.usage = l.getUsage();
+ t->attr.id = l.getId();
+ t->attr.generationNumber = l.getGenerationNumber();
+ t->nativeHandle = hidl_handle(l.handle);
+}
+
+/**
+ * \brief Convert `AnwBuffer` to `GraphicBuffer`.
+ *
+ * \param[out] l The destination `GraphicBuffer`.
+ * \param[in] t The source `AnwBuffer`.
+ *
+ * This function will duplicate all file descriptors in \p t.
+ */
+// convert: AnwBuffer -> GraphicBuffer
+// Ref: frameworks/native/libs/ui/GraphicBuffer.cpp: GraphicBuffer::flatten
+inline bool convertTo(GraphicBuffer* l, AnwBuffer const& t) {
+ native_handle_t* handle = t.nativeHandle == nullptr ?
+ nullptr : native_handle_clone(t.nativeHandle);
+
+ size_t const numInts = 12 + (handle ? handle->numInts : 0);
+ int32_t* ints = new int32_t[numInts];
+
+ size_t numFds = static_cast<size_t>(handle ? handle->numFds : 0);
+ int* fds = new int[numFds];
+
+ ints[0] = 'GBFR';
+ ints[1] = static_cast<int32_t>(t.attr.width);
+ ints[2] = static_cast<int32_t>(t.attr.height);
+ ints[3] = static_cast<int32_t>(t.attr.stride);
+ ints[4] = static_cast<int32_t>(t.attr.format);
+ ints[5] = static_cast<int32_t>(t.attr.layerCount);
+ ints[6] = static_cast<int32_t>(t.attr.usage);
+ ints[7] = static_cast<int32_t>(t.attr.id >> 32);
+ ints[8] = static_cast<int32_t>(t.attr.id & 0xFFFFFFFF);
+ ints[9] = static_cast<int32_t>(t.attr.generationNumber);
+ ints[10] = 0;
+ ints[11] = 0;
+ if (handle) {
+ ints[10] = static_cast<int32_t>(handle->numFds);
+ ints[11] = static_cast<int32_t>(handle->numInts);
+ int* intsStart = handle->data + handle->numFds;
+ std::copy(handle->data, intsStart, fds);
+ std::copy(intsStart, intsStart + handle->numInts, &ints[12]);
+ }
+
+ void const* constBuffer = static_cast<void const*>(ints);
+ size_t size = numInts * sizeof(int32_t);
+ int const* constFds = static_cast<int const*>(fds);
+ status_t status = l->unflatten(constBuffer, size, constFds, numFds);
+
+ delete [] fds;
+ delete [] ints;
+ native_handle_delete(handle);
+ return status == NO_ERROR;
+}
+
+/**
* \brief Wrap `OMXBuffer` in `CodecBuffer`.
*
* \param[out] t The wrapper of type `CodecBuffer`.
@@ -568,8 +638,8 @@
*/
// wrap: OMXBuffer -> CodecBuffer
inline bool wrapAs(CodecBuffer* t, OMXBuffer const& l) {
- t->nativeHandle = hidl_handle();
t->sharedMemory = hidl_memory();
+ t->nativeHandle = hidl_handle();
switch (l.mBufferType) {
case OMXBuffer::kBufferTypeInvalid: {
t->type = CodecBuffer::Type::INVALID;
@@ -599,7 +669,6 @@
t->attr.anwBuffer.format = static_cast<PixelFormat>(1);
t->attr.anwBuffer.layerCount = 0;
t->attr.anwBuffer.usage = 0;
- t->nativeHandle = hidl_handle();
return true;
}
t->attr.anwBuffer.width = l.mGraphicBuffer->getWidth();
@@ -609,12 +678,12 @@
l.mGraphicBuffer->getPixelFormat());
t->attr.anwBuffer.layerCount = l.mGraphicBuffer->getLayerCount();
t->attr.anwBuffer.usage = l.mGraphicBuffer->getUsage();
- t->nativeHandle = hidl_handle(l.mGraphicBuffer->handle);
+ t->nativeHandle = l.mGraphicBuffer->handle;
return true;
}
case OMXBuffer::kBufferTypeNativeHandle: {
t->type = CodecBuffer::Type::NATIVE_HANDLE;
- t->nativeHandle = hidl_handle(l.mNativeHandle->handle());
+ t->nativeHandle = l.mNativeHandle->handle();
return true;
}
}
@@ -650,16 +719,14 @@
*l = OMXBuffer(sp<GraphicBuffer>(nullptr));
return true;
}
- *l = OMXBuffer(sp<GraphicBuffer>(new GraphicBuffer(
- t.attr.anwBuffer.width,
- t.attr.anwBuffer.height,
- static_cast<::android::PixelFormat>(
- t.attr.anwBuffer.format),
- t.attr.anwBuffer.layerCount,
- t.attr.anwBuffer.usage,
- t.attr.anwBuffer.stride,
- native_handle_clone(t.nativeHandle),
- true)));
+ AnwBuffer anwBuffer;
+ anwBuffer.nativeHandle = t.nativeHandle;
+ anwBuffer.attr = t.attr.anwBuffer;
+ sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
+ if (!convertTo(graphicBuffer.get(), anwBuffer)) {
+ return false;
+ }
+ *l = OMXBuffer(graphicBuffer);
return true;
}
case CodecBuffer::Type::NATIVE_HANDLE: {
@@ -834,76 +901,6 @@
}
/**
- * \brief Wrap `GraphicBuffer` in `AnwBuffer`.
- *
- * \param[out] t The wrapper of type `AnwBuffer`.
- * \param[in] l The source `GraphicBuffer`.
- */
-// wrap: GraphicBuffer -> AnwBuffer
-inline void wrapAs(AnwBuffer* t, GraphicBuffer const& l) {
- t->attr.width = l.getWidth();
- t->attr.height = l.getHeight();
- t->attr.stride = l.getStride();
- t->attr.format = static_cast<PixelFormat>(l.getPixelFormat());
- t->attr.layerCount = l.getLayerCount();
- t->attr.usage = l.getUsage();
- t->attr.id = l.getId();
- t->attr.generationNumber = l.getGenerationNumber();
- t->nativeHandle = hidl_handle(l.handle);
-}
-
-/**
- * \brief Convert `AnwBuffer` to `GraphicBuffer`.
- *
- * \param[out] l The destination `GraphicBuffer`.
- * \param[in] t The source `AnwBuffer`.
- *
- * This function will duplicate all file descriptors in \p t.
- */
-// convert: AnwBuffer -> GraphicBuffer
-// Ref: frameworks/native/libs/ui/GraphicBuffer.cpp: GraphicBuffer::flatten
-inline bool convertTo(GraphicBuffer* l, AnwBuffer const& t) {
- native_handle_t* handle = t.nativeHandle == nullptr ?
- nullptr : native_handle_clone(t.nativeHandle);
-
- size_t const numInts = 12 + (handle ? handle->numInts : 0);
- int32_t* ints = new int32_t[numInts];
-
- size_t numFds = static_cast<size_t>(handle ? handle->numFds : 0);
- int* fds = new int[numFds];
-
- ints[0] = 'GBFR';
- ints[1] = static_cast<int32_t>(t.attr.width);
- ints[2] = static_cast<int32_t>(t.attr.height);
- ints[3] = static_cast<int32_t>(t.attr.stride);
- ints[4] = static_cast<int32_t>(t.attr.format);
- ints[5] = static_cast<int32_t>(t.attr.layerCount);
- ints[6] = static_cast<int32_t>(t.attr.usage);
- ints[7] = static_cast<int32_t>(t.attr.id >> 32);
- ints[8] = static_cast<int32_t>(t.attr.id & 0xFFFFFFFF);
- ints[9] = static_cast<int32_t>(t.attr.generationNumber);
- ints[10] = 0;
- ints[11] = 0;
- if (handle) {
- ints[10] = static_cast<int32_t>(handle->numFds);
- ints[11] = static_cast<int32_t>(handle->numInts);
- int* intsStart = handle->data + handle->numFds;
- std::copy(handle->data, intsStart, fds);
- std::copy(intsStart, intsStart + handle->numInts, &ints[12]);
- }
-
- void const* constBuffer = static_cast<void const*>(ints);
- size_t size = numInts * sizeof(int32_t);
- int const* constFds = static_cast<int const*>(fds);
- status_t status = l->unflatten(constBuffer, size, constFds, numFds);
-
- delete [] fds;
- delete [] ints;
- native_handle_delete(handle);
- return status == NO_ERROR;
-}
-
-/**
* Conversion functions for types outside media
* ============================================
*
diff --git a/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.cpp b/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.cpp
index 8ba2924..af9cf03 100644
--- a/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.cpp
+++ b/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.cpp
@@ -39,8 +39,9 @@
new TWOmxNode(omxNode), toHardwareDataspace(dataSpace)));
}
-::android::binder::Status LWGraphicBufferSource::setSuspend(bool suspend) {
- return toBinderStatus(mBase->setSuspend(suspend));
+::android::binder::Status LWGraphicBufferSource::setSuspend(
+ bool suspend, int64_t timeUs) {
+ return toBinderStatus(mBase->setSuspend(suspend, timeUs));
}
::android::binder::Status LWGraphicBufferSource::setRepeatPreviousFrameDelayUs(
@@ -63,6 +64,11 @@
return toBinderStatus(mBase->setStartTimeUs(startTimeUs));
}
+::android::binder::Status LWGraphicBufferSource::setStopTimeUs(
+ int64_t stopTimeUs) {
+ return toBinderStatus(mBase->setStopTimeUs(stopTimeUs));
+}
+
::android::binder::Status LWGraphicBufferSource::setColorAspects(
int32_t aspects) {
return toBinderStatus(mBase->setColorAspects(
@@ -89,8 +95,9 @@
return Void();
}
-Return<void> TWGraphicBufferSource::setSuspend(bool suspend) {
- mBase->setSuspend(suspend);
+Return<void> TWGraphicBufferSource::setSuspend(
+ bool suspend, int64_t timeUs) {
+ mBase->setSuspend(suspend, timeUs);
return Void();
}
@@ -116,6 +123,10 @@
return Void();
}
+Return<void> TWGraphicBufferSource::setStopTimeUs(int64_t stopTimeUs) {
+ return toHardwareStatus(mBase->setStopTimeUs(stopTimeUs));
+}
+
Return<void> TWGraphicBufferSource::setColorAspects(
const ColorAspects& aspects) {
mBase->setColorAspects(toCompactColorAspects(aspects));
diff --git a/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.h b/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.h
index 69efdde..dd6168e 100644
--- a/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.h
+++ b/media/libstagefright/omx/hal/1.0/impl/WGraphicBufferSource.h
@@ -69,13 +69,14 @@
LWGraphicBufferSource(sp<TGraphicBufferSource> const& base);
::android::binder::Status configure(
const sp<IOMXNode>& omxNode, int32_t dataSpace) override;
- ::android::binder::Status setSuspend(bool suspend) override;
+ ::android::binder::Status setSuspend(bool suspend, int64_t timeUs) override;
::android::binder::Status setRepeatPreviousFrameDelayUs(
int64_t repeatAfterUs) override;
::android::binder::Status setMaxFps(float maxFps) override;
::android::binder::Status setTimeLapseConfig(
int64_t timePerFrameUs, int64_t timePerCaptureUs) override;
::android::binder::Status setStartTimeUs(int64_t startTimeUs) override;
+ ::android::binder::Status setStopTimeUs(int64_t stopTimeUs) override;
::android::binder::Status setColorAspects(int32_t aspects) override;
::android::binder::Status setTimeOffsetUs(int64_t timeOffsetsUs) override;
::android::binder::Status signalEndOfInputStream() override;
@@ -86,12 +87,13 @@
TWGraphicBufferSource(sp<LGraphicBufferSource> const& base);
Return<void> configure(
const sp<IOmxNode>& omxNode, Dataspace dataspace) override;
- Return<void> setSuspend(bool suspend) override;
+ Return<void> setSuspend(bool suspend, int64_t timeUs) override;
Return<void> setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) override;
Return<void> setMaxFps(float maxFps) override;
Return<void> setTimeLapseConfig(
int64_t timePerFrameUs, int64_t timePerCaptureUs) override;
Return<void> setStartTimeUs(int64_t startTimeUs) override;
+ Return<void> setStopTimeUs(int64_t stopTimeUs) override;
Return<void> setColorAspects(const ColorAspects& aspects) override;
Return<void> setTimeOffsetUs(int64_t timeOffsetUs) override;
Return<void> signalEndOfInputStream() override;
diff --git a/media/libstagefright/omx/hal/1.0/utils/Conversion.h b/media/libstagefright/omx/hal/1.0/utils/Conversion.h
index 2319cd9..5050687 100644
--- a/media/libstagefright/omx/hal/1.0/utils/Conversion.h
+++ b/media/libstagefright/omx/hal/1.0/utils/Conversion.h
@@ -560,6 +560,76 @@
}
/**
+ * \brief Wrap `GraphicBuffer` in `AnwBuffer`.
+ *
+ * \param[out] t The wrapper of type `AnwBuffer`.
+ * \param[in] l The source `GraphicBuffer`.
+ */
+// wrap: GraphicBuffer -> AnwBuffer
+inline void wrapAs(AnwBuffer* t, GraphicBuffer const& l) {
+ t->attr.width = l.getWidth();
+ t->attr.height = l.getHeight();
+ t->attr.stride = l.getStride();
+ t->attr.format = static_cast<PixelFormat>(l.getPixelFormat());
+ t->attr.layerCount = l.getLayerCount();
+ t->attr.usage = l.getUsage();
+ t->attr.id = l.getId();
+ t->attr.generationNumber = l.getGenerationNumber();
+ t->nativeHandle = hidl_handle(l.handle);
+}
+
+/**
+ * \brief Convert `AnwBuffer` to `GraphicBuffer`.
+ *
+ * \param[out] l The destination `GraphicBuffer`.
+ * \param[in] t The source `AnwBuffer`.
+ *
+ * This function will duplicate all file descriptors in \p t.
+ */
+// convert: AnwBuffer -> GraphicBuffer
+// Ref: frameworks/native/libs/ui/GraphicBuffer.cpp: GraphicBuffer::flatten
+inline bool convertTo(GraphicBuffer* l, AnwBuffer const& t) {
+ native_handle_t* handle = t.nativeHandle == nullptr ?
+ nullptr : native_handle_clone(t.nativeHandle);
+
+ size_t const numInts = 12 + (handle ? handle->numInts : 0);
+ int32_t* ints = new int32_t[numInts];
+
+ size_t numFds = static_cast<size_t>(handle ? handle->numFds : 0);
+ int* fds = new int[numFds];
+
+ ints[0] = 'GBFR';
+ ints[1] = static_cast<int32_t>(t.attr.width);
+ ints[2] = static_cast<int32_t>(t.attr.height);
+ ints[3] = static_cast<int32_t>(t.attr.stride);
+ ints[4] = static_cast<int32_t>(t.attr.format);
+ ints[5] = static_cast<int32_t>(t.attr.layerCount);
+ ints[6] = static_cast<int32_t>(t.attr.usage);
+ ints[7] = static_cast<int32_t>(t.attr.id >> 32);
+ ints[8] = static_cast<int32_t>(t.attr.id & 0xFFFFFFFF);
+ ints[9] = static_cast<int32_t>(t.attr.generationNumber);
+ ints[10] = 0;
+ ints[11] = 0;
+ if (handle) {
+ ints[10] = static_cast<int32_t>(handle->numFds);
+ ints[11] = static_cast<int32_t>(handle->numInts);
+ int* intsStart = handle->data + handle->numFds;
+ std::copy(handle->data, intsStart, fds);
+ std::copy(intsStart, intsStart + handle->numInts, &ints[12]);
+ }
+
+ void const* constBuffer = static_cast<void const*>(ints);
+ size_t size = numInts * sizeof(int32_t);
+ int const* constFds = static_cast<int const*>(fds);
+ status_t status = l->unflatten(constBuffer, size, constFds, numFds);
+
+ delete [] fds;
+ delete [] ints;
+ native_handle_delete(handle);
+ return status == NO_ERROR;
+}
+
+/**
* \brief Wrap `OMXBuffer` in `CodecBuffer`.
*
* \param[out] t The wrapper of type `CodecBuffer`.
@@ -568,8 +638,8 @@
*/
// wrap: OMXBuffer -> CodecBuffer
inline bool wrapAs(CodecBuffer* t, OMXBuffer const& l) {
- t->nativeHandle = hidl_handle();
t->sharedMemory = hidl_memory();
+ t->nativeHandle = hidl_handle();
switch (l.mBufferType) {
case OMXBuffer::kBufferTypeInvalid: {
t->type = CodecBuffer::Type::INVALID;
@@ -599,7 +669,6 @@
t->attr.anwBuffer.format = static_cast<PixelFormat>(1);
t->attr.anwBuffer.layerCount = 0;
t->attr.anwBuffer.usage = 0;
- t->nativeHandle = hidl_handle();
return true;
}
t->attr.anwBuffer.width = l.mGraphicBuffer->getWidth();
@@ -609,12 +678,12 @@
l.mGraphicBuffer->getPixelFormat());
t->attr.anwBuffer.layerCount = l.mGraphicBuffer->getLayerCount();
t->attr.anwBuffer.usage = l.mGraphicBuffer->getUsage();
- t->nativeHandle = hidl_handle(l.mGraphicBuffer->handle);
+ t->nativeHandle = l.mGraphicBuffer->handle;
return true;
}
case OMXBuffer::kBufferTypeNativeHandle: {
t->type = CodecBuffer::Type::NATIVE_HANDLE;
- t->nativeHandle = hidl_handle(l.mNativeHandle->handle());
+ t->nativeHandle = l.mNativeHandle->handle();
return true;
}
}
@@ -650,16 +719,14 @@
*l = OMXBuffer(sp<GraphicBuffer>(nullptr));
return true;
}
- *l = OMXBuffer(sp<GraphicBuffer>(new GraphicBuffer(
- t.attr.anwBuffer.width,
- t.attr.anwBuffer.height,
- static_cast<::android::PixelFormat>(
- t.attr.anwBuffer.format),
- t.attr.anwBuffer.layerCount,
- t.attr.anwBuffer.usage,
- t.attr.anwBuffer.stride,
- native_handle_clone(t.nativeHandle),
- true)));
+ AnwBuffer anwBuffer;
+ anwBuffer.nativeHandle = t.nativeHandle;
+ anwBuffer.attr = t.attr.anwBuffer;
+ sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
+ if (!convertTo(graphicBuffer.get(), anwBuffer)) {
+ return false;
+ }
+ *l = OMXBuffer(graphicBuffer);
return true;
}
case CodecBuffer::Type::NATIVE_HANDLE: {
@@ -834,76 +901,6 @@
}
/**
- * \brief Wrap `GraphicBuffer` in `AnwBuffer`.
- *
- * \param[out] t The wrapper of type `AnwBuffer`.
- * \param[in] l The source `GraphicBuffer`.
- */
-// wrap: GraphicBuffer -> AnwBuffer
-inline void wrapAs(AnwBuffer* t, GraphicBuffer const& l) {
- t->attr.width = l.getWidth();
- t->attr.height = l.getHeight();
- t->attr.stride = l.getStride();
- t->attr.format = static_cast<PixelFormat>(l.getPixelFormat());
- t->attr.layerCount = l.getLayerCount();
- t->attr.usage = l.getUsage();
- t->attr.id = l.getId();
- t->attr.generationNumber = l.getGenerationNumber();
- t->nativeHandle = hidl_handle(l.handle);
-}
-
-/**
- * \brief Convert `AnwBuffer` to `GraphicBuffer`.
- *
- * \param[out] l The destination `GraphicBuffer`.
- * \param[in] t The source `AnwBuffer`.
- *
- * This function will duplicate all file descriptors in \p t.
- */
-// convert: AnwBuffer -> GraphicBuffer
-// Ref: frameworks/native/libs/ui/GraphicBuffer.cpp: GraphicBuffer::flatten
-inline bool convertTo(GraphicBuffer* l, AnwBuffer const& t) {
- native_handle_t* handle = t.nativeHandle == nullptr ?
- nullptr : native_handle_clone(t.nativeHandle);
-
- size_t const numInts = 12 + (handle ? handle->numInts : 0);
- int32_t* ints = new int32_t[numInts];
-
- size_t numFds = static_cast<size_t>(handle ? handle->numFds : 0);
- int* fds = new int[numFds];
-
- ints[0] = 'GBFR';
- ints[1] = static_cast<int32_t>(t.attr.width);
- ints[2] = static_cast<int32_t>(t.attr.height);
- ints[3] = static_cast<int32_t>(t.attr.stride);
- ints[4] = static_cast<int32_t>(t.attr.format);
- ints[5] = static_cast<int32_t>(t.attr.layerCount);
- ints[6] = static_cast<int32_t>(t.attr.usage);
- ints[7] = static_cast<int32_t>(t.attr.id >> 32);
- ints[8] = static_cast<int32_t>(t.attr.id & 0xFFFFFFFF);
- ints[9] = static_cast<int32_t>(t.attr.generationNumber);
- ints[10] = 0;
- ints[11] = 0;
- if (handle) {
- ints[10] = static_cast<int32_t>(handle->numFds);
- ints[11] = static_cast<int32_t>(handle->numInts);
- int* intsStart = handle->data + handle->numFds;
- std::copy(handle->data, intsStart, fds);
- std::copy(intsStart, intsStart + handle->numInts, &ints[12]);
- }
-
- void const* constBuffer = static_cast<void const*>(ints);
- size_t size = numInts * sizeof(int32_t);
- int const* constFds = static_cast<int const*>(fds);
- status_t status = l->unflatten(constBuffer, size, constFds, numFds);
-
- delete [] fds;
- delete [] ints;
- native_handle_delete(handle);
- return status == NO_ERROR;
-}
-
-/**
* Conversion functions for types outside media
* ============================================
*
diff --git a/media/libstagefright/omx/hal/1.0/utils/WGraphicBufferSource.cpp b/media/libstagefright/omx/hal/1.0/utils/WGraphicBufferSource.cpp
index a23b48a..afe8bc5 100644
--- a/media/libstagefright/omx/hal/1.0/utils/WGraphicBufferSource.cpp
+++ b/media/libstagefright/omx/hal/1.0/utils/WGraphicBufferSource.cpp
@@ -39,8 +39,9 @@
new TWOmxNode(omxNode), toHardwareDataspace(dataSpace)));
}
-::android::binder::Status LWGraphicBufferSource::setSuspend(bool suspend) {
- return toBinderStatus(mBase->setSuspend(suspend));
+::android::binder::Status LWGraphicBufferSource::setSuspend(
+ bool suspend, int64_t timeUs) {
+ return toBinderStatus(mBase->setSuspend(suspend, timeUs));
}
::android::binder::Status LWGraphicBufferSource::setRepeatPreviousFrameDelayUs(
@@ -63,6 +64,11 @@
return toBinderStatus(mBase->setStartTimeUs(startTimeUs));
}
+::android::binder::Status LWGraphicBufferSource::setStopTimeUs(
+ int64_t stopTimeUs) {
+ return toBinderStatus(mBase->setStopTimeUs(stopTimeUs));
+}
+
::android::binder::Status LWGraphicBufferSource::setColorAspects(
int32_t aspects) {
return toBinderStatus(mBase->setColorAspects(
@@ -89,8 +95,8 @@
return Void();
}
-Return<void> TWGraphicBufferSource::setSuspend(bool suspend) {
- mBase->setSuspend(suspend);
+Return<void> TWGraphicBufferSource::setSuspend(bool suspend, int64_t timeUs) {
+ mBase->setSuspend(suspend, timeUs);
return Void();
}
@@ -116,6 +122,10 @@
return Void();
}
+Return<void> TWGraphicBufferSource::setStopTimeUs(int64_t stopTimeUs) {
+ return toHardwareStatus(mBase->setStopTimeUs(stopTimeUs));
+}
+
Return<void> TWGraphicBufferSource::setColorAspects(
const ColorAspects& aspects) {
mBase->setColorAspects(toCompactColorAspects(aspects));
diff --git a/media/libstagefright/omx/hal/1.0/utils/WGraphicBufferSource.h b/media/libstagefright/omx/hal/1.0/utils/WGraphicBufferSource.h
index d21de42..1b09cbd 100644
--- a/media/libstagefright/omx/hal/1.0/utils/WGraphicBufferSource.h
+++ b/media/libstagefright/omx/hal/1.0/utils/WGraphicBufferSource.h
@@ -69,13 +69,14 @@
LWGraphicBufferSource(sp<TGraphicBufferSource> const& base);
::android::binder::Status configure(
const sp<IOMXNode>& omxNode, int32_t dataSpace) override;
- ::android::binder::Status setSuspend(bool suspend) override;
+ ::android::binder::Status setSuspend(bool suspend, int64_t timeUs) override;
::android::binder::Status setRepeatPreviousFrameDelayUs(
int64_t repeatAfterUs) override;
::android::binder::Status setMaxFps(float maxFps) override;
::android::binder::Status setTimeLapseConfig(
int64_t timePerFrameUs, int64_t timePerCaptureUs) override;
::android::binder::Status setStartTimeUs(int64_t startTimeUs) override;
+ ::android::binder::Status setStopTimeUs(int64_t stopTimeUs) override;
::android::binder::Status setColorAspects(int32_t aspects) override;
::android::binder::Status setTimeOffsetUs(int64_t timeOffsetsUs) override;
::android::binder::Status signalEndOfInputStream() override;
@@ -86,12 +87,13 @@
TWGraphicBufferSource(sp<LGraphicBufferSource> const& base);
Return<void> configure(
const sp<IOmxNode>& omxNode, Dataspace dataspace) override;
- Return<void> setSuspend(bool suspend) override;
+ Return<void> setSuspend(bool suspend, int64_t timeUs) override;
Return<void> setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) override;
Return<void> setMaxFps(float maxFps) override;
Return<void> setTimeLapseConfig(
int64_t timePerFrameUs, int64_t timePerCaptureUs) override;
Return<void> setStartTimeUs(int64_t startTimeUs) override;
+ Return<void> setStopTimeUs(int64_t stopTimeUs) override;
Return<void> setColorAspects(const ColorAspects& aspects) override;
Return<void> setTimeOffsetUs(int64_t timeOffsetUs) override;
Return<void> signalEndOfInputStream() override;
diff --git a/media/libstagefright/omx/tests/Android.mk b/media/libstagefright/omx/tests/Android.mk
index 5e4ba10..08deaab 100644
--- a/media/libstagefright/omx/tests/Android.mk
+++ b/media/libstagefright/omx/tests/Android.mk
@@ -2,15 +2,26 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES = \
- OMXHarness.cpp \
+ OMXHarness.cpp \
LOCAL_SHARED_LIBRARIES := \
- libstagefright libbinder libmedia libutils liblog libstagefright_foundation
+ libstagefright \
+ libbinder \
+ libmedia \
+ libutils \
+ liblog \
+ libstagefright_foundation \
+ libcutils \
+ libhidlbase \
+ libhidlmemory \
+ android.hidl.memory@1.0 \
+ android.hardware.media.omx@1.0 \
+ android.hardware.media.omx@1.0-utils
LOCAL_C_INCLUDES := \
- $(TOP)/frameworks/av/media/libstagefright \
- $(TOP)/frameworks/native/include/media/openmax \
- $(TOP)/system/libhidl/base/include \
+ $(TOP)/frameworks/av/media/libstagefright \
+ $(TOP)/frameworks/native/include/media/openmax \
+ $(TOP)/system/libhidl/base/include \
LOCAL_CFLAGS += -Werror -Wall
@@ -29,14 +40,14 @@
LOCAL_MODULE_TAGS := tests
LOCAL_SRC_FILES := \
- FrameDropper_test.cpp \
+ FrameDropper_test.cpp \
LOCAL_SHARED_LIBRARIES := \
- libstagefright_omx \
- libutils \
+ libstagefright_omx \
+ libutils \
LOCAL_C_INCLUDES := \
- frameworks/av/media/libstagefright/omx \
+ frameworks/av/media/libstagefright/omx \
LOCAL_CFLAGS += -Werror -Wall
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index 1ce5d1a..8817cf9 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -39,6 +39,8 @@
#include <media/stagefright/MetaData.h>
#include <media/stagefright/SimpleDecodingSource.h>
#include <media/OMXBuffer.h>
+#include <android/hardware/media/omx/1.0/IOmx.h>
+#include <omx/hal/1.0/utils/WOmx.h>
#define DEFAULT_TIMEOUT 500000
@@ -64,7 +66,7 @@
/////////////////////////////////////////////////////////////////////
Harness::Harness()
- : mInitCheck(NO_INIT) {
+ : mInitCheck(NO_INIT), mUseTreble(false) {
mInitCheck = initOMX();
}
@@ -76,10 +78,23 @@
}
status_t Harness::initOMX() {
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder = sm->getService(String16("media.codec"));
- sp<IMediaCodecService> service = interface_cast<IMediaCodecService>(binder);
- mOMX = service->getOMX();
+ int32_t trebleOmx = property_get_int32("persist.media.treble_omx", -1);
+ if ((trebleOmx == 1) || ((trebleOmx == -1) &&
+ property_get_bool("persist.hal.binderization", 0))) {
+ using namespace ::android::hardware::media::omx::V1_0;
+ sp<IOmx> tOmx = IOmx::getService();
+ if (tOmx == nullptr) {
+ return NO_INIT;
+ }
+ mOMX = new utils::LWOmx(tOmx);
+ mUseTreble = true;
+ } else {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16("media.codec"));
+ sp<IMediaCodecService> service = interface_cast<IMediaCodecService>(binder);
+ mOMX = service->getOMX();
+ mUseTreble = false;
+ }
return mOMX != 0 ? OK : NO_INIT;
}
@@ -197,7 +212,6 @@
EXPECT((err) == OK, info " failed")
status_t Harness::allocatePortBuffers(
- const sp<MemoryDealer> &dealer,
OMX_U32 portIndex, Vector<Buffer> *buffers) {
buffers->clear();
@@ -207,11 +221,27 @@
for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
Buffer buffer;
- buffer.mMemory = dealer->allocate(def.nBufferSize);
buffer.mFlags = 0;
- CHECK(buffer.mMemory != NULL);
+ if (mUseTreble) {
+ bool success;
+ auto transStatus = mAllocator->allocate(def.nBufferSize,
+ [&success, &buffer](
+ bool s,
+ hidl_memory const& m) {
+ success = s;
+ buffer.mHidlMemory = m;
+ });
+ EXPECT(transStatus.isOk(),
+ "Cannot call allocator");
+ EXPECT(success,
+ "Cannot allocate memory");
+ err = mOMXNode->useBuffer(portIndex, buffer.mHidlMemory, &buffer.mID);
+ } else {
+ buffer.mMemory = mDealer->allocate(def.nBufferSize);
+ CHECK(buffer.mMemory != NULL);
+ err = mOMXNode->useBuffer(portIndex, buffer.mMemory, &buffer.mID);
+ }
- err = mOMXNode->useBuffer(portIndex, buffer.mMemory, &buffer.mID);
EXPECT_SUCCESS(err, "useBuffer");
buffers->push(buffer);
@@ -279,7 +309,13 @@
return OK;
}
- sp<MemoryDealer> dealer = new MemoryDealer(16 * 1024 * 1024, "OMXHarness");
+ if (mUseTreble) {
+ mAllocator = IAllocator::getService("ashmem");
+ EXPECT(mAllocator != nullptr,
+ "Cannot obtain hidl AshmemAllocator");
+ } else {
+ mDealer = new MemoryDealer(16 * 1024 * 1024, "OMXHarness");
+ }
sp<CodecObserver> observer = new CodecObserver(this, ++mCurGeneration);
@@ -305,14 +341,14 @@
// Now allocate buffers.
Vector<Buffer> inputBuffers;
- err = allocatePortBuffers(dealer, 0, &inputBuffers);
+ err = allocatePortBuffers(0, &inputBuffers);
EXPECT_SUCCESS(err, "allocatePortBuffers(input)");
err = dequeueMessageForNode(&msg, DEFAULT_TIMEOUT);
CHECK_EQ(err, (status_t)TIMED_OUT);
Vector<Buffer> outputBuffers;
- err = allocatePortBuffers(dealer, 1, &outputBuffers);
+ err = allocatePortBuffers(1, &outputBuffers);
EXPECT_SUCCESS(err, "allocatePortBuffers(output)");
err = dequeueMessageForNode(&msg, DEFAULT_TIMEOUT);
diff --git a/media/libstagefright/omx/tests/OMXHarness.h b/media/libstagefright/omx/tests/OMXHarness.h
index 0fe00a6..022707f 100644
--- a/media/libstagefright/omx/tests/OMXHarness.h
+++ b/media/libstagefright/omx/tests/OMXHarness.h
@@ -23,6 +23,9 @@
#include <utils/Vector.h>
#include <utils/threads.h>
+#include <binder/MemoryDealer.h>
+#include <android/hidl/memory/1.0/IAllocator.h>
+#include <android/hidl/memory/1.0/IMemory.h>
#include <OMX_Component.h>
namespace android {
@@ -30,12 +33,15 @@
class MemoryDealer;
struct Harness : public RefBase {
+ typedef hidl::memory::V1_0::IMemory TMemory;
+ typedef hardware::hidl_memory hidl_memory;
enum BufferFlags {
kBufferBusy = 1
};
struct Buffer {
IOMX::buffer_id mID;
sp<IMemory> mMemory;
+ hidl_memory mHidlMemory;
uint32_t mFlags;
};
@@ -54,7 +60,6 @@
OMX_U32 portIndex, OMX_PARAM_PORTDEFINITIONTYPE *def);
status_t allocatePortBuffers(
- const sp<MemoryDealer> &dealer,
OMX_U32 portIndex, Vector<Buffer> *buffers);
status_t setRole(const char *role);
@@ -74,6 +79,8 @@
virtual ~Harness();
private:
+ typedef hidl::memory::V1_0::IAllocator IAllocator;
+
friend struct NodeReaper;
struct CodecObserver;
@@ -86,6 +93,9 @@
Condition mMessageAddedCondition;
int32_t mLastMsgGeneration;
int32_t mCurGeneration;
+ bool mUseTreble;
+ sp<MemoryDealer> mDealer;
+ sp<IAllocator> mAllocator;
status_t initOMX();
diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk
index a4cb66d..f7597db 100644
--- a/media/mediaserver/Android.mk
+++ b/media/mediaserver/Android.mk
@@ -12,23 +12,24 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- main_mediaserver.cpp
+ main_mediaserver.cpp
LOCAL_SHARED_LIBRARIES := \
- libresourcemanagerservice \
- liblog \
- libmediaplayerservice \
- libutils \
- libbinder \
- libicuuc \
+ libresourcemanagerservice \
+ liblog \
+ libmediaplayerservice \
+ libutils \
+ libbinder \
+ libicuuc \
+ android.hardware.media.omx@1.0 \
LOCAL_STATIC_LIBRARIES := \
libicuandroid_utils \
libregistermsext
LOCAL_C_INCLUDES := \
- frameworks/av/media/libmediaplayerservice \
- frameworks/av/services/mediaresourcemanager \
+ frameworks/av/media/libmediaplayerservice \
+ frameworks/av/services/mediaresourcemanager \
LOCAL_MODULE:= mediaserver
LOCAL_32_BIT_ONLY := true
diff --git a/services/mediacodec/Android.mk b/services/mediacodec/Android.mk
index e8a8264..cb14bb5 100644
--- a/services/mediacodec/Android.mk
+++ b/services/mediacodec/Android.mk
@@ -3,7 +3,12 @@
# service library
include $(CLEAR_VARS)
LOCAL_SRC_FILES := MediaCodecService.cpp
-LOCAL_SHARED_LIBRARIES := libmedia libbinder libutils liblog libstagefright_omx
+LOCAL_SHARED_LIBRARIES := \
+ libmedia \
+ libbinder \
+ libutils \
+ liblog \
+ libstagefright_omx
LOCAL_C_INCLUDES := \
$(TOP)/frameworks/av/media/libstagefright \
$(TOP)/frameworks/native/include/media/openmax
@@ -16,8 +21,16 @@
include $(CLEAR_VARS)
LOCAL_REQUIRED_MODULES_arm := mediacodec-seccomp.policy
LOCAL_SRC_FILES := main_codecservice.cpp
-LOCAL_SHARED_LIBRARIES := libmedia libmediacodecservice libbinder libutils \
- libbase libavservices_minijail libcutils \
+LOCAL_SHARED_LIBRARIES := \
+ libmedia \
+ libmediacodecservice \
+ libbinder \
+ libutils \
+ liblog \
+ libbase \
+ libavservices_minijail \
+ libcutils \
+ libhwbinder \
android.hardware.media.omx@1.0
LOCAL_C_INCLUDES := \
$(TOP)/frameworks/av/media/libstagefright \
diff --git a/services/mediacodec/main_codecservice.cpp b/services/mediacodec/main_codecservice.cpp
index 6cbb368..983bbba 100644
--- a/services/mediacodec/main_codecservice.cpp
+++ b/services/mediacodec/main_codecservice.cpp
@@ -32,6 +32,7 @@
#include "minijail.h"
#include <android/hardware/media/omx/1.0/IOmx.h>
+#include <hidl/HidlTransportSupport.h>
using namespace android;
@@ -45,13 +46,13 @@
SetUpMinijail(kSeccompPolicyPath, std::string());
strcpy(argv[0], "media.codec");
- sp<ProcessState> proc(ProcessState::self());
- sp<IServiceManager> sm = defaultServiceManager();
- MediaCodecService::instantiate();
- // Treble
- bool useTrebleOmx = bool(property_get_bool("debug.treble_omx", 0));
- if (useTrebleOmx) {
+ ::android::hardware::configureRpcThreadpool(64, false);
+ sp<ProcessState> proc(ProcessState::self());
+
+ int32_t trebleOmx = property_get_int32("persist.media.treble_omx", -1);
+ if ((trebleOmx == 1) || ((trebleOmx == -1) &&
+ property_get_bool("persist.hal.binderization", 0))) {
using namespace ::android::hardware::media::omx::V1_0;
sp<IOmx> omx = IOmx::getService(true);
if (omx == nullptr) {
@@ -59,8 +60,11 @@
} else if (omx->registerAsService("default") != OK) {
LOG(ERROR) << "Cannot register a Treble IOmx service.";
} else {
- LOG(VERBOSE) << "Treble IOmx service created.";
+ LOG(INFO) << "Treble IOmx service created.";
}
+ } else {
+ MediaCodecService::instantiate();
+ LOG(INFO) << "Non-Treble IOMX service created.";
}
ProcessState::self()->startThreadPool();
diff --git a/services/radio/HidlUtils.cpp b/services/radio/HidlUtils.cpp
index 3b33386..6895377 100644
--- a/services/radio/HidlUtils.cpp
+++ b/services/radio/HidlUtils.cpp
@@ -134,14 +134,18 @@
halInfo->channel, halInfo->subChannel);
}
+// TODO(twasilczyk): drop unnecessary channel info
//static
void HidlUtils::convertMetaDataFromHal(radio_metadata_t **metadata,
const hidl_vec<MetaData>& halMetadata,
- uint32_t channel,
- uint32_t subChannel)
+ uint32_t channel __unused,
+ uint32_t subChannel __unused)
{
- radio_metadata_allocate(metadata, channel, subChannel);
+ if (metadata == nullptr || *metadata == nullptr) {
+ ALOGE("destination metadata buffer is a nullptr");
+ return;
+ }
for (size_t i = 0; i < halMetadata.size(); i++) {
radio_metadata_key_t key = static_cast<radio_metadata_key_t>(halMetadata[i].key);
radio_metadata_type_t type = static_cast<radio_metadata_key_t>(halMetadata[i].type);
diff --git a/services/radio/RadioHalHidl.cpp b/services/radio/RadioHalHidl.cpp
index 032d3fd..3dcf2f3 100644
--- a/services/radio/RadioHalHidl.cpp
+++ b/services/radio/RadioHalHidl.cpp
@@ -20,7 +20,7 @@
#include <media/audiohal/hidl/HalDeathHandler.h>
#include <utils/Log.h>
#include <utils/misc.h>
-#include <system/radio_metadata.h>
+#include <system/RadioMetadataWrapper.h>
#include <android/hardware/broadcastradio/1.0/IBroadcastRadioFactory.h>
#include "RadioHalHidl.h"
@@ -261,27 +261,25 @@
Return<void> RadioHalHidl::Tuner::tuneComplete(Result result, const ProgramInfo& info)
{
ALOGV("%s IN", __FUNCTION__);
- radio_hal_event_t event;
- memset(&event, 0, sizeof(radio_hal_event_t));
+ radio_hal_event_t event = {};
+ RadioMetadataWrapper metadataWrapper(&event.info.metadata);
+
event.type = RADIO_EVENT_TUNED;
event.status = HidlUtils::convertHalResult(result);
HidlUtils::convertProgramInfoFromHal(&event.info, &info);
onCallback(&event);
- radio_metadata_deallocate(event.info.metadata);
return Return<void>();
}
Return<void> RadioHalHidl::Tuner::afSwitch(const ProgramInfo& info)
{
ALOGV("%s IN", __FUNCTION__);
- radio_hal_event_t event;
- memset(&event, 0, sizeof(radio_hal_event_t));
+ radio_hal_event_t event = {};
+ RadioMetadataWrapper metadataWrapper(&event.info.metadata);
+
event.type = RADIO_EVENT_AF_SWITCH;
HidlUtils::convertProgramInfoFromHal(&event.info, &info);
onCallback(&event);
- if (event.info.metadata != NULL) {
- radio_metadata_deallocate(event.info.metadata);
- }
return Return<void>();
}
@@ -319,14 +317,12 @@
const ::android::hardware::hidl_vec<MetaData>& metadata)
{
ALOGV("%s IN", __FUNCTION__);
- radio_hal_event_t event;
- memset(&event, 0, sizeof(radio_hal_event_t));
+ radio_hal_event_t event = {};
+ RadioMetadataWrapper metadataWrapper(&event.info.metadata);
+
event.type = RADIO_EVENT_METADATA;
HidlUtils::convertMetaDataFromHal(&event.metadata, metadata, channel, subChannel);
onCallback(&event);
- if (event.metadata != NULL) {
- radio_metadata_deallocate(event.info.metadata);
- }
return Return<void>();
}