Merge "audio: fix device address conversion to HIDL"
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
index f642373..ca865a8 100644
--- a/include/media/IMediaPlayer.h
+++ b/include/media/IMediaPlayer.h
@@ -24,6 +24,7 @@
#include <system/audio.h>
#include <media/IMediaSource.h>
+#include <media/drm/DrmAPI.h> // for DrmPlugin::* enum
// Fwd decl to make sure everyone agrees that the scope of struct sockaddr_in is
// global, and not in android::
@@ -89,6 +90,22 @@
virtual status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint) = 0;
virtual status_t getRetransmitEndpoint(struct sockaddr_in* endpoint) = 0;
virtual status_t setNextPlayer(const sp<IMediaPlayer>& next) = 0;
+ // ModDrm
+ virtual status_t prepareDrm(const uint8_t uuid[16], const int mode) = 0;
+ virtual status_t releaseDrm() = 0;
+ virtual status_t getKeyRequest(Vector<uint8_t> const& scope,
+ String8 const &mimeType,
+ DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8>& optionalParameters,
+ Vector<uint8_t>& request,
+ String8& defaultUrl,
+ DrmPlugin::KeyRequestType& keyRequestType) = 0;
+ virtual status_t provideKeyResponse(Vector<uint8_t>& releaseKeySetId,
+ Vector<uint8_t>& response,
+ Vector<uint8_t>& keySetId) = 0;
+ virtual status_t restoreKeys(Vector<uint8_t> const& keySetId) = 0;
+ virtual status_t getDrmPropertyString(String8 const& name, String8& value) = 0;
+ virtual status_t setDrmPropertyString(String8 const& name, String8 const& value) = 0;
// Invoke a generic method on the player by using opaque parcels
// for the request and reply.
diff --git a/include/media/MediaAnalyticsItem.h b/include/media/MediaAnalyticsItem.h
index a78aa8b..f050e7f 100644
--- a/include/media/MediaAnalyticsItem.h
+++ b/include/media/MediaAnalyticsItem.h
@@ -40,6 +40,7 @@
friend class MediaAnalyticsService;
friend class IMediaAnalyticsService;
+ friend class MediaMetricsJNI;
public:
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 0e815cb..4e18f1f 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -280,6 +280,34 @@
return INVALID_OPERATION;
}
+ // ModDrm
+ virtual status_t prepareDrm(const uint8_t uuid[16], const int mode) {
+ return INVALID_OPERATION;
+ }
+ virtual status_t releaseDrm() {
+ return INVALID_OPERATION;
+ }
+ virtual status_t getKeyRequest(Vector<uint8_t> const& scope, String8 const& mimeType,
+ DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8>& optionalParameters,
+ Vector<uint8_t>& request, String8& defaultUrl,
+ DrmPlugin::KeyRequestType& keyRequestType) {
+ return INVALID_OPERATION;
+ }
+ virtual status_t provideKeyResponse(Vector<uint8_t>& releaseKeySetId,
+ Vector<uint8_t>& response, Vector<uint8_t>& keySetId) {
+ return INVALID_OPERATION;
+ }
+ virtual status_t restoreKeys(Vector<uint8_t> const& keySetId) {
+ return INVALID_OPERATION;
+ }
+ virtual status_t getDrmPropertyString(String8 const& name, String8& value) {
+ return INVALID_OPERATION;
+ }
+ virtual status_t setDrmPropertyString(String8 const& name, String8 const& value) {
+ return INVALID_OPERATION;
+ }
+
private:
friend class MediaPlayerService;
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 5d7c25a..2c5ff1f 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -55,6 +55,7 @@
MEDIA_INFO = 200,
MEDIA_SUBTITLE_DATA = 201,
MEDIA_META_DATA = 202,
+ MEDIA_DRM_INFO = 210,
};
// Generic error codes for the media player framework. Errors are fatal, the
@@ -260,6 +261,19 @@
status_t getParameter(int key, Parcel* reply);
status_t setRetransmitEndpoint(const char* addrString, uint16_t port);
status_t setNextMediaPlayer(const sp<MediaPlayer>& player);
+ // ModDrm
+ status_t prepareDrm(const uint8_t uuid[16], const int mode);
+ status_t releaseDrm();
+ status_t getKeyRequest(Vector<uint8_t> const& scope, String8 const& mimeType,
+ DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8>& optionalParameters,
+ Vector<uint8_t>& request, String8& defaultUrl,
+ DrmPlugin::KeyRequestType& keyRequestType);
+ status_t provideKeyResponse(Vector<uint8_t>& releaseKeySetId,
+ Vector<uint8_t>& response, Vector<uint8_t>& keySetId);
+ status_t restoreKeys(Vector<uint8_t> const& keySetId);
+ status_t getDrmPropertyString(String8 const& name, String8& value);
+ status_t setDrmPropertyString(String8 const& name, String8 const& value);
private:
void clear_l();
diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h
index 2e367bf..699ae48 100644
--- a/include/media/stagefright/MediaCodec.h
+++ b/include/media/stagefright/MediaCodec.h
@@ -25,6 +25,7 @@
#include <media/hardware/CryptoAPI.h>
#include <media/MediaCodecInfo.h>
#include <media/MediaResource.h>
+#include <media/MediaAnalyticsItem.h>
#include <media/stagefright/foundation/AHandler.h>
#include <media/stagefright/FrameRenderTracker.h>
#include <utils/Vector.h>
@@ -172,6 +173,8 @@
status_t getName(AString *componentName) const;
+ status_t getMetrics(Parcel *reply);
+
status_t setParameters(const sp<AMessage> ¶ms);
// Create a MediaCodec notification message from a list of rendered or dropped render infos
@@ -298,6 +301,8 @@
sp<Surface> mSurface;
SoftwareRenderer *mSoftRenderer;
+ MediaAnalyticsItem *mAnalyticsItem;
+
sp<AMessage> mOutputFormat;
sp<AMessage> mInputFormat;
sp<AMessage> mCallback;
diff --git a/include/media/stagefright/MediaExtractor.h b/include/media/stagefright/MediaExtractor.h
index b460ef7..211f794 100644
--- a/include/media/stagefright/MediaExtractor.h
+++ b/include/media/stagefright/MediaExtractor.h
@@ -20,6 +20,7 @@
#include <media/IMediaExtractor.h>
#include <media/IMediaSource.h>
+#include <media/MediaAnalyticsItem.h>
namespace android {
@@ -69,7 +70,9 @@
protected:
MediaExtractor();
- virtual ~MediaExtractor() {}
+ virtual ~MediaExtractor();
+
+ MediaAnalyticsItem *mAnalyticsItem;
private:
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index 9ffde4e..966267a 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -70,8 +70,28 @@
SET_RETRANSMIT_ENDPOINT,
GET_RETRANSMIT_ENDPOINT,
SET_NEXT_PLAYER,
+ // ModDrm
+ PREPARE_DRM,
+ RELEASE_DRM,
+ GET_KEY_REQUEST,
+ PROVIDE_KEY_RESPONSE,
+ RESTORE_KEYS,
+ GET_DRM_PROPERTY_STRING,
+ SET_DRM_PROPERTY_STRING,
};
+// ModDrm helpers
+static void readVector(const Parcel& reply, Vector<uint8_t>& vector) {
+ uint32_t size = reply.readUint32();
+ vector.insertAt((size_t)0, size);
+ reply.read(vector.editArray(), size);
+}
+
+static void writeVector(Parcel& data, Vector<uint8_t> const& vector) {
+ data.writeUint32(vector.size());
+ data.write(vector.array(), vector.size());
+}
+
class BpMediaPlayer: public BpInterface<IMediaPlayer>
{
public:
@@ -447,6 +467,137 @@
return err;
}
+
+ // ModDrm
+ status_t prepareDrm(const uint8_t uuid[16], const int mode)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+
+ data.write(uuid, 16);
+ data.writeInt32(mode);
+
+ status_t status = remote()->transact(PREPARE_DRM, data, &reply);
+ if (status != OK) {
+ ALOGE("prepareDrm: binder call failed: %d", status);
+ return status;
+ }
+
+ return reply.readInt32();
+ }
+
+ status_t releaseDrm()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+
+ status_t status = remote()->transact(RELEASE_DRM, data, &reply);
+ if (status != OK) {
+ ALOGE("releaseDrm: binder call failed: %d", status);
+ return status;
+ }
+
+ return reply.readInt32();
+ }
+
+ status_t getKeyRequest(Vector<uint8_t> const& scope, String8 const& mimeType,
+ DrmPlugin::KeyType keyType, KeyedVector<String8, String8>& optionalParameters,
+ Vector<uint8_t>& request, String8& defaultUrl,
+ DrmPlugin::KeyRequestType& keyRequestType)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+
+ writeVector(data, scope);
+ data.writeString8(mimeType);
+ data.writeInt32((int32_t)keyType);
+
+ data.writeUint32(optionalParameters.size());
+ for (size_t i = 0; i < optionalParameters.size(); ++i) {
+ data.writeString8(optionalParameters.keyAt(i));
+ data.writeString8(optionalParameters.valueAt(i));
+ }
+
+ status_t status = remote()->transact(GET_KEY_REQUEST, data, &reply);
+ if (status != OK) {
+ ALOGE("getKeyRequest: binder call failed: %d", status);
+ return status;
+ }
+
+ readVector(reply, request);
+ defaultUrl = reply.readString8();
+ keyRequestType = (DrmPlugin::KeyRequestType)reply.readInt32();
+
+ return reply.readInt32();
+ }
+
+ status_t provideKeyResponse(Vector<uint8_t>& releaseKeySetId, Vector<uint8_t>& response,
+ Vector<uint8_t> &keySetId)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+
+ writeVector(data, releaseKeySetId);
+ writeVector(data, response);
+
+ status_t status = remote()->transact(PROVIDE_KEY_RESPONSE, data, &reply);
+ if (status != OK) {
+ ALOGE("provideKeyResponse: binder call failed: %d", status);
+ return status;
+ }
+
+ readVector(reply, keySetId);
+
+ return reply.readInt32();
+ }
+
+ status_t restoreKeys(Vector<uint8_t> const& keySetId)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+
+ writeVector(data, keySetId);
+
+ status_t status = remote()->transact(RESTORE_KEYS, data, &reply);
+ if (status != OK) {
+ ALOGE("restoreKeys: binder call failed: %d", status);
+ return status;
+ }
+
+ return reply.readInt32();
+ }
+
+ status_t getDrmPropertyString(String8 const& name, String8& value)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+
+ data.writeString8(name);
+ status_t status = remote()->transact(GET_DRM_PROPERTY_STRING, data, &reply);
+ if (status != OK) {
+ ALOGE("getDrmPropertyString: binder call failed: %d", status);
+ return status;
+ }
+
+ value = reply.readString8();
+ return reply.readInt32();
+ }
+
+ status_t setDrmPropertyString(String8 const& name, String8 const& value)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+
+ data.writeString8(name);
+ data.writeString8(value);
+ status_t status = remote()->transact(SET_DRM_PROPERTY_STRING, data, &reply);
+ if (status != OK) {
+ ALOGE("setDrmPropertyString: binder call failed: %d", status);
+ return status;
+ }
+
+ return reply.readInt32();
+ }
};
IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
@@ -741,6 +892,93 @@
return NO_ERROR;
} break;
+
+ // ModDrm
+ case PREPARE_DRM: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ uint8_t uuid[16];
+ data.read(uuid, sizeof(uuid));
+
+ int mode = data.readInt32();
+
+ uint32_t result = prepareDrm(uuid, mode);
+ reply->writeInt32(result);
+ return OK;
+ }
+ case RELEASE_DRM: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+
+ uint32_t result = releaseDrm();
+ reply->writeInt32(result);
+ return OK;
+ }
+ case GET_KEY_REQUEST: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+
+ Vector<uint8_t> scope;
+ readVector(data, scope);
+ String8 mimeType = data.readString8();
+ DrmPlugin::KeyType keyType = (DrmPlugin::KeyType)data.readInt32();
+
+ KeyedVector<String8, String8> optionalParameters;
+ uint32_t count = data.readUint32();
+ for (size_t i = 0; i < count; ++i) {
+ String8 key, value;
+ key = data.readString8();
+ value = data.readString8();
+ optionalParameters.add(key, value);
+ }
+
+ Vector<uint8_t> request;
+ String8 defaultUrl;
+ DrmPlugin::KeyRequestType keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
+
+ status_t result = getKeyRequest(scope, mimeType, keyType, optionalParameters,
+ request, defaultUrl, keyRequestType);
+
+ writeVector(*reply, request);
+ reply->writeString8(defaultUrl);
+ reply->writeInt32(keyRequestType);
+ reply->writeInt32(result);
+ return OK;
+ }
+ case PROVIDE_KEY_RESPONSE: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ Vector<uint8_t> releaseKeySetId, response, keySetId;
+ readVector(data, releaseKeySetId);
+ readVector(data, response);
+ uint32_t result = provideKeyResponse(releaseKeySetId, response, keySetId);
+ writeVector(*reply, keySetId);
+ reply->writeInt32(result);
+ return OK;
+ }
+ case RESTORE_KEYS: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+
+ Vector<uint8_t> keySetId;
+ readVector(data, keySetId);
+ uint32_t result = restoreKeys(keySetId);
+ reply->writeInt32(result);
+ return OK;
+ }
+ case GET_DRM_PROPERTY_STRING: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ String8 name, value;
+ name = data.readString8();
+ uint32_t result = getDrmPropertyString(name, value);
+ reply->writeString8(value);
+ reply->writeInt32(result);
+ return OK;
+ }
+ case SET_DRM_PROPERTY_STRING: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ String8 name, value;
+ name = data.readString8();
+ value = data.readString8();
+ uint32_t result = setDrmPropertyString(name, value);
+ reply->writeInt32(result);
+ return OK;
+ }
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 40af8de..2feb035 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -36,6 +36,7 @@
#include <media/AudioSystem.h>
#include <media/AVSyncSettings.h>
#include <media/IDataSource.h>
+#include <media/MediaAnalyticsItem.h>
#include <binder/MemoryBase.h>
@@ -810,7 +811,11 @@
ALOGV("MediaPlayer::getParameter(%d)", key);
Mutex::Autolock _l(mLock);
if (mPlayer != NULL) {
- return mPlayer->getParameter(key, reply);
+ status_t status = mPlayer->getParameter(key, reply);
+ if (status != OK) {
+ ALOGD("getParameter returns %d", status);
+ }
+ return status;
}
ALOGV("getParameter: no active player");
return INVALID_OPERATION;
@@ -874,7 +879,7 @@
case MEDIA_NOP: // interface test message
break;
case MEDIA_PREPARED:
- ALOGV("prepared");
+ ALOGV("MediaPlayer::notify() prepared");
mCurrentState = MEDIA_PLAYER_PREPARED;
if (mPrepareSync) {
ALOGV("signal application thread");
@@ -883,6 +888,9 @@
mSignal.signal();
}
break;
+ case MEDIA_DRM_INFO:
+ ALOGV("MediaPlayer::notify() MEDIA_DRM_INFO(%d, %d, %d, %p)", msg, ext1, ext2, obj);
+ break;
case MEDIA_PLAYBACK_COMPLETE:
ALOGV("playback complete");
if (mCurrentState == MEDIA_PLAYER_IDLE) {
@@ -983,4 +991,123 @@
return mPlayer->setNextPlayer(next == NULL ? NULL : next->mPlayer);
}
+// ModDrm
+status_t MediaPlayer::prepareDrm(const uint8_t uuid[16], const int mode)
+{
+ Mutex::Autolock _l(mLock);
+ if (mPlayer == NULL) {
+ return NO_INIT;
+ }
+
+ // Only allowing it in player's prepared state
+ if (!(mCurrentState & MEDIA_PLAYER_PREPARED)) {
+ ALOGE("prepareDrm must only be called in the prepared state.");
+ return INVALID_OPERATION;
+ }
+
+ status_t ret = mPlayer->prepareDrm(uuid, mode);
+ ALOGV("prepareDrm: ret=%d", ret);
+
+ return ret;
+}
+
+status_t MediaPlayer::releaseDrm()
+{
+ Mutex::Autolock _l(mLock);
+ if (mPlayer == NULL) {
+ return NO_INIT;
+ }
+
+ // Not allowing releaseDrm in an active state
+ if (mCurrentState & (MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PAUSED)) {
+ ALOGE("releaseDrm can not be called in the started/paused state.");
+ return INVALID_OPERATION;
+ }
+
+ status_t ret = mPlayer->releaseDrm();
+ ALOGV("releaseDrm: ret=%d", ret);
+
+ return ret;
+}
+
+status_t MediaPlayer::getKeyRequest(Vector<uint8_t> const& scope, String8 const& mimeType,
+ DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8>& optionalParameters,
+ Vector<uint8_t>& request, String8& defaultUrl,
+ DrmPlugin::KeyRequestType& keyRequestType)
+{
+ Mutex::Autolock _l(mLock);
+ if (mPlayer == NULL) {
+ return NO_INIT;
+ }
+
+ // Not enforcing a particular state beyond the checks enforced by the Java layer
+ // Key exchange can happen after the start.
+ status_t ret = mPlayer->getKeyRequest(scope, mimeType, keyType, optionalParameters,
+ request, defaultUrl, keyRequestType);
+ ALOGV("getKeyRequest ret=%d %d %s %d ", ret,
+ (int)request.size(), defaultUrl.string(), (int)keyRequestType);
+
+ return ret;
+}
+
+status_t MediaPlayer::provideKeyResponse(Vector<uint8_t>& releaseKeySetId,
+ Vector<uint8_t>& response, Vector<uint8_t>& keySetId)
+{
+ Mutex::Autolock _l(mLock);
+ if (mPlayer == NULL) {
+ return NO_INIT;
+ }
+
+ // Not enforcing a particular state beyond the checks enforced by the Java layer
+ // Key exchange can happen after the start.
+ status_t ret = mPlayer->provideKeyResponse(releaseKeySetId, response, keySetId);
+ ALOGV("provideKeyResponse: ret=%d", ret);
+
+ return ret;
+}
+
+status_t MediaPlayer::restoreKeys(Vector<uint8_t> const& keySetId)
+{
+ Mutex::Autolock _l(mLock);
+ if (mPlayer == NULL) {
+ return NO_INIT;
+ }
+
+ // Not enforcing a particular state beyond the checks enforced by the Java layer
+ // Key exchange can happen after the start.
+ status_t ret = mPlayer->restoreKeys(keySetId);
+ ALOGV("restoreKeys: ret=%d", ret);
+
+ return ret;
+}
+
+status_t MediaPlayer::getDrmPropertyString(String8 const& name, String8& value)
+{
+ Mutex::Autolock _l(mLock);
+ if (mPlayer == NULL) {
+ return NO_INIT;
+ }
+
+ // Not enforcing a particular state beyond the checks enforced by the Java layer
+ status_t ret = mPlayer->getDrmPropertyString(name, value);
+ ALOGV("getDrmPropertyString: ret=%d", ret);
+
+ return ret;
+}
+
+status_t MediaPlayer::setDrmPropertyString(String8 const& name, String8 const& value)
+{
+ Mutex::Autolock _l(mLock);
+ if (mPlayer == NULL) {
+ return NO_INIT;
+ }
+
+ // Not enforcing a particular state beyond the checks enforced by the Java layer
+ status_t ret = mPlayer->setDrmPropertyString(name, value);
+ ALOGV("setDrmPropertyString: ret=%d", ret);
+
+ return ret;
+}
+
} // namespace android
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index db182b2..819973e 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -347,6 +347,32 @@
virtual status_t dump(int fd, const Vector<String16>& args);
audio_session_t getAudioSessionId() { return mAudioSessionId; }
+ // ModDrm
+ virtual status_t prepareDrm(const uint8_t /*uuid*/[16], const int /*mode*/)
+ { return INVALID_OPERATION; }
+ virtual status_t releaseDrm()
+ { return INVALID_OPERATION; }
+ virtual status_t getKeyRequest(Vector<uint8_t> const& /*scope*/,
+ String8 const& /*mimeType*/,
+ DrmPlugin::KeyType /*keyType*/,
+ KeyedVector<String8, String8>& /*optionalParameters*/,
+ Vector<uint8_t>& /*request*/,
+ String8& /*defaultUrl*/,
+ DrmPlugin::KeyRequestType& /*keyRequestType*/)
+ { return INVALID_OPERATION; }
+ virtual status_t provideKeyResponse(Vector<uint8_t>& /*releaseKeySetId*/,
+ Vector<uint8_t>& /*response*/,
+ Vector<uint8_t>& /*keySetId*/)
+ { return INVALID_OPERATION; }
+ virtual status_t restoreKeys(Vector<uint8_t> const& /*keySetId*/)
+ { return INVALID_OPERATION; }
+ virtual status_t getDrmPropertyString(String8 const& /*name*/,
+ String8& /*value*/)
+ { return INVALID_OPERATION; }
+ virtual status_t setDrmPropertyString(String8 const& /*name*/,
+ String8 const& /*value*/)
+ { return INVALID_OPERATION; }
+
private:
class ServiceDeathNotifier: public IBinder::DeathRecipient
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 4c576a5..6593fcd 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -1822,7 +1822,8 @@
// Take into account sample aspect ratio if necessary:
int32_t sarWidth, sarHeight;
if (inputFormat->findInt32("sar-width", &sarWidth)
- && inputFormat->findInt32("sar-height", &sarHeight)) {
+ && inputFormat->findInt32("sar-height", &sarHeight)
+ && sarWidth > 0 && sarHeight > 0) {
ALOGV("Sample aspect ratio %d : %d", sarWidth, sarHeight);
displayWidth = (displayWidth * sarWidth) / sarHeight;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index b8bb8fe..0ddbd63 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -706,7 +706,16 @@
return INVALID_OPERATION;
}
-status_t NuPlayerDriver::getParameter(int /* key */, Parcel * /* reply */) {
+status_t NuPlayerDriver::getParameter(int key, Parcel *reply) {
+
+ if (key == FOURCC('m','t','r','X')) {
+ // mtrX -- a play on 'metrics' (not matrix)
+ // gather current info all together, parcel it, and send it back
+ finalizeMetrics("api");
+ mAnalyticsItem->writeToParcel(reply);
+ return OK;
+ }
+
return INVALID_OPERATION;
}
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 192eccd..d46ef3c 100755
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -79,6 +79,8 @@
static const char kMetaKey_CaptureFps[] = "com.android.capture.fps";
static const char kMetaKey_TemporalLayerCount[] = "com.android.video.temporal_layers_count";
+static const int kTimestampDebugCount = 10;
+
static const uint8_t kMandatoryHevcNalUnitTypes[3] = {
kHevcNalUnitTypeVps,
kHevcNalUnitTypeSps,
@@ -305,6 +307,9 @@
int64_t mMinCttsOffsetTimeUs;
int64_t mMaxCttsOffsetTimeUs;
+ // Save the last 10 frames' timestamp for debug.
+ std::list<std::pair<int64_t, int64_t>> mTimestampDebugHelper;
+
// Sequence parameter set or picture parameter set
struct AVCParamSet {
AVCParamSet(uint16_t length, const uint8_t *data)
@@ -334,6 +339,8 @@
// Update the audio track's drift information.
void updateDriftTime(const sp<MetaData>& meta);
+ void dumpTimeStamps();
+
int32_t getStartTimeOffsetScaledTime() const;
static void *ThreadWrapper(void *me);
@@ -2501,6 +2508,17 @@
}
}
+void MPEG4Writer::Track::dumpTimeStamps() {
+ ALOGE("Dumping %s track's last 10 frames timestamp ", getTrackType());
+ std::string timeStampString;
+ for (std::list<std::pair<int64_t, int64_t>>::iterator num = mTimestampDebugHelper.begin();
+ num != mTimestampDebugHelper.end(); ++num) {
+ timeStampString += "(" + std::to_string(num->first)+
+ "us, " + std::to_string(num->second) + "us) ";
+ }
+ ALOGE("%s", timeStampString.c_str());
+}
+
status_t MPEG4Writer::Track::threadEntry() {
int32_t count = 0;
const int64_t interleaveDurationUs = mOwner->interleaveDuration();
@@ -2706,8 +2724,9 @@
previousPausedDurationUs += pausedDurationUs - lastDurationUs;
mResumed = false;
}
-
+ std::pair<int64_t, int64_t> timestampPair;
timestampUs -= previousPausedDurationUs;
+ timestampPair.first = timestampUs;
if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
copy->release();
mSource->stop();
@@ -2729,9 +2748,11 @@
if (mLastDecodingTimeUs < 0) {
decodingTimeUs = std::max((int64_t)0, decodingTimeUs);
} else {
- // increase decoding time by at least 1 tick
- decodingTimeUs = std::max(
- mLastDecodingTimeUs + divUp(1000000, mTimeScale), decodingTimeUs);
+ // increase decoding time by at least the larger vaule of 1 tick and
+ // 0.1 milliseconds. This needs to take into account the possible
+ // delta adjustment in DurationTicks in below.
+ decodingTimeUs = std::max(mLastDecodingTimeUs +
+ std::max(100, divUp(1000000, mTimeScale)), decodingTimeUs);
}
mLastDecodingTimeUs = decodingTimeUs;
@@ -2864,6 +2885,12 @@
lastDurationUs = timestampUs - lastTimestampUs;
lastDurationTicks = currDurationTicks;
lastTimestampUs = timestampUs;
+ timestampPair.second = timestampUs;
+ // Insert the timestamp into the mTimestampDebugHelper
+ if (mTimestampDebugHelper.size() >= kTimestampDebugCount) {
+ mTimestampDebugHelper.pop_front();
+ }
+ mTimestampDebugHelper.push_back(timestampPair);
if (isSync != 0) {
addOneStssTableEntry(mStszTableEntries->count());
@@ -2919,6 +2946,7 @@
}
if (isTrackMalFormed()) {
+ dumpTimeStamps();
err = ERROR_MALFORMED;
}
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 9eca982..5dc9ffa 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -33,6 +33,7 @@
#include <media/IOMX.h>
#include <media/IResourceManagerService.h>
#include <media/MediaCodecBuffer.h>
+#include <media/MediaAnalyticsItem.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -57,6 +58,13 @@
namespace android {
+// key for media statistics
+static const char *CodecKeyName = "codec";
+// attrs for media statistics
+static const char *CodecMime = "mime";
+static const char *CodecCodec = "codec";
+
+
static int64_t getId(const sp<IResourceManagerClient> &client) {
return (int64_t) client.get();
}
@@ -476,11 +484,27 @@
} else {
mUid = uid;
}
+ // set up our new record, get a sessionID, put it into the in-progress list
+ mAnalyticsItem = new MediaAnalyticsItem(CodecKeyName);
+ if (mAnalyticsItem != NULL) {
+ (void) mAnalyticsItem->generateSessionID();
+ // don't record it yet; only at the end, when we have decided that we have
+ // data worth writing (e.g. .count() > 0)
+ }
}
MediaCodec::~MediaCodec() {
CHECK_EQ(mState, UNINITIALIZED);
mResourceManagerService->removeResource(getId(mResourceManagerClient));
+
+ if (mAnalyticsItem != NULL ) {
+ if (mAnalyticsItem->count() > 0) {
+ mAnalyticsItem->setFinalized(true);
+ mAnalyticsItem->selfrecord();
+ }
+ delete mAnalyticsItem;
+ mAnalyticsItem = NULL;
+ }
}
// static
@@ -600,6 +624,19 @@
msg->setInt32("encoder", encoder);
}
+ if (mAnalyticsItem != NULL) {
+ if (nameIsType) {
+ // name is the mime type
+ mAnalyticsItem->setCString(CodecMime, name.c_str());
+ } else {
+ mAnalyticsItem->setCString(CodecCodec, name.c_str());
+ }
+ mAnalyticsItem->setCString("mode", mIsVideo ? "video" : "audio");
+ //mAnalyticsItem->setInt32("type", nameIsType);
+ if (nameIsType)
+ mAnalyticsItem->setInt32("encoder", encoder);
+ }
+
status_t err;
Vector<MediaResource> resources;
MediaResource::Type type =
@@ -652,6 +689,12 @@
mRotationDegrees = 0;
}
+ if (mAnalyticsItem != NULL) {
+ mAnalyticsItem->setInt32("width", mVideoWidth);
+ mAnalyticsItem->setInt32("height", mVideoHeight);
+ mAnalyticsItem->setInt32("rotation", mRotationDegrees);
+ }
+
// Prevent possible integer overflow in downstream code.
if (mInitIsEncoder
&& (uint64_t)mVideoWidth * mVideoHeight > (uint64_t)INT32_MAX / 4) {
@@ -666,6 +709,10 @@
if (crypto != NULL) {
msg->setPointer("crypto", crypto.get());
+ if (mAnalyticsItem != NULL) {
+ // XXX: save indication that it's crypto in some way...
+ mAnalyticsItem->setInt32("crypto", 1);
+ }
}
// save msg for reset
@@ -1058,6 +1105,21 @@
return OK;
}
+status_t MediaCodec::getMetrics(Parcel *reply) {
+
+ // shouldn't happen, but be safe
+ if (mAnalyticsItem == NULL) {
+ return UNKNOWN_ERROR;
+ }
+
+ // XXX: go get current values for whatever in-flight data we want
+
+ // send it back to the caller.
+ mAnalyticsItem->writeToParcel(reply);
+
+ return OK;
+}
+
status_t MediaCodec::getInputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
msg->setInt32("portIndex", kPortIndexInput);
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index df4d9bf..677d43e 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -36,6 +36,7 @@
#include <binder/IServiceManager.h>
#include <binder/MemoryDealer.h>
+#include <media/MediaAnalyticsItem.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/DataSource.h>
@@ -47,9 +48,16 @@
#include <utils/String8.h>
#include <private/android_filesystem_config.h>
+// still doing some on/off toggling here.
+#define MEDIA_LOG 1
+
namespace android {
+// key for media statistics
+static const char *KeyName_Extractor = "extractor";
+// attrs for media statistics
+
MediaExtractor::MediaExtractor() {
if (!LOG_NDEBUG) {
uid_t uid = getuid();
@@ -57,8 +65,29 @@
ALOGI("extractor created in uid: %d (%s)", getuid(), pw->pw_name);
}
+ mAnalyticsItem = NULL;
+ if (MEDIA_LOG) {
+ mAnalyticsItem = new MediaAnalyticsItem(KeyName_Extractor);
+ (void) mAnalyticsItem->generateSessionID();
+ }
}
+MediaExtractor::~MediaExtractor() {
+
+ // log the current record, provided it has some information worth recording
+ if (MEDIA_LOG) {
+ if (mAnalyticsItem != NULL) {
+ if (mAnalyticsItem->count() > 0) {
+ mAnalyticsItem->setFinalized(true);
+ mAnalyticsItem->selfrecord();
+ }
+ }
+ }
+ if (mAnalyticsItem != NULL) {
+ delete mAnalyticsItem;
+ mAnalyticsItem = NULL;
+ }
+}
sp<MetaData> MediaExtractor::getMetaData() {
return new MetaData;
@@ -214,6 +243,31 @@
ret = new MidiExtractor(source);
}
+ if (ret != NULL) {
+ // track the container format (mpeg, aac, wvm, etc)
+ if (MEDIA_LOG) {
+ if (ret->mAnalyticsItem != NULL) {
+ ret->mAnalyticsItem->setCString("fmt", ret->name());
+ // tracks (size_t)
+ ret->mAnalyticsItem->setInt32("ntrk", ret->countTracks());
+ // metadata
+ sp<MetaData> pMetaData = ret->getMetaData();
+ if (pMetaData != NULL) {
+ String8 xx = pMetaData->toString();
+ ALOGD("metadata says: %s", xx.string());
+ // can grab various fields like:
+ // 'titl' -- but this verges into PII
+ // 'mime'
+ const char *mime = NULL;
+ if (pMetaData->findCString(kKeyMIMEType, &mime)) {
+ ret->mAnalyticsItem->setCString("mime", mime);
+ }
+ // what else is interesting here?
+ }
+ }
+ }
+ }
+
return ret;
}
diff --git a/media/libstagefright/avc_utils.cpp b/media/libstagefright/avc_utils.cpp
index 9f15cf7..a1c4979 100644
--- a/media/libstagefright/avc_utils.cpp
+++ b/media/libstagefright/avc_utils.cpp
@@ -420,8 +420,8 @@
meta->setInt32(kKeyWidth, width);
meta->setInt32(kKeyHeight, height);
- if (sarWidth > 1 || sarHeight > 1) {
- // We treat 0:0 (unspecified) as 1:1.
+ if ((sarWidth > 0 && sarHeight > 0) && (sarWidth != 1 || sarHeight != 1)) {
+ // We treat *:0 and 0:* (unspecified) as 1:1.
meta->setInt32(kKeySARWidth, sarWidth);
meta->setInt32(kKeySARHeight, sarHeight);
diff --git a/radio/IRadio.cpp b/radio/IRadio.cpp
index d475805..72f3b68 100644
--- a/radio/IRadio.cpp
+++ b/radio/IRadio.cpp
@@ -16,6 +16,7 @@
*/
#define LOG_TAG "IRadio"
+//#define LOG_NDEBUG 0
#include <utils/Log.h>
#include <utils/Errors.h>
#include <binder/IMemory.h>
@@ -23,7 +24,7 @@
#include <radio/IRadioService.h>
#include <radio/IRadioClient.h>
#include <system/radio.h>
-#include <system/radio_metadata.h>
+#include <system/RadioMetadataWrapper.h>
namespace android {
@@ -300,12 +301,9 @@
case GET_PROGRAM_INFORMATION: {
CHECK_INTERFACE(IRadio, data, reply);
struct radio_program_info info;
+ RadioMetadataWrapper metadataWrapper(&info.metadata);
- status_t status = radio_metadata_allocate(&info.metadata, 0, 0);
- if (status != NO_ERROR) {
- return status;
- }
- status = getProgramInformation(&info);
+ status_t status = getProgramInformation(&info);
reply->writeInt32(status);
if (status == NO_ERROR) {
reply->write(&info, sizeof(struct radio_program_info));
@@ -317,7 +315,6 @@
reply->writeUint32(0);
}
}
- radio_metadata_deallocate(info.metadata);
return NO_ERROR;
}
case HAS_CONTROL: {
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index 5b4d10d..9328d65 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -90,12 +90,6 @@
LOCAL_CFLAGS += -Wall -Wextra -Werror
-ifeq ($(ENABLE_TREBLE), true)
-
- LOCAL_CFLAGS += -DENABLE_TREBLE
-
-endif # ENABLE_TREBLE
-
LOCAL_MODULE:= libcameraservice
include $(BUILD_SHARED_LIBRARY)
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index f439590..f708654 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -18,12 +18,6 @@
#define ATRACE_TAG ATRACE_TAG_CAMERA
//#define LOG_NDEBUG 0
-#ifdef ENABLE_TREBLE
- #define USE_HIDL true
-#else
- #define USE_HIDL false
-#endif
-
#include <algorithm>
#include <climits>
#include <stdio.h>
@@ -197,10 +191,13 @@
notifier.noteResetFlashlight();
status_t res = INVALID_OPERATION;
- if (USE_HIDL) {
- res = enumerateProviders();
- } else {
+
+ bool disableTreble = property_get_bool("camera.disable_treble", false);
+ if (disableTreble) {
+ ALOGI("Treble disabled - using legacy path");
res = loadLegacyHalModule();
+ } else {
+ res = enumerateProviders();
}
if (res == OK) {
mInitialized = true;