summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorniko <niko@google.com>2009-07-20 15:07:26 -0700
committerniko <niko@google.com>2009-07-22 15:03:22 -0700
commita64c8c79af1a15911c55306d83a797fa50969f77 (patch)
tree09edd1daa9b6d41bc6eeafb3207067f288b30ef7 /media
parent8445fd927053268929125a6a9406ec3b622e2920 (diff)
downloadframeworks_av-a64c8c79af1a15911c55306d83a797fa50969f77.zip
frameworks_av-a64c8c79af1a15911c55306d83a797fa50969f77.tar.gz
frameworks_av-a64c8c79af1a15911c55306d83a797fa50969f77.tar.bz2
Added native metadata support.
Metadata.java: Fixed typo 8k != 8092. The comment was correct though. In Metadata.h, the new Metadata class is declared in the ns android::media to limit the chances of conflict with other packages. The MetadataType in MediaPlayerInterface is gone and moved to Metadata as an inner typedef. Similarly the SortedVector<MetadataType> instance have been replace by a new type Metadata::Filter. All the keys declared in the java counterpart are also in Metadata.h. Metadata.cpp: Contains the implementation of the native metadata packing. There an associated change in the opencore package that should go in at the same time as this one.
Diffstat (limited to 'media')
-rw-r--r--media/libmedia/Android.mk37
-rw-r--r--media/libmedia/Metadata.cpp168
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp53
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.h13
-rw-r--r--media/libmediaplayerservice/MidiFile.h4
-rw-r--r--media/libmediaplayerservice/StagefrightPlayer.cpp7
-rw-r--r--media/libmediaplayerservice/StagefrightPlayer.h3
-rw-r--r--media/libmediaplayerservice/TestPlayerStub.h4
-rw-r--r--media/libmediaplayerservice/VorbisPlayer.h4
9 files changed, 216 insertions, 77 deletions
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index cdaab04..07c81f7 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -2,24 +2,25 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- AudioTrack.cpp \
- IAudioFlinger.cpp \
- IAudioFlingerClient.cpp \
- IAudioTrack.cpp \
- IAudioRecord.cpp \
- AudioRecord.cpp \
- AudioSystem.cpp \
- mediaplayer.cpp \
- IMediaPlayerService.cpp \
- IMediaPlayerClient.cpp \
- IMediaPlayer.cpp \
- IMediaRecorder.cpp \
- mediarecorder.cpp \
- IMediaMetadataRetriever.cpp \
- mediametadataretriever.cpp \
- ToneGenerator.cpp \
- JetPlayer.cpp \
- IOMX.cpp
+ AudioTrack.cpp \
+ IAudioFlinger.cpp \
+ IAudioFlingerClient.cpp \
+ IAudioTrack.cpp \
+ IAudioRecord.cpp \
+ AudioRecord.cpp \
+ AudioSystem.cpp \
+ mediaplayer.cpp \
+ IMediaPlayerService.cpp \
+ IMediaPlayerClient.cpp \
+ IMediaPlayer.cpp \
+ IMediaRecorder.cpp \
+ Metadata.cpp \
+ mediarecorder.cpp \
+ IMediaMetadataRetriever.cpp \
+ mediametadataretriever.cpp \
+ ToneGenerator.cpp \
+ JetPlayer.cpp \
+ IOMX.cpp
LOCAL_SHARED_LIBRARIES := \
libui libcutils libutils libbinder libsonivox
diff --git a/media/libmedia/Metadata.cpp b/media/libmedia/Metadata.cpp
new file mode 100644
index 0000000..35ec6b3
--- /dev/null
+++ b/media/libmedia/Metadata.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Metadata"
+#include <utils/Log.h>
+
+#include <sys/types.h>
+#include <media/Metadata.h>
+#include <binder/Parcel.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+// This file contains code to serialize Metadata triples (key, type,
+// value) into a parcel. The Parcel is destinated to be decoded by the
+// Metadata.java class.
+
+namespace {
+// All these constants below must be kept in sync with Metadata.java.
+enum MetadataId {
+ FIRST_SYSTEM_ID = 1,
+ LAST_SYSTEM_ID = 31,
+ FIRST_CUSTOM_ID = 8192
+};
+
+// Types
+enum Types {
+ STRING_VAL = 1,
+ INTEGER_VAL,
+ BOOLEAN_VAL,
+ LONG_VAL,
+ DOUBLE_VAL,
+ TIMED_TEXT_VAL,
+ DATE_VAL,
+ BYTE_ARRAY_VAL,
+};
+
+const size_t kRecordHeaderSize = 3 * sizeof(int32_t);
+const int32_t kMetaMarker = 0x4d455441; // 'M' 'E' 'T' 'A'
+
+} // anonymous namespace
+
+namespace android {
+namespace media {
+
+Metadata::Metadata(Parcel *p)
+ :mData(p),
+ mBegin(p->dataPosition()) { }
+
+Metadata::~Metadata() { }
+
+void Metadata::resetParcel()
+{
+ mData->setDataPosition(mBegin);
+}
+
+// Update the 4 bytes int at the beginning of the parcel which holds
+// the number of bytes written so far.
+void Metadata::updateLength()
+{
+ const size_t end = mData->dataPosition();
+
+ mData->setDataPosition(mBegin);
+ mData->writeInt32(end - mBegin);
+ mData->setDataPosition(end);
+}
+
+// Write the header. The java layer will look for the marker.
+bool Metadata::appendHeader()
+{
+ bool ok = true;
+
+ // Placeholder for the length of the metadata
+ ok = ok && mData->writeInt32(-1) == OK;
+ ok = ok && mData->writeInt32(kMetaMarker) == OK;
+ return ok;
+}
+
+bool Metadata::appendBool(int key, bool val)
+{
+ if (!checkKey(key)) {
+ return false;
+ }
+
+ const size_t begin = mData->dataPosition();
+ bool ok = true;
+
+ // 4 int32s: size, key, type, value.
+ ok = ok && mData->writeInt32(4 * sizeof(int32_t)) == OK;
+ ok = ok && mData->writeInt32(key) == OK;
+ ok = ok && mData->writeInt32(BOOLEAN_VAL) == OK;
+ ok = ok && mData->writeInt32(val ? 1 : 0) == OK;
+ if (!ok) {
+ mData->setDataPosition(begin);
+ }
+ return ok;
+}
+
+bool Metadata::appendInt32(int key, int32_t val)
+{
+ if (!checkKey(key)) {
+ return false;
+ }
+
+ const size_t begin = mData->dataPosition();
+ bool ok = true;
+
+ // 4 int32s: size, key, type, value.
+ ok = ok && mData->writeInt32(4 * sizeof(int32_t)) == OK;
+ ok = ok && mData->writeInt32(key) == OK;
+ ok = ok && mData->writeInt32(INTEGER_VAL) == OK;
+ ok = ok && mData->writeInt32(val) == OK;
+ if (!ok) {
+ mData->setDataPosition(begin);
+ }
+ return ok;
+}
+
+// Check the key (i.e metadata id) is valid if it is a system one.
+// Loop over all the exiting ones in the Parcel to check for duplicate
+// (not allowed).
+bool Metadata::checkKey(int key)
+{
+ if (key < FIRST_SYSTEM_ID ||
+ (LAST_SYSTEM_ID < key && key < FIRST_CUSTOM_ID)) {
+ LOGE("Bad key %d", key);
+ return false;
+ }
+ size_t curr = mData->dataPosition();
+ // Loop over the keys to check if it has been used already.
+ mData->setDataPosition(mBegin);
+
+ bool error = false;
+ size_t left = curr - mBegin;
+ while (left > 0) {
+ size_t pos = mData->dataPosition();
+ size_t size = mData->readInt32();
+ if (size < kRecordHeaderSize || size > left) {
+ error = true;
+ break;
+ }
+ if (mData->readInt32() == key) {
+ LOGE("Key exists already %d", key);
+ error = true;
+ break;
+ }
+ mData->setDataPosition(pos + size);
+ left -= size;
+ }
+ mData->setDataPosition(curr);
+ return !error;
+}
+
+} // namespace android::media
+} // namespace android
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 5e62f9d..77f7434 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -47,10 +47,9 @@
#include <media/MediaPlayerInterface.h>
#include <media/mediarecorder.h>
#include <media/MediaMetadataRetrieverInterface.h>
+#include <media/Metadata.h>
#include <media/AudioTrack.h>
-#include <utils/SortedVector.h>
-
#include "MediaRecorderClient.h"
#include "MediaPlayerService.h"
#include "MetadataRetrieverClient.h"
@@ -85,21 +84,17 @@ pid_t gettid() { return syscall(__NR_gettid);}
#endif
namespace {
+using android::media::Metadata;
using android::status_t;
using android::OK;
using android::BAD_VALUE;
using android::NOT_ENOUGH_DATA;
-using android::MetadataType;
using android::Parcel;
-using android::SortedVector;
// Max number of entries in the filter.
const int kMaxFilterSize = 64; // I pulled that out of thin air.
-// Keep in sync with ANY in Metadata.java
-const int32_t kAny = 0;
-
-const int32_t kMetaMarker = 0x4d455441; // 'M' 'E' 'T' 'A'
+// FIXME: Move all the metadata related function in the Metadata.cpp
// Unmarshall a filter from a Parcel.
@@ -124,7 +119,7 @@ const int32_t kMetaMarker = 0x4d455441; // 'M' 'E' 'T' 'A'
// @param[out] status On exit contains the status code to be returned.
// @return true if the parcel starts with a valid filter.
bool unmarshallFilter(const Parcel& p,
- SortedVector<MetadataType> *filter,
+ Metadata::Filter *filter,
status_t *status)
{
int32_t val;
@@ -147,7 +142,7 @@ bool unmarshallFilter(const Parcel& p,
filter->clear();
filter->setCapacity(num);
- size_t size = num * sizeof(MetadataType);
+ size_t size = num * sizeof(Metadata::Type);
if (p.dataAvail() < size)
@@ -157,7 +152,8 @@ bool unmarshallFilter(const Parcel& p,
return false;
}
- const MetadataType *data = static_cast<const MetadataType*>(p.readInplace(size));
+ const Metadata::Type *data =
+ static_cast<const Metadata::Type*>(p.readInplace(size));
if (NULL == data)
{
@@ -181,11 +177,11 @@ bool unmarshallFilter(const Parcel& p,
// @param filter Of metadata type.
// @param val To be searched.
// @return true if a match was found.
-bool findMetadata(const SortedVector<MetadataType>& filter, const int32_t val)
+bool findMetadata(const Metadata::Filter& filter, const int32_t val)
{
// Deal with empty and ANY right away
if (filter.isEmpty()) return false;
- if (filter[0] == kAny) return true;
+ if (filter[0] == Metadata::kAny) return true;
return filter.indexOf(val) >= 0;
}
@@ -857,7 +853,7 @@ status_t MediaPlayerService::Client::invoke(const Parcel& request,
status_t MediaPlayerService::Client::setMetadataFilter(const Parcel& filter)
{
status_t status;
- SortedVector<MetadataType> allow, drop;
+ media::Metadata::Filter allow, drop;
if (unmarshallFilter(filter, &allow, &status) &&
unmarshallFilter(filter, &drop, &status)) {
@@ -872,14 +868,14 @@ status_t MediaPlayerService::Client::setMetadataFilter(const Parcel& filter)
status_t MediaPlayerService::Client::getMetadata(
bool update_only, bool apply_filter, Parcel *reply)
{
- sp<MediaPlayerBase> p = getPlayer();
- if (p == 0) return UNKNOWN_ERROR;
+ sp<MediaPlayerBase> player = getPlayer();
+ if (player == 0) return UNKNOWN_ERROR;
status_t status;
// Placeholder for the return code, updated by the caller.
reply->writeInt32(-1);
- SortedVector<MetadataType> ids;
+ media::Metadata::Filter ids;
// We don't block notifications while we fetch the data. We clear
// mMetadataUpdated first so we don't lose notifications happening
@@ -892,14 +888,13 @@ status_t MediaPlayerService::Client::getMetadata(
mMetadataUpdated.clear();
}
- const size_t begin = reply->dataPosition();
- reply->writeInt32(-1); // Placeholder for the length of the metadata
- reply->writeInt32(kMetaMarker);
+ media::Metadata metadata(reply);
- status = p->getMetadata(ids, reply);
+ metadata.appendHeader();
+ status = player->getMetadata(ids, reply);
if (status != OK) {
- reply->setDataPosition(begin);
+ metadata.resetParcel();
LOGE("getMetadata failed %d", status);
return status;
}
@@ -908,12 +903,8 @@ status_t MediaPlayerService::Client::getMetadata(
// filtering takes place on the update notifications already. This
// would be when all the metadata are fetch and a filter is set.
- const size_t end = reply->dataPosition();
-
// Everything is fine, update the metadata length.
- reply->setDataPosition(begin);
- reply->writeInt32(end - begin);
- reply->setDataPosition(end);
+ metadata.updateLength();
return OK;
}
@@ -1043,7 +1034,7 @@ void MediaPlayerService::Client::notify(void* cookie, int msg, int ext1, int ext
if (MEDIA_INFO == msg &&
MEDIA_INFO_METADATA_UPDATE == ext1) {
- const MetadataType metadata_type = ext2;
+ const media::Metadata::Type metadata_type = ext2;
if(client->shouldDropMetadata(metadata_type)) {
return;
@@ -1058,7 +1049,7 @@ void MediaPlayerService::Client::notify(void* cookie, int msg, int ext1, int ext
}
-bool MediaPlayerService::Client::shouldDropMetadata(MetadataType code) const
+bool MediaPlayerService::Client::shouldDropMetadata(media::Metadata::Type code) const
{
Mutex::Autolock lock(mLock);
@@ -1074,7 +1065,7 @@ bool MediaPlayerService::Client::shouldDropMetadata(MetadataType code) const
}
-void MediaPlayerService::Client::addNewMetadataUpdate(MetadataType metadata_type) {
+void MediaPlayerService::Client::addNewMetadataUpdate(media::Metadata::Type metadata_type) {
Mutex::Autolock lock(mLock);
if (mMetadataUpdated.indexOf(metadata_type) < 0) {
mMetadataUpdated.add(metadata_type);
@@ -1499,4 +1490,4 @@ void MediaPlayerService::AudioCache::notify(void* cookie, int msg, int ext1, int
p->mSignal.signal();
}
-}; // namespace android
+} // namespace android
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 94cb917..a4be414 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -23,15 +23,14 @@
#include <utils/List.h>
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
-#include <utils/SortedVector.h>
#include <utils/Vector.h>
#include <ui/SurfaceComposerClient.h>
#include <media/IMediaPlayerService.h>
#include <media/MediaPlayerInterface.h>
+#include <media/Metadata.h>
namespace android {
-typedef int32_t MetadataType;
class IMediaRecorder;
class IMediaMetadataRetriever;
@@ -239,12 +238,12 @@ private:
// @param type Of the metadata to be tested.
// @return true if the metadata should be dropped according to
// the filters.
- bool shouldDropMetadata(MetadataType type) const;
+ bool shouldDropMetadata(media::Metadata::Type type) const;
// Add a new element to the set of metadata updated. Noop if
// the element exists already.
// @param type Of the metadata to be recorded.
- void addNewMetadataUpdate(MetadataType type);
+ void addNewMetadataUpdate(media::Metadata::Type type);
mutable Mutex mLock;
sp<MediaPlayerBase> mPlayer;
@@ -257,14 +256,14 @@ private:
int32_t mConnId;
// Metadata filters.
- SortedVector<int32_t> mMetadataAllow; // protected by mLock
- SortedVector<int32_t> mMetadataDrop; // protected by mLock
+ media::Metadata::Filter mMetadataAllow; // protected by mLock
+ media::Metadata::Filter mMetadataDrop; // protected by mLock
// Metadata updated. For each MEDIA_INFO_METADATA_UPDATE
// notification we try to update mMetadataUpdated which is a
// set: no duplicate.
// getMetadata clears this set.
- SortedVector<int32_t> mMetadataUpdated; // protected by mLock
+ media::Metadata::Filter mMetadataUpdated; // protected by mLock
#if CALLBACK_ANTAGONIZER
Antagonizer* mAntagonizer;
diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h
index 30b6a2e..25d4a1b 100644
--- a/media/libmediaplayerservice/MidiFile.h
+++ b/media/libmediaplayerservice/MidiFile.h
@@ -49,10 +49,6 @@ public:
virtual status_t invoke(const Parcel& request, Parcel *reply) {
return INVALID_OPERATION;
}
- virtual status_t getMetadata(const SortedVector<MetadataType>& ids,
- Parcel *records) {
- return INVALID_OPERATION;
- }
private:
status_t createOutputTrack();
diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp
index 8597275..9a06d13 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.cpp
+++ b/media/libmediaplayerservice/StagefrightPlayer.cpp
@@ -144,7 +144,7 @@ status_t StagefrightPlayer::seekTo(int msec) {
if (mPlayer == NULL) {
return NO_INIT;
}
-
+
status_t err = mPlayer->seekTo((int64_t)msec * 1000);
sendEvent(MEDIA_SEEK_COMPLETE);
@@ -205,9 +205,4 @@ void StagefrightPlayer::setAudioSink(const sp<AudioSink> &audioSink) {
}
}
-status_t StagefrightPlayer::getMetadata(
- const SortedVector<MetadataType> &ids, Parcel *records) {
- return INVALID_OPERATION;
-}
-
} // namespace android
diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h
index f93c1f8..f214872 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.h
+++ b/media/libmediaplayerservice/StagefrightPlayer.h
@@ -48,9 +48,6 @@ public:
virtual status_t invoke(const Parcel &request, Parcel *reply);
virtual void setAudioSink(const sp<AudioSink> &audioSink);
- virtual status_t getMetadata(
- const SortedVector<MetadataType> &ids, Parcel *records);
-
private:
MediaPlayerImpl *mPlayer;
diff --git a/media/libmediaplayerservice/TestPlayerStub.h b/media/libmediaplayerservice/TestPlayerStub.h
index 339b108..80d53a8 100644
--- a/media/libmediaplayerservice/TestPlayerStub.h
+++ b/media/libmediaplayerservice/TestPlayerStub.h
@@ -94,10 +94,6 @@ class TestPlayerStub : public MediaPlayerInterface {
virtual status_t invoke(const android::Parcel& in, android::Parcel *out) {
return mPlayer->invoke(in, out);
}
- virtual status_t getMetadata(const SortedVector<MetadataType>& ids,
- Parcel *records) {
- return INVALID_OPERATION;
- }
// @return true if the current build is 'eng' or 'test' and the
diff --git a/media/libmediaplayerservice/VorbisPlayer.h b/media/libmediaplayerservice/VorbisPlayer.h
index 040eb36..4024654 100644
--- a/media/libmediaplayerservice/VorbisPlayer.h
+++ b/media/libmediaplayerservice/VorbisPlayer.h
@@ -54,10 +54,6 @@ public:
virtual status_t setLooping(int loop);
virtual player_type playerType() { return VORBIS_PLAYER; }
virtual status_t invoke(const Parcel& request, Parcel *reply) {return INVALID_OPERATION;}
- virtual status_t getMetadata(const SortedVector<MetadataType>& ids,
- Parcel *records) {
- return INVALID_OPERATION;
- }
private:
status_t setdatasource(const char *path, int fd, int64_t offset, int64_t length);