Merge "set software codec prioirty to match MediaCodec looper"
diff --git a/camera/aidl/android/hardware/ICameraServiceProxy.aidl b/camera/aidl/android/hardware/ICameraServiceProxy.aidl
index 5dc23eb..7575948 100644
--- a/camera/aidl/android/hardware/ICameraServiceProxy.aidl
+++ b/camera/aidl/android/hardware/ICameraServiceProxy.aidl
@@ -46,8 +46,14 @@
const int CAMERA_FACING_EXTERNAL = 2;
/**
+ * Values for notifyCameraState api level
+ */
+ const int CAMERA_API_LEVEL_1 = 1;
+ const int CAMERA_API_LEVEL_2 = 2;
+
+ /**
* Update the status of a camera device.
*/
oneway void notifyCameraState(String cameraId, int facing, int newCameraState,
- String clientName);
+ String clientName, int apiLevel);
}
diff --git a/cmds/stagefright/SineSource.cpp b/cmds/stagefright/SineSource.cpp
index 9e40a0f..0ecc16c 100644
--- a/cmds/stagefright/SineSource.cpp
+++ b/cmds/stagefright/SineSource.cpp
@@ -89,7 +89,7 @@
x += k;
}
- buffer->meta_data()->setInt64(
+ buffer->meta_data().setInt64(
kKeyTime, ((int64_t)mPhase * 1000000) / mSampleRate);
mPhase += numFramesPerBuffer;
diff --git a/cmds/stagefright/recordvideo.cpp b/cmds/stagefright/recordvideo.cpp
index b7a5066..a63b9b9 100644
--- a/cmds/stagefright/recordvideo.cpp
+++ b/cmds/stagefright/recordvideo.cpp
@@ -114,8 +114,8 @@
x = x >= 0xa0 ? 0x60 : x + 1;
#endif
(*buffer)->set_range(0, mSize);
- (*buffer)->meta_data()->clear();
- (*buffer)->meta_data()->setInt64(
+ (*buffer)->meta_data().clear();
+ (*buffer)->meta_data().setInt64(
kKeyTime, (mNumFramesOutput * 1000000) / mFrameRate);
++mNumFramesOutput;
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 5fa8304..936733d 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -253,7 +253,7 @@
shouldSeek = true;
} else {
int64_t timestampUs;
- CHECK(buffer->meta_data()->findInt64(kKeyTime, ×tampUs));
+ CHECK(buffer->meta_data().findInt64(kKeyTime, ×tampUs));
bool failed = false;
@@ -492,12 +492,12 @@
if (mStreamType == AVC) {
bool isIDR = isIDRFrame(*buffer);
- (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, isIDR);
+ (*buffer)->meta_data().setInt32(kKeyIsSyncFrame, isIDR);
if (isIDR) {
mSawFirstIDRFrame = true;
}
} else {
- (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, true);
+ (*buffer)->meta_data().setInt32(kKeyIsSyncFrame, true);
}
if (mStreamType != AVC || mSawFirstIDRFrame) {
@@ -591,7 +591,7 @@
if (err == OK) {
int64_t timeUs;
- CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
+ CHECK(buffer->meta_data().findInt64(kKeyTime, &timeUs));
printf("%" PRId64 "\t%" PRId64 "\t%" PRId64 "\n",
seekTimeUs, timeUs, seekTimeUs - timeUs);
diff --git a/include/media/MediaSourceBase.h b/include/media/MediaSourceBase.h
deleted file mode 120000
index fe227b1..0000000
--- a/include/media/MediaSourceBase.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmediaextractor/include/media/MediaSourceBase.h
\ No newline at end of file
diff --git a/include/media/MediaTrack.h b/include/media/MediaTrack.h
new file mode 120000
index 0000000..5a63287a
--- /dev/null
+++ b/include/media/MediaTrack.h
@@ -0,0 +1 @@
+../../media/libmediaextractor/include/media/MediaTrack.h
\ No newline at end of file
diff --git a/include/media/VorbisComment.h b/include/media/VorbisComment.h
new file mode 120000
index 0000000..adaa489
--- /dev/null
+++ b/include/media/VorbisComment.h
@@ -0,0 +1 @@
+../../media/libmediaextractor/include/media/VorbisComment.h
\ No newline at end of file
diff --git a/media/extractors/aac/AACExtractor.cpp b/media/extractors/aac/AACExtractor.cpp
index f6c8664..bbc1ff8 100644
--- a/media/extractors/aac/AACExtractor.cpp
+++ b/media/extractors/aac/AACExtractor.cpp
@@ -20,7 +20,7 @@
#include "AACExtractor.h"
#include <media/DataSourceBase.h>
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -33,17 +33,18 @@
namespace android {
-class AACSource : public MediaSourceBase {
+class AACSource : public MediaTrack {
public:
- AACSource(DataSourceBase *source,
- const sp<MetaData> &meta,
- const Vector<uint64_t> &offset_vector,
- int64_t frame_duration_us);
+ AACSource(
+ DataSourceBase *source,
+ MetaDataBase &meta,
+ const Vector<uint64_t> &offset_vector,
+ int64_t frame_duration_us);
- virtual status_t start(MetaData *params = NULL);
+ virtual status_t start(MetaDataBase *params = NULL);
virtual status_t stop();
- virtual sp<MetaData> getFormat();
+ virtual status_t getFormat(MetaDataBase&);
virtual status_t read(
MediaBufferBase **buffer, const ReadOptions *options = NULL);
@@ -54,7 +55,7 @@
private:
static const size_t kMaxFrameSize;
DataSourceBase *mDataSource;
- sp<MetaData> mMeta;
+ MetaDataBase mMeta;
off64_t mOffset;
int64_t mCurrentTimeUs;
@@ -132,19 +133,10 @@
}
AACExtractor::AACExtractor(
- DataSourceBase *source, const sp<AMessage> &_meta)
+ DataSourceBase *source, off64_t offset)
: mDataSource(source),
mInitCheck(NO_INIT),
mFrameDurationUs(0) {
- sp<AMessage> meta = _meta;
-
- if (meta == NULL) {
- ALOGE("no metadata specified");
- return;
- }
-
- int64_t offset;
- CHECK(meta->findInt64("offset", &offset));
uint8_t profile, sf_index, channel, header[2];
if (mDataSource->readAt(offset + 2, &header, 2) < 2) {
@@ -159,7 +151,7 @@
}
channel = (header[0] & 0x1) << 2 | (header[1] >> 6);
- mMeta = MakeAACCodecSpecificData(profile, sf_index, channel);
+ MakeAACCodecSpecificData(mMeta, profile, sf_index, channel);
off64_t streamSize, numFrames = 0;
size_t frameSize = 0;
@@ -182,7 +174,7 @@
// Round up and get the duration
mFrameDurationUs = (1024 * 1000000ll + (sr - 1)) / sr;
duration = numFrames * mFrameDurationUs;
- mMeta->setInt64(kKeyDuration, duration);
+ mMeta.setInt64(kKeyDuration, duration);
}
mInitCheck = OK;
@@ -191,23 +183,20 @@
AACExtractor::~AACExtractor() {
}
-sp<MetaData> AACExtractor::getMetaData() {
- sp<MetaData> meta = new MetaData;
-
- if (mInitCheck != OK) {
- return meta;
+status_t AACExtractor::getMetaData(MetaDataBase &meta) {
+ meta.clear();
+ if (mInitCheck == OK) {
+ meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC_ADTS);
}
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC_ADTS);
-
- return meta;
+ return OK;
}
size_t AACExtractor::countTracks() {
return mInitCheck == OK ? 1 : 0;
}
-MediaSourceBase *AACExtractor::getTrack(size_t index) {
+MediaTrack *AACExtractor::getTrack(size_t index) {
if (mInitCheck != OK || index != 0) {
return NULL;
}
@@ -215,12 +204,13 @@
return new AACSource(mDataSource, mMeta, mOffsetVector, mFrameDurationUs);
}
-sp<MetaData> AACExtractor::getTrackMetaData(size_t index, uint32_t /* flags */) {
+status_t AACExtractor::getTrackMetaData(MetaDataBase &meta, size_t index, uint32_t /* flags */) {
if (mInitCheck != OK || index != 0) {
- return NULL;
+ return UNKNOWN_ERROR;
}
- return mMeta;
+ meta = mMeta;
+ return OK;
}
////////////////////////////////////////////////////////////////////////////////
@@ -229,7 +219,8 @@
const size_t AACSource::kMaxFrameSize = 8192;
AACSource::AACSource(
- DataSourceBase *source, const sp<MetaData> &meta,
+ DataSourceBase *source,
+ MetaDataBase &meta,
const Vector<uint64_t> &offset_vector,
int64_t frame_duration_us)
: mDataSource(source),
@@ -248,7 +239,7 @@
}
}
-status_t AACSource::start(MetaData * /* params */) {
+status_t AACSource::start(MetaDataBase * /* params */) {
CHECK(!mStarted);
if (mOffsetVector.empty()) {
@@ -275,8 +266,9 @@
return OK;
}
-sp<MetaData> AACSource::getFormat() {
- return mMeta;
+status_t AACSource::getFormat(MetaDataBase &meta) {
+ meta = mMeta;
+ return OK;
}
status_t AACSource::read(
@@ -319,8 +311,8 @@
}
buffer->set_range(0, frameSizeWithoutHeader);
- buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs);
- buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+ buffer->meta_data().setInt64(kKeyTime, mCurrentTimeUs);
+ buffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
mOffset += frameSize;
mCurrentTimeUs += mFrameDurationUs;
@@ -334,14 +326,8 @@
static MediaExtractor* CreateExtractor(
DataSourceBase *source,
void *meta) {
- sp<AMessage> metaData = static_cast<AMessage *>(meta);
- return new AACExtractor(source, metaData);
-}
-
-static void FreeMeta(void *meta) {
- if (meta != nullptr) {
- static_cast<AMessage *>(meta)->decStrong(nullptr);
- }
+ off64_t offset = *static_cast<off64_t*>(meta);
+ return new AACExtractor(source, offset);
}
static MediaExtractor::CreatorFunc Sniff(
@@ -386,12 +372,9 @@
if ((header[0] == 0xff) && ((header[1] & 0xf6) == 0xf0)) {
*confidence = 0.2;
- AMessage *msg = new AMessage;
- msg->setInt64("offset", pos);
- *meta = msg;
- *freeMeta = &FreeMeta;
- // ref count will be decreased in FreeMeta.
- msg->incStrong(nullptr);
+ off64_t *offPtr = (off64_t*) malloc(sizeof(off64_t));
+ *meta = offPtr;
+ *freeMeta = ::free;
return CreateExtractor;
}
diff --git a/media/extractors/aac/AACExtractor.h b/media/extractors/aac/AACExtractor.h
index e99699c..9dadbed 100644
--- a/media/extractors/aac/AACExtractor.h
+++ b/media/extractors/aac/AACExtractor.h
@@ -19,6 +19,7 @@
#define AAC_EXTRACTOR_H_
#include <media/MediaExtractor.h>
+#include <media/stagefright/MetaDataBase.h>
#include <utils/Vector.h>
@@ -29,13 +30,13 @@
class AACExtractor : public MediaExtractor {
public:
- AACExtractor(DataSourceBase *source, const sp<AMessage> &meta);
+ AACExtractor(DataSourceBase *source, off64_t offset);
virtual size_t countTracks();
- virtual MediaSourceBase *getTrack(size_t index);
- virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+ virtual MediaTrack *getTrack(size_t index);
+ virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
- virtual sp<MetaData> getMetaData();
+ virtual status_t getMetaData(MetaDataBase& meta);
virtual const char * name() { return "AACExtractor"; }
protected:
@@ -43,7 +44,7 @@
private:
DataSourceBase *mDataSource;
- sp<MetaData> mMeta;
+ MetaDataBase mMeta;
status_t mInitCheck;
Vector<uint64_t> mOffsetVector;
@@ -54,8 +55,7 @@
};
bool SniffAAC(
- DataSourceBase *source, String8 *mimeType, float *confidence,
- sp<AMessage> *);
+ DataSourceBase *source, String8 *mimeType, float *confidence, off64_t *offset);
} // namespace android
diff --git a/media/extractors/amr/AMRExtractor.cpp b/media/extractors/amr/AMRExtractor.cpp
index 59d9ef1..f56d5ef 100644
--- a/media/extractors/amr/AMRExtractor.cpp
+++ b/media/extractors/amr/AMRExtractor.cpp
@@ -21,7 +21,7 @@
#include "AMRExtractor.h"
#include <media/DataSourceBase.h>
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDefs.h>
@@ -31,18 +31,19 @@
namespace android {
-class AMRSource : public MediaSourceBase {
+class AMRSource : public MediaTrack {
public:
- AMRSource(DataSourceBase *source,
- const sp<MetaData> &meta,
- bool isWide,
- const off64_t *offset_table,
- size_t offset_table_length);
+ AMRSource(
+ DataSourceBase *source,
+ MetaDataBase &meta,
+ bool isWide,
+ const off64_t *offset_table,
+ size_t offset_table_length);
- virtual status_t start(MetaData *params = NULL);
+ virtual status_t start(MetaDataBase *params = NULL);
virtual status_t stop();
- virtual sp<MetaData> getFormat();
+ virtual status_t getFormat(MetaDataBase &);
virtual status_t read(
MediaBufferBase **buffer, const ReadOptions *options = NULL);
@@ -52,7 +53,7 @@
private:
DataSourceBase *mDataSource;
- sp<MetaData> mMeta;
+ MetaDataBase mMeta;
bool mIsWide;
off64_t mOffset;
@@ -116,25 +117,48 @@
return OK;
}
+static bool SniffAMR(
+ DataSourceBase *source, bool *isWide, float *confidence) {
+ char header[9];
+
+ if (source->readAt(0, header, sizeof(header)) != sizeof(header)) {
+ return false;
+ }
+
+ if (!memcmp(header, "#!AMR\n", 6)) {
+ if (isWide != nullptr) {
+ *isWide = false;
+ }
+ *confidence = 0.5;
+
+ return true;
+ } else if (!memcmp(header, "#!AMR-WB\n", 9)) {
+ if (isWide != nullptr) {
+ *isWide = true;
+ }
+ *confidence = 0.5;
+
+ return true;
+ }
+
+ return false;
+}
+
AMRExtractor::AMRExtractor(DataSourceBase *source)
: mDataSource(source),
mInitCheck(NO_INIT),
mOffsetTableLength(0) {
- String8 mimeType;
float confidence;
- if (!SniffAMR(mDataSource, &mimeType, &confidence)) {
+ if (!SniffAMR(mDataSource, &mIsWide, &confidence)) {
return;
}
- mIsWide = (mimeType == MEDIA_MIMETYPE_AUDIO_AMR_WB);
-
- mMeta = new MetaData;
- mMeta->setCString(
+ mMeta.setCString(
kKeyMIMEType, mIsWide ? MEDIA_MIMETYPE_AUDIO_AMR_WB
: MEDIA_MIMETYPE_AUDIO_AMR_NB);
- mMeta->setInt32(kKeyChannelCount, 1);
- mMeta->setInt32(kKeySampleRate, mIsWide ? 16000 : 8000);
+ mMeta.setInt32(kKeyChannelCount, 1);
+ mMeta.setInt32(kKeySampleRate, mIsWide ? 16000 : 8000);
off64_t offset = mIsWide ? 9 : 6;
off64_t streamSize;
@@ -161,7 +185,7 @@
numFrames ++;
}
- mMeta->setInt64(kKeyDuration, duration);
+ mMeta.setInt64(kKeyDuration, duration);
}
mInitCheck = OK;
@@ -170,23 +194,21 @@
AMRExtractor::~AMRExtractor() {
}
-sp<MetaData> AMRExtractor::getMetaData() {
- sp<MetaData> meta = new MetaData;
+status_t AMRExtractor::getMetaData(MetaDataBase &meta) {
+ meta.clear();
- if (mInitCheck != OK) {
- return meta;
+ if (mInitCheck == OK) {
+ meta.setCString(kKeyMIMEType, mIsWide ? "audio/amr-wb" : "audio/amr");
}
- meta->setCString(kKeyMIMEType, mIsWide ? "audio/amr-wb" : "audio/amr");
-
- return meta;
+ return OK;
}
size_t AMRExtractor::countTracks() {
return mInitCheck == OK ? 1 : 0;
}
-MediaSourceBase *AMRExtractor::getTrack(size_t index) {
+MediaTrack *AMRExtractor::getTrack(size_t index) {
if (mInitCheck != OK || index != 0) {
return NULL;
}
@@ -195,18 +217,19 @@
mOffsetTable, mOffsetTableLength);
}
-sp<MetaData> AMRExtractor::getTrackMetaData(size_t index, uint32_t /* flags */) {
+status_t AMRExtractor::getTrackMetaData(MetaDataBase &meta, size_t index, uint32_t /* flags */) {
if (mInitCheck != OK || index != 0) {
- return NULL;
+ return UNKNOWN_ERROR;
}
- return mMeta;
+ meta = mMeta;
+ return OK;
}
////////////////////////////////////////////////////////////////////////////////
AMRSource::AMRSource(
- DataSourceBase *source, const sp<MetaData> &meta,
+ DataSourceBase *source, MetaDataBase &meta,
bool isWide, const off64_t *offset_table, size_t offset_table_length)
: mDataSource(source),
mMeta(meta),
@@ -227,7 +250,7 @@
}
}
-status_t AMRSource::start(MetaData * /* params */) {
+status_t AMRSource::start(MetaDataBase * /* params */) {
CHECK(!mStarted);
mOffset = mIsWide ? 9 : 6;
@@ -249,8 +272,9 @@
return OK;
}
-sp<MetaData> AMRSource::getFormat() {
- return mMeta;
+status_t AMRSource::getFormat(MetaDataBase &meta) {
+ meta = mMeta;
+ return OK;
}
status_t AMRSource::read(
@@ -325,8 +349,8 @@
}
buffer->set_range(0, frameSize);
- buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs);
- buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+ buffer->meta_data().setInt64(kKeyTime, mCurrentTimeUs);
+ buffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
mOffset += frameSize;
mCurrentTimeUs += 20000; // Each frame is 20ms
@@ -338,33 +362,6 @@
////////////////////////////////////////////////////////////////////////////////
-bool SniffAMR(
- DataSourceBase *source, String8 *mimeType, float *confidence) {
- char header[9];
-
- if (source->readAt(0, header, sizeof(header)) != sizeof(header)) {
- return false;
- }
-
- if (!memcmp(header, "#!AMR\n", 6)) {
- if (mimeType != nullptr) {
- *mimeType = MEDIA_MIMETYPE_AUDIO_AMR_NB;
- }
- *confidence = 0.5;
-
- return true;
- } else if (!memcmp(header, "#!AMR-WB\n", 9)) {
- if (mimeType != nullptr) {
- *mimeType = MEDIA_MIMETYPE_AUDIO_AMR_WB;
- }
- *confidence = 0.5;
-
- return true;
- }
-
- return false;
-}
-
extern "C" {
// This is the only symbol that needs to be exported
__attribute__ ((visibility ("default")))
diff --git a/media/extractors/amr/AMRExtractor.h b/media/extractors/amr/AMRExtractor.h
index b8b44ea..c90b325 100644
--- a/media/extractors/amr/AMRExtractor.h
+++ b/media/extractors/amr/AMRExtractor.h
@@ -20,6 +20,7 @@
#include <utils/Errors.h>
#include <media/MediaExtractor.h>
+#include <media/stagefright/MetaDataBase.h>
namespace android {
@@ -32,10 +33,10 @@
explicit AMRExtractor(DataSourceBase *source);
virtual size_t countTracks();
- virtual MediaSourceBase *getTrack(size_t index);
- virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+ virtual MediaTrack *getTrack(size_t index);
+ virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
- virtual sp<MetaData> getMetaData();
+ virtual status_t getMetaData(MetaDataBase& meta);
virtual const char * name() { return "AMRExtractor"; }
protected:
@@ -43,7 +44,7 @@
private:
DataSourceBase *mDataSource;
- sp<MetaData> mMeta;
+ MetaDataBase mMeta;
status_t mInitCheck;
bool mIsWide;
@@ -54,9 +55,6 @@
AMRExtractor &operator=(const AMRExtractor &);
};
-bool SniffAMR(
- DataSourceBase *source, String8 *mimeType, float *confidence);
-
} // namespace android
#endif // AMR_EXTRACTOR_H_
diff --git a/media/extractors/amr/Android.bp b/media/extractors/amr/Android.bp
index e5bbe31..bd8a00c 100644
--- a/media/extractors/amr/Android.bp
+++ b/media/extractors/amr/Android.bp
@@ -10,7 +10,6 @@
"liblog",
"libmediaextractor",
"libstagefright_foundation",
- "libutils",
],
name: "libamrextractor",
diff --git a/media/extractors/flac/Android.bp b/media/extractors/flac/Android.bp
index 84ba6d3..0160ca4 100644
--- a/media/extractors/flac/Android.bp
+++ b/media/extractors/flac/Android.bp
@@ -11,7 +11,6 @@
"liblog",
"libmediaextractor",
"libstagefright_foundation",
- "libutils",
],
static_libs: [
diff --git a/media/extractors/flac/FLACExtractor.cpp b/media/extractors/flac/FLACExtractor.cpp
index 2c5e43e..e3da259 100644
--- a/media/extractors/flac/FLACExtractor.cpp
+++ b/media/extractors/flac/FLACExtractor.cpp
@@ -23,11 +23,11 @@
#include "FLAC/stream_decoder.h"
#include <media/DataSourceBase.h>
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
+#include <media/VorbisComment.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/base64.h>
-#include <media/stagefright/foundation/ByteUtils.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaData.h>
@@ -35,142 +35,18 @@
namespace android {
-// also exists in OggExtractor, candidate for moving to utility/support library?
-static void extractAlbumArt(
- const sp<MetaData> &fileMeta, const void *data, size_t size) {
- ALOGV("extractAlbumArt from '%s'", (const char *)data);
-
- sp<ABuffer> flacBuffer = decodeBase64(AString((const char *)data, size));
- if (flacBuffer == NULL) {
- ALOGE("malformed base64 encoded data.");
- return;
- }
-
- size_t flacSize = flacBuffer->size();
- uint8_t *flac = flacBuffer->data();
- ALOGV("got flac of size %zu", flacSize);
-
- uint32_t picType;
- uint32_t typeLen;
- uint32_t descLen;
- uint32_t dataLen;
- char type[128];
-
- if (flacSize < 8) {
- return;
- }
-
- picType = U32_AT(flac);
-
- if (picType != 3) {
- // This is not a front cover.
- return;
- }
-
- typeLen = U32_AT(&flac[4]);
- if (typeLen > sizeof(type) - 1) {
- return;
- }
-
- // we've already checked above that flacSize >= 8
- if (flacSize - 8 < typeLen) {
- return;
- }
-
- memcpy(type, &flac[8], typeLen);
- type[typeLen] = '\0';
-
- ALOGV("picType = %d, type = '%s'", picType, type);
-
- if (!strcmp(type, "-->")) {
- // This is not inline cover art, but an external url instead.
- return;
- }
-
- if (flacSize < 32 || flacSize - 32 < typeLen) {
- return;
- }
-
- descLen = U32_AT(&flac[8 + typeLen]);
- if (flacSize - 32 - typeLen < descLen) {
- return;
- }
-
- dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]);
-
- // we've already checked above that (flacSize - 32 - typeLen - descLen) >= 0
- if (flacSize - 32 - typeLen - descLen < dataLen) {
- return;
- }
-
- ALOGV("got image data, %zu trailing bytes",
- flacSize - 32 - typeLen - descLen - dataLen);
-
- fileMeta->setData(
- kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen);
-
- fileMeta->setCString(kKeyAlbumArtMIME, type);
-}
-
-// also exists in OggExtractor, candidate for moving to utility/support library?
-static void parseVorbisComment(
- const sp<MetaData> &fileMeta, const char *comment, size_t commentLength)
-{
- struct {
- const char *const mTag;
- uint32_t mKey;
- } kMap[] = {
- { "TITLE", kKeyTitle },
- { "ARTIST", kKeyArtist },
- { "ALBUMARTIST", kKeyAlbumArtist },
- { "ALBUM ARTIST", kKeyAlbumArtist },
- { "COMPILATION", kKeyCompilation },
- { "ALBUM", kKeyAlbum },
- { "COMPOSER", kKeyComposer },
- { "GENRE", kKeyGenre },
- { "AUTHOR", kKeyAuthor },
- { "TRACKNUMBER", kKeyCDTrackNumber },
- { "DISCNUMBER", kKeyDiscNumber },
- { "DATE", kKeyDate },
- { "YEAR", kKeyYear },
- { "LYRICIST", kKeyWriter },
- { "METADATA_BLOCK_PICTURE", kKeyAlbumArt },
- { "ANDROID_LOOP", kKeyAutoLoop },
- };
-
- for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) {
- size_t tagLen = strlen(kMap[j].mTag);
- if (!strncasecmp(kMap[j].mTag, comment, tagLen)
- && comment[tagLen] == '=') {
- if (kMap[j].mKey == kKeyAlbumArt) {
- extractAlbumArt(
- fileMeta,
- &comment[tagLen + 1],
- commentLength - tagLen - 1);
- } else if (kMap[j].mKey == kKeyAutoLoop) {
- if (!strcasecmp(&comment[tagLen + 1], "true")) {
- fileMeta->setInt32(kKeyAutoLoop, true);
- }
- } else {
- fileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]);
- }
- }
- }
-
-}
-
class FLACParser;
-class FLACSource : public MediaSourceBase {
+class FLACSource : public MediaTrack {
public:
FLACSource(
DataSourceBase *dataSource,
- const sp<MetaData> &trackMetadata);
+ MetaDataBase &meta);
- virtual status_t start(MetaData *params);
+ virtual status_t start(MetaDataBase *params);
virtual status_t stop();
- virtual sp<MetaData> getFormat();
+ virtual status_t getFormat(MetaDataBase &meta);
virtual status_t read(
MediaBufferBase **buffer, const ReadOptions *options = NULL);
@@ -180,13 +56,11 @@
private:
DataSourceBase *mDataSource;
- sp<MetaData> mTrackMetadata;
- sp<FLACParser> mParser;
+ MetaDataBase mTrackMetadata;
+ FLACParser *mParser;
bool mInitCheck;
bool mStarted;
- status_t init();
-
// no copy constructor or assignment
FLACSource(const FLACSource &);
FLACSource &operator=(const FLACSource &);
@@ -195,7 +69,7 @@
// FLACParser wraps a C libFLAC parser aka stream decoder
-class FLACParser : public RefBase {
+class FLACParser {
public:
enum {
@@ -205,8 +79,10 @@
explicit FLACParser(
DataSourceBase *dataSource,
// If metadata pointers aren't provided, we don't fill them
- const sp<MetaData> &fileMetadata = 0,
- const sp<MetaData> &trackMetadata = 0);
+ MetaDataBase *fileMetadata = 0,
+ MetaDataBase *trackMetadata = 0);
+
+ virtual ~FLACParser();
status_t initCheck() const {
return mInitCheck;
@@ -239,13 +115,10 @@
return readBuffer(true, sample);
}
-protected:
- virtual ~FLACParser();
-
private:
DataSourceBase *mDataSource;
- sp<MetaData> mFileMetadata;
- sp<MetaData> mTrackMetadata;
+ MetaDataBase *mFileMetadata;
+ MetaDataBase *mTrackMetadata;
bool mInitCheck;
// media buffers
@@ -613,8 +486,8 @@
FLACParser::FLACParser(
DataSourceBase *dataSource,
- const sp<MetaData> &fileMetadata,
- const sp<MetaData> &trackMetadata)
+ MetaDataBase *fileMetadata,
+ MetaDataBase *trackMetadata)
: mDataSource(dataSource),
mFileMetadata(fileMetadata),
mTrackMetadata(trackMetadata),
@@ -825,8 +698,8 @@
CHECK(mWriteHeader.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
FLAC__uint64 sampleNumber = mWriteHeader.number.sample_number;
int64_t timeUs = (1000000LL * sampleNumber) / getSampleRate();
- buffer->meta_data()->setInt64(kKeyTime, timeUs);
- buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+ buffer->meta_data().setInt64(kKeyTime, timeUs);
+ buffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
return buffer;
}
@@ -834,7 +707,7 @@
FLACSource::FLACSource(
DataSourceBase *dataSource,
- const sp<MetaData> &trackMetadata)
+ MetaDataBase &trackMetadata)
: mDataSource(dataSource),
mTrackMetadata(trackMetadata),
mParser(0),
@@ -842,7 +715,9 @@
mStarted(false)
{
ALOGV("FLACSource::FLACSource");
- mInitCheck = init();
+ // re-use the same track metadata passed into constructor from FLACExtractor
+ mParser = new FLACParser(mDataSource);
+ mInitCheck = mParser->initCheck();
}
FLACSource::~FLACSource()
@@ -851,9 +726,10 @@
if (mStarted) {
stop();
}
+ delete mParser;
}
-status_t FLACSource::start(MetaData * /* params */)
+status_t FLACSource::start(MetaDataBase * /* params */)
{
ALOGV("FLACSource::start");
@@ -875,9 +751,10 @@
return OK;
}
-sp<MetaData> FLACSource::getFormat()
+status_t FLACSource::getFormat(MetaDataBase &meta)
{
- return mTrackMetadata;
+ meta = mTrackMetadata;
+ return OK;
}
status_t FLACSource::read(
@@ -907,28 +784,24 @@
return buffer != NULL ? (status_t) OK : (status_t) ERROR_END_OF_STREAM;
}
-status_t FLACSource::init()
-{
- ALOGV("FLACSource::init");
- // re-use the same track metadata passed into constructor from FLACExtractor
- mParser = new FLACParser(mDataSource);
- return mParser->initCheck();
-}
-
// FLACExtractor
FLACExtractor::FLACExtractor(
DataSourceBase *dataSource)
: mDataSource(dataSource),
+ mParser(nullptr),
mInitCheck(false)
{
ALOGV("FLACExtractor::FLACExtractor");
- mInitCheck = init();
+ // FLACParser will fill in the metadata for us
+ mParser = new FLACParser(mDataSource, &mFileMetadata, &mTrackMetadata);
+ mInitCheck = mParser->initCheck();
}
FLACExtractor::~FLACExtractor()
{
ALOGV("~FLACExtractor::FLACExtractor");
+ delete mParser;
}
size_t FLACExtractor::countTracks()
@@ -936,7 +809,7 @@
return mInitCheck == OK ? 1 : 0;
}
-MediaSourceBase *FLACExtractor::getTrack(size_t index)
+MediaTrack *FLACExtractor::getTrack(size_t index)
{
if (mInitCheck != OK || index > 0) {
return NULL;
@@ -944,26 +817,20 @@
return new FLACSource(mDataSource, mTrackMetadata);
}
-sp<MetaData> FLACExtractor::getTrackMetaData(
+status_t FLACExtractor::getTrackMetaData(
+ MetaDataBase &meta,
size_t index, uint32_t /* flags */) {
if (mInitCheck != OK || index > 0) {
- return NULL;
+ return UNKNOWN_ERROR;
}
- return mTrackMetadata;
+ meta = mTrackMetadata;
+ return OK;
}
-status_t FLACExtractor::init()
+status_t FLACExtractor::getMetaData(MetaDataBase &meta)
{
- mFileMetadata = new MetaData;
- mTrackMetadata = new MetaData;
- // FLACParser will fill in the metadata for us
- mParser = new FLACParser(mDataSource, mFileMetadata, mTrackMetadata);
- return mParser->initCheck();
-}
-
-sp<MetaData> FLACExtractor::getMetaData()
-{
- return mFileMetadata;
+ meta = mFileMetadata;
+ return OK;
}
// Sniffer
diff --git a/media/extractors/flac/FLACExtractor.h b/media/extractors/flac/FLACExtractor.h
index f41d878..7fb6ec6 100644
--- a/media/extractors/flac/FLACExtractor.h
+++ b/media/extractors/flac/FLACExtractor.h
@@ -19,6 +19,7 @@
#include <media/DataSourceBase.h>
#include <media/MediaExtractor.h>
+#include <media/stagefright/MetaDataBase.h>
#include <utils/String8.h>
namespace android {
@@ -31,10 +32,10 @@
explicit FLACExtractor(DataSourceBase *source);
virtual size_t countTracks();
- virtual MediaSourceBase *getTrack(size_t index);
- virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+ virtual MediaTrack *getTrack(size_t index);
+ virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
- virtual sp<MetaData> getMetaData();
+ virtual status_t getMetaData(MetaDataBase& meta);
virtual const char * name() { return "FLACExtractor"; }
protected:
@@ -42,14 +43,12 @@
private:
DataSourceBase *mDataSource;
- sp<FLACParser> mParser;
+ FLACParser *mParser;
status_t mInitCheck;
- sp<MetaData> mFileMetadata;
+ MetaDataBase mFileMetadata;
// There is only one track
- sp<MetaData> mTrackMetadata;
-
- status_t init();
+ MetaDataBase mTrackMetadata;
FLACExtractor(const FLACExtractor &);
FLACExtractor &operator=(const FLACExtractor &);
diff --git a/media/extractors/midi/Android.bp b/media/extractors/midi/Android.bp
index 9af128e..5412e99 100644
--- a/media/extractors/midi/Android.bp
+++ b/media/extractors/midi/Android.bp
@@ -9,8 +9,7 @@
shared_libs: [
"liblog",
"libmediaextractor",
- "libstagefright_foundation",
- "libutils",
+ "libstagefright_foundation"
],
static_libs: [
diff --git a/media/extractors/midi/MidiExtractor.cpp b/media/extractors/midi/MidiExtractor.cpp
index cf446db..949fbe0 100644
--- a/media/extractors/midi/MidiExtractor.cpp
+++ b/media/extractors/midi/MidiExtractor.cpp
@@ -25,7 +25,7 @@
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaData.h>
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
#include <libsonivox/eas_reverb.h>
namespace android {
@@ -33,16 +33,16 @@
// how many Sonivox output buffers to aggregate into one MediaBufferBase
static const int NUM_COMBINE_BUFFERS = 4;
-class MidiSource : public MediaSourceBase {
+class MidiSource : public MediaTrack {
public:
MidiSource(
- const sp<MidiEngine> &engine,
- const sp<MetaData> &trackMetadata);
+ MidiEngine &engine,
+ MetaDataBase &trackMetadata);
- virtual status_t start(MetaData *params);
+ virtual status_t start(MetaDataBase *params);
virtual status_t stop();
- virtual sp<MetaData> getFormat();
+ virtual status_t getFormat(MetaDataBase&);
virtual status_t read(
MediaBufferBase **buffer, const ReadOptions *options = NULL);
@@ -51,8 +51,8 @@
virtual ~MidiSource();
private:
- sp<MidiEngine> mEngine;
- sp<MetaData> mTrackMetadata;
+ MidiEngine &mEngine;
+ MetaDataBase &mTrackMetadata;
bool mInitCheck;
bool mStarted;
@@ -68,8 +68,8 @@
// Midisource
MidiSource::MidiSource(
- const sp<MidiEngine> &engine,
- const sp<MetaData> &trackMetadata)
+ MidiEngine &engine,
+ MetaDataBase &trackMetadata)
: mEngine(engine),
mTrackMetadata(trackMetadata),
mInitCheck(false),
@@ -87,13 +87,13 @@
}
}
-status_t MidiSource::start(MetaData * /* params */)
+status_t MidiSource::start(MetaDataBase * /* params */)
{
ALOGV("MidiSource::start");
CHECK(!mStarted);
mStarted = true;
- mEngine->allocateBuffers();
+ mEngine.allocateBuffers();
return OK;
}
@@ -103,14 +103,15 @@
CHECK(mStarted);
mStarted = false;
- mEngine->releaseBuffers();
+ mEngine.releaseBuffers();
return OK;
}
-sp<MetaData> MidiSource::getFormat()
+status_t MidiSource::getFormat(MetaDataBase &meta)
{
- return mTrackMetadata;
+ meta = mTrackMetadata;
+ return OK;
}
status_t MidiSource::read(
@@ -125,9 +126,9 @@
if (seekTimeUs <= 0LL) {
seekTimeUs = 0LL;
}
- mEngine->seekTo(seekTimeUs);
+ mEngine.seekTo(seekTimeUs);
}
- buffer = mEngine->readBuffer();
+ buffer = mEngine.readBuffer();
*outBuffer = buffer;
ALOGV("MidiSource::read %p done", this);
return buffer != NULL ? (status_t) OK : (status_t) ERROR_END_OF_STREAM;
@@ -142,8 +143,8 @@
// MidiEngine
MidiEngine::MidiEngine(DataSourceBase *dataSource,
- const sp<MetaData> &fileMetadata,
- const sp<MetaData> &trackMetadata) :
+ MetaDataBase *fileMetadata,
+ MetaDataBase *trackMetadata) :
mGroup(NULL),
mEasData(NULL),
mEasHandle(NULL),
@@ -191,7 +192,7 @@
EAS_Shutdown(mEasData);
}
delete mGroup;
-
+ delete mIoWrapper;
}
status_t MidiEngine::initCheck() {
@@ -238,7 +239,7 @@
EAS_I32 timeMs;
EAS_GetLocation(mEasData, mEasHandle, &timeMs);
int64_t timeUs = 1000ll * timeMs;
- buffer->meta_data()->setInt64(kKeyTime, timeUs);
+ buffer->meta_data().setInt64(kKeyTime, timeUs);
EAS_PCM* p = (EAS_PCM*) buffer->data();
int numBytesOutput = 0;
@@ -266,9 +267,7 @@
mInitCheck(false)
{
ALOGV("MidiExtractor ctor");
- mFileMetadata = new MetaData;
- mTrackMetadata = new MetaData;
- mEngine = new MidiEngine(mDataSource, mFileMetadata, mTrackMetadata);
+ mEngine = new MidiEngine(mDataSource, &mFileMetadata, &mTrackMetadata);
mInitCheck = mEngine->initCheck();
}
@@ -282,35 +281,38 @@
return mInitCheck == OK ? 1 : 0;
}
-MediaSourceBase *MidiExtractor::getTrack(size_t index)
+MediaTrack *MidiExtractor::getTrack(size_t index)
{
if (mInitCheck != OK || index > 0) {
return NULL;
}
- return new MidiSource(mEngine, mTrackMetadata);
+ return new MidiSource(*mEngine, mTrackMetadata);
}
-sp<MetaData> MidiExtractor::getTrackMetaData(
+status_t MidiExtractor::getTrackMetaData(
+ MetaDataBase &meta,
size_t index, uint32_t /* flags */) {
ALOGV("MidiExtractor::getTrackMetaData");
if (mInitCheck != OK || index > 0) {
- return NULL;
+ return UNKNOWN_ERROR;
}
- return mTrackMetadata;
+ meta = mTrackMetadata;
+ return OK;
}
-sp<MetaData> MidiExtractor::getMetaData()
+status_t MidiExtractor::getMetaData(MetaDataBase &meta)
{
ALOGV("MidiExtractor::getMetaData");
- return mFileMetadata;
+ meta = mFileMetadata;
+ return OK;
}
// Sniffer
bool SniffMidi(DataSourceBase *source, float *confidence)
{
- sp<MidiEngine> p = new MidiEngine(source, NULL, NULL);
- if (p->initCheck() == OK) {
+ MidiEngine p(source, NULL, NULL);
+ if (p.initCheck() == OK) {
*confidence = 0.8;
ALOGV("SniffMidi: yes");
return true;
diff --git a/media/extractors/midi/MidiExtractor.h b/media/extractors/midi/MidiExtractor.h
index 4274513..244dd0f 100644
--- a/media/extractors/midi/MidiExtractor.h
+++ b/media/extractors/midi/MidiExtractor.h
@@ -21,17 +21,18 @@
#include <media/MediaExtractor.h>
#include <media/stagefright/MediaBufferBase.h>
#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MetaDataBase.h>
#include <media/MidiIoWrapper.h>
#include <utils/String8.h>
#include <libsonivox/eas.h>
namespace android {
-class MidiEngine : public RefBase {
+class MidiEngine {
public:
- MidiEngine(DataSourceBase *dataSource,
- const sp<MetaData> &fileMetadata,
- const sp<MetaData> &trackMetadata);
+ explicit MidiEngine(DataSourceBase *dataSource,
+ MetaDataBase *fileMetadata,
+ MetaDataBase *trackMetadata);
~MidiEngine();
status_t initCheck();
@@ -41,7 +42,7 @@
status_t seekTo(int64_t positionUs);
MediaBufferBase* readBuffer();
private:
- sp<MidiIoWrapper> mIoWrapper;
+ MidiIoWrapper *mIoWrapper;
MediaBufferGroup *mGroup;
EAS_DATA_HANDLE mEasData;
EAS_HANDLE mEasHandle;
@@ -55,10 +56,10 @@
explicit MidiExtractor(DataSourceBase *source);
virtual size_t countTracks();
- virtual MediaSourceBase *getTrack(size_t index);
- virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+ virtual MediaTrack *getTrack(size_t index);
+ virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
- virtual sp<MetaData> getMetaData();
+ virtual status_t getMetaData(MetaDataBase& meta);
virtual const char * name() { return "MidiExtractor"; }
protected:
@@ -67,12 +68,12 @@
private:
DataSourceBase *mDataSource;
status_t mInitCheck;
- sp<MetaData> mFileMetadata;
+ MetaDataBase mFileMetadata;
// There is only one track
- sp<MetaData> mTrackMetadata;
+ MetaDataBase mTrackMetadata;
- sp<MidiEngine> mEngine;
+ MidiEngine *mEngine;
EAS_DATA_HANDLE mEasData;
EAS_HANDLE mEasHandle;
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index 65988d3..5592a88 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -22,7 +22,7 @@
#include "MatroskaExtractor.h"
#include <media/DataSourceBase.h>
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/foundation/ABuffer.h>
@@ -121,13 +121,13 @@
BlockIterator &operator=(const BlockIterator &);
};
-struct MatroskaSource : public MediaSourceBase {
+struct MatroskaSource : public MediaTrack {
MatroskaSource(MatroskaExtractor *extractor, size_t index);
- virtual status_t start(MetaData *params);
+ virtual status_t start(MetaDataBase *params);
virtual status_t stop();
- virtual sp<MetaData> getFormat();
+ virtual status_t getFormat(MetaDataBase &);
virtual status_t read(
MediaBufferBase **buffer, const ReadOptions *options);
@@ -219,10 +219,10 @@
mExtractor->mTracks.itemAt(index).mTrackNum,
index),
mNALSizeLen(-1) {
- sp<MetaData> meta = mExtractor->mTracks.itemAt(index).mMeta;
+ MetaDataBase &meta = mExtractor->mTracks.editItemAt(index).mMeta;
const char *mime;
- CHECK(meta->findCString(kKeyMIMEType, &mime));
+ CHECK(meta.findCString(kKeyMIMEType, &mime));
mIsAudio = !strncasecmp("audio/", mime, 6);
@@ -233,11 +233,11 @@
const uint8_t *avcc;
size_t avccSize;
int32_t nalSizeLen = 0;
- if (meta->findInt32(kKeyNalLengthSize, &nalSizeLen)) {
+ if (meta.findInt32(kKeyNalLengthSize, &nalSizeLen)) {
if (nalSizeLen >= 0 && nalSizeLen <= 4) {
mNALSizeLen = nalSizeLen;
}
- } else if (meta->findData(kKeyAVCC, &dummy, (const void **)&avcc, &avccSize)
+ } else if (meta.findData(kKeyAVCC, &dummy, (const void **)&avcc, &avccSize)
&& avccSize >= 5u) {
mNALSizeLen = 1 + (avcc[4] & 3);
ALOGV("mNALSizeLen = %zd", mNALSizeLen);
@@ -250,7 +250,7 @@
uint32_t dummy;
const uint8_t *hvcc;
size_t hvccSize;
- if (meta->findData(kKeyHVCC, &dummy, (const void **)&hvcc, &hvccSize)
+ if (meta.findData(kKeyHVCC, &dummy, (const void **)&hvcc, &hvccSize)
&& hvccSize >= 22u) {
mNALSizeLen = 1 + (hvcc[14+7] & 3);
ALOGV("mNALSizeLen = %zu", mNALSizeLen);
@@ -266,7 +266,7 @@
clearPendingFrames();
}
-status_t MatroskaSource::start(MetaData * /* params */) {
+status_t MatroskaSource::start(MetaDataBase * /* params */) {
if (mType == AVC && mNALSizeLen < 0) {
return ERROR_MALFORMED;
}
@@ -282,8 +282,9 @@
return OK;
}
-sp<MetaData> MatroskaSource::getFormat() {
- return mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
+status_t MatroskaSource::getFormat(MetaDataBase &meta) {
+ meta = mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
+ return OK;
}
////////////////////////////////////////////////////////////////////////////////
@@ -589,7 +590,7 @@
return ERROR_MALFORMED;
}
- sp<MetaData> meta = mbuf->meta_data();
+ MetaDataBase &meta = mbuf->meta_data();
if (blockEncrypted) {
/*
* 0 1 2 3
@@ -612,13 +613,13 @@
uint32_t type;
const uint8_t *keyId;
size_t keyIdSize;
- sp<MetaData> trackMeta = mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
- CHECK(trackMeta->findData(kKeyCryptoKey, &type, (const void **)&keyId, &keyIdSize));
- meta->setData(kKeyCryptoKey, 0, keyId, keyIdSize);
+ const MetaDataBase &trackMeta = mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
+ CHECK(trackMeta.findData(kKeyCryptoKey, &type, (const void **)&keyId, &keyIdSize));
+ meta.setData(kKeyCryptoKey, 0, keyId, keyIdSize);
memcpy(ctrCounter, data + 1, 8);
- meta->setData(kKeyCryptoIV, 0, ctrCounter, 16);
- meta->setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes));
- meta->setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes));
+ meta.setData(kKeyCryptoIV, 0, ctrCounter, 16);
+ meta.setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes));
+ meta.setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes));
mbuf->set_range(9, mbuf->range_length() - 9);
} else {
/*
@@ -634,8 +635,8 @@
*/
int32_t plainSizes[] = { static_cast<int32_t>(mbuf->range_length() - 1) };
int32_t encryptedSizes[] = { 0 };
- meta->setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes));
- meta->setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes));
+ meta.setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes));
+ meta.setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes));
mbuf->set_range(1, mbuf->range_length() - 1);
}
@@ -668,8 +669,8 @@
memcpy(data, trackInfo->mHeader, trackInfo->mHeaderLen);
}
- mbuf->meta_data()->setInt64(kKeyTime, timeUs);
- mbuf->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey());
+ mbuf->meta_data().setInt64(kKeyTime, timeUs);
+ mbuf->meta_data().setInt32(kKeyIsSyncFrame, block->IsKey());
status_t err = frame.Read(mExtractor->mReader, data + trackInfo->mHeaderLen);
if (err == OK
@@ -736,7 +737,7 @@
if ((mType != AVC && mType != HEVC) || mNALSizeLen == 0) {
if (targetSampleTimeUs >= 0ll) {
- frame->meta_data()->setInt64(
+ frame->meta_data().setInt64(
kKeyTargetTime, targetSampleTimeUs);
}
@@ -824,12 +825,12 @@
}
int64_t timeUs;
- CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs));
+ CHECK(frame->meta_data().findInt64(kKeyTime, &timeUs));
int32_t isSync;
- CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync));
+ CHECK(frame->meta_data().findInt32(kKeyIsSyncFrame, &isSync));
- buffer->meta_data()->setInt64(kKeyTime, timeUs);
- buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync);
+ buffer->meta_data().setInt64(kKeyTime, timeUs);
+ buffer->meta_data().setInt32(kKeyIsSyncFrame, isSync);
dstPtr = (uint8_t *)buffer->data();
}
@@ -841,7 +842,7 @@
}
if (targetSampleTimeUs >= 0ll) {
- buffer->meta_data()->setInt64(
+ buffer->meta_data().setInt64(
kKeyTargetTime, targetSampleTimeUs);
}
@@ -927,7 +928,7 @@
return mTracks.size();
}
-MediaSourceBase *MatroskaExtractor::getTrack(size_t index) {
+MediaTrack *MatroskaExtractor::getTrack(size_t index) {
if (index >= mTracks.size()) {
return NULL;
}
@@ -935,10 +936,11 @@
return new MatroskaSource(this, index);
}
-sp<MetaData> MatroskaExtractor::getTrackMetaData(
+status_t MatroskaExtractor::getTrackMetaData(
+ MetaDataBase &meta,
size_t index, uint32_t flags) {
if (index >= mTracks.size()) {
- return NULL;
+ return UNKNOWN_ERROR;
}
if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails
@@ -947,7 +949,8 @@
mExtractedThumbnails = true;
}
- return mTracks.itemAt(index).mMeta;
+ meta = mTracks.itemAt(index).mMeta;
+ return OK;
}
bool MatroskaExtractor::isLiveStreaming() const {
@@ -982,7 +985,7 @@
}
static void addESDSFromCodecPrivate(
- const sp<MetaData> &meta,
+ MetaDataBase &meta,
bool isAudio, const void *priv, size_t privSize) {
int privSizeBytesRequired = bytesForSize(privSize);
@@ -1010,14 +1013,14 @@
storeSize(esds, idx, privSize);
memcpy(esds + idx, priv, privSize);
- meta->setData(kKeyESDS, 0, esds, esdsSize);
+ meta.setData(kKeyESDS, 0, esds, esdsSize);
delete[] esds;
esds = NULL;
}
status_t addVorbisCodecInfo(
- const sp<MetaData> &meta,
+ MetaDataBase &meta,
const void *_codecPrivate, size_t codecPrivateSize) {
// hexdump(_codecPrivate, codecPrivateSize);
@@ -1075,7 +1078,7 @@
if (codecPrivate[offset] != 0x01) {
return ERROR_MALFORMED;
}
- meta->setData(kKeyVorbisInfo, 0, &codecPrivate[offset], len1);
+ meta.setData(kKeyVorbisInfo, 0, &codecPrivate[offset], len1);
offset += len1;
if (codecPrivate[offset] != 0x03) {
@@ -1087,7 +1090,7 @@
return ERROR_MALFORMED;
}
- meta->setData(
+ meta.setData(
kKeyVorbisBooks, 0, &codecPrivate[offset],
codecPrivateSize - offset);
@@ -1095,11 +1098,11 @@
}
static status_t addFlacMetadata(
- const sp<MetaData> &meta,
+ MetaDataBase &meta,
const void *codecPrivate, size_t codecPrivateSize) {
// hexdump(codecPrivate, codecPrivateSize);
- meta->setData(kKeyFlacMetadata, 0, codecPrivate, codecPrivateSize);
+ meta.setData(kKeyFlacMetadata, 0, codecPrivate, codecPrivateSize);
int32_t maxInputSize = 64 << 10;
sp<FLACDecoder> flacDecoder = FLACDecoder::Create();
@@ -1120,7 +1123,7 @@
* streamInfo.max_blocksize * streamInfo.channels;
}
}
- meta->setInt32(kKeyMaxInputSize, maxInputSize);
+ meta.setInt32(kKeyMaxInputSize, maxInputSize);
return OK;
}
@@ -1143,14 +1146,12 @@
return ERROR_MALFORMED;
}
- sp<MetaData> avcMeta = MakeAVCCodecSpecificData(abuf);
- if (avcMeta == NULL) {
+ if (!MakeAVCCodecSpecificData(trackInfo->mMeta, abuf)) {
return ERROR_MALFORMED;
}
// Override the synthesized nal length size, which is arbitrary
- avcMeta->setInt32(kKeyNalLengthSize, 0);
- trackInfo->mMeta = avcMeta;
+ trackInfo->mMeta.setInt32(kKeyNalLengthSize, 0);
return OK;
}
@@ -1172,7 +1173,7 @@
}
void MatroskaExtractor::getColorInformation(
- const mkvparser::VideoTrack *vtrack, sp<MetaData> &meta) {
+ const mkvparser::VideoTrack *vtrack, MetaDataBase &meta) {
const mkvparser::Colour *color = vtrack->GetColour();
if (color == NULL) {
return;
@@ -1206,10 +1207,10 @@
ColorAspects aspects;
ColorUtils::convertIsoColorAspectsToCodecAspects(
primaries, transfer, coeffs, fullRange, aspects);
- meta->setInt32(kKeyColorPrimaries, aspects.mPrimaries);
- meta->setInt32(kKeyTransferFunction, aspects.mTransfer);
- meta->setInt32(kKeyColorMatrix, aspects.mMatrixCoeffs);
- meta->setInt32(
+ meta.setInt32(kKeyColorPrimaries, aspects.mPrimaries);
+ meta.setInt32(kKeyTransferFunction, aspects.mTransfer);
+ meta.setInt32(kKeyColorMatrix, aspects.mMatrixCoeffs);
+ meta.setInt32(
kKeyColorRange, rangeSpecified ? aspects.mRange : ColorAspects::RangeUnspecified);
}
@@ -1254,13 +1255,13 @@
// Only advertise static info if at least one of the groups have been specified.
if (memcmp(&info, &nullInfo, sizeof(info)) != 0) {
info.mID = HDRStaticInfo::kType1;
- meta->setData(kKeyHdrStaticInfo, 'hdrS', &info, sizeof(info));
+ meta.setData(kKeyHdrStaticInfo, 'hdrS', &info, sizeof(info));
}
}
}
status_t MatroskaExtractor::initTrackInfo(
- const mkvparser::Track *track, const sp<MetaData> &meta, TrackInfo *trackInfo) {
+ const mkvparser::Track *track, MetaDataBase &meta, TrackInfo *trackInfo) {
trackInfo->mTrackNum = track->GetNumber();
trackInfo->mMeta = meta;
trackInfo->mExtractor = this;
@@ -1273,7 +1274,7 @@
for(size_t j = 0; j < encoding->GetEncryptionCount(); j++) {
const mkvparser::ContentEncoding::ContentEncryption *encryption;
encryption = encoding->GetEncryptionByIndex(j);
- trackInfo->mMeta->setData(kKeyCryptoKey, 0, encryption->key_id, encryption->key_id_len);
+ trackInfo->mMeta.setData(kKeyCryptoKey, 0, encryption->key_id, encryption->key_id_len);
trackInfo->mEncrypted = true;
break;
}
@@ -1322,7 +1323,7 @@
enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 };
- sp<MetaData> meta = new MetaData;
+ MetaDataBase meta;
status_t err = OK;
@@ -1333,19 +1334,19 @@
static_cast<const mkvparser::VideoTrack *>(track);
if (!strcmp("V_MPEG4/ISO/AVC", codecID)) {
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
- meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize);
+ meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+ meta.setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize);
} else if (!strcmp("V_MPEGH/ISO/HEVC", codecID)) {
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_HEVC);
+ meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_HEVC);
if (codecPrivateSize > 0) {
- meta->setData(kKeyHVCC, kTypeHVCC, codecPrivate, codecPrivateSize);
+ meta.setData(kKeyHVCC, kTypeHVCC, codecPrivate, codecPrivateSize);
} else {
ALOGW("HEVC is detected, but does not have configuration.");
continue;
}
} else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) {
if (codecPrivateSize > 0) {
- meta->setCString(
+ meta.setCString(
kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
addESDSFromCodecPrivate(
meta, false, codecPrivate, codecPrivateSize);
@@ -1355,13 +1356,13 @@
continue;
}
} else if (!strcmp("V_VP8", codecID)) {
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP8);
+ meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP8);
} else if (!strcmp("V_VP9", codecID)) {
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP9);
+ meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP9);
if (codecPrivateSize > 0) {
// 'csd-0' for VP9 is the Blob of Codec Private data as
// specified in http://www.webmproject.org/vp9/profiles/.
- meta->setData(
+ meta.setData(
kKeyVp9CodecPrivate, 0, codecPrivate,
codecPrivateSize);
}
@@ -1380,8 +1381,8 @@
ALOGW("track height exceeds int32_t, %lld", height);
continue;
}
- meta->setInt32(kKeyWidth, (int32_t)width);
- meta->setInt32(kKeyHeight, (int32_t)height);
+ meta.setInt32(kKeyWidth, (int32_t)width);
+ meta.setInt32(kKeyHeight, (int32_t)height);
// setting display width/height is optional
const long long displayUnit = vtrack->GetDisplayUnit();
@@ -1391,8 +1392,8 @@
&& displayHeight > 0 && displayHeight <= INT32_MAX) {
switch (displayUnit) {
case 0: // pixels
- meta->setInt32(kKeyDisplayWidth, (int32_t)displayWidth);
- meta->setInt32(kKeyDisplayHeight, (int32_t)displayHeight);
+ meta.setInt32(kKeyDisplayWidth, (int32_t)displayWidth);
+ meta.setInt32(kKeyDisplayHeight, (int32_t)displayHeight);
break;
case 1: // centimeters
case 2: // inches
@@ -1406,8 +1407,8 @@
const long long computedHeight =
std::max(height, width * displayHeight / displayWidth);
if (computedWidth <= INT32_MAX && computedHeight <= INT32_MAX) {
- meta->setInt32(kKeyDisplayWidth, (int32_t)computedWidth);
- meta->setInt32(kKeyDisplayHeight, (int32_t)computedHeight);
+ meta.setInt32(kKeyDisplayWidth, (int32_t)computedWidth);
+ meta.setInt32(kKeyDisplayHeight, (int32_t)computedHeight);
}
break;
}
@@ -1427,34 +1428,34 @@
static_cast<const mkvparser::AudioTrack *>(track);
if (!strcmp("A_AAC", codecID)) {
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
+ meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
CHECK(codecPrivateSize >= 2);
addESDSFromCodecPrivate(
meta, true, codecPrivate, codecPrivateSize);
} else if (!strcmp("A_VORBIS", codecID)) {
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
+ meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
err = addVorbisCodecInfo(
meta, codecPrivate, codecPrivateSize);
} else if (!strcmp("A_OPUS", codecID)) {
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_OPUS);
- meta->setData(kKeyOpusHeader, 0, codecPrivate, codecPrivateSize);
- meta->setInt64(kKeyOpusCodecDelay, track->GetCodecDelay());
- meta->setInt64(kKeyOpusSeekPreRoll, track->GetSeekPreRoll());
+ meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_OPUS);
+ meta.setData(kKeyOpusHeader, 0, codecPrivate, codecPrivateSize);
+ meta.setInt64(kKeyOpusCodecDelay, track->GetCodecDelay());
+ meta.setInt64(kKeyOpusSeekPreRoll, track->GetSeekPreRoll());
mSeekPreRollNs = track->GetSeekPreRoll();
} else if (!strcmp("A_MPEG/L3", codecID)) {
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
+ meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
} else if (!strcmp("A_FLAC", codecID)) {
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_FLAC);
+ meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_FLAC);
err = addFlacMetadata(meta, codecPrivate, codecPrivateSize);
} else {
ALOGW("%s is not supported.", codecID);
continue;
}
- meta->setInt32(kKeySampleRate, atrack->GetSamplingRate());
- meta->setInt32(kKeyChannelCount, atrack->GetChannels());
+ meta.setInt32(kKeySampleRate, atrack->GetSamplingRate());
+ meta.setInt32(kKeyChannelCount, atrack->GetChannels());
break;
}
@@ -1467,7 +1468,7 @@
char lang[4];
strncpy(lang, language, 3);
lang[3] = '\0';
- meta->setCString(kKeyMediaLanguage, lang);
+ meta.setCString(kKeyMediaLanguage, lang);
}
if (err != OK) {
@@ -1476,7 +1477,7 @@
}
long long durationNs = mSegment->GetDuration();
- meta->setInt64(kKeyDuration, (durationNs + 500) / 1000);
+ meta.setInt64(kKeyDuration, (durationNs + 500) / 1000);
mTracks.push();
size_t n = mTracks.size() - 1;
@@ -1498,7 +1499,7 @@
TrackInfo *info = &mTracks.editItemAt(i);
const char *mime;
- CHECK(info->mMeta->findCString(kKeyMIMEType, &mime));
+ CHECK(info->mMeta.findCString(kKeyMIMEType, &mime));
if (strncasecmp(mime, "video/", 6)) {
continue;
@@ -1524,18 +1525,16 @@
}
iter.advance();
}
- info->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
+ info->mMeta.setInt64(kKeyThumbnailTime, thumbnailTimeUs);
}
}
-sp<MetaData> MatroskaExtractor::getMetaData() {
- sp<MetaData> meta = new MetaData;
-
- meta->setCString(
+status_t MatroskaExtractor::getMetaData(MetaDataBase &meta) {
+ meta.setCString(
kKeyMIMEType,
mIsWebm ? "video/webm" : MEDIA_MIMETYPE_CONTAINER_MATROSKA);
- return meta;
+ return OK;
}
uint32_t MatroskaExtractor::flags() const {
diff --git a/media/extractors/mkv/MatroskaExtractor.h b/media/extractors/mkv/MatroskaExtractor.h
index 095452b..3568ea1 100644
--- a/media/extractors/mkv/MatroskaExtractor.h
+++ b/media/extractors/mkv/MatroskaExtractor.h
@@ -21,6 +21,7 @@
#include "mkvparser/mkvparser.h"
#include <media/MediaExtractor.h>
+#include <media/stagefright/MetaDataBase.h>
#include <utils/Vector.h>
#include <utils/threads.h>
@@ -38,12 +39,11 @@
virtual size_t countTracks();
- virtual MediaSourceBase *getTrack(size_t index);
+ virtual MediaTrack *getTrack(size_t index);
- virtual sp<MetaData> getTrackMetaData(
- size_t index, uint32_t flags);
+ virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
- virtual sp<MetaData> getMetaData();
+ virtual status_t getMetaData(MetaDataBase& meta);
virtual uint32_t flags() const;
@@ -59,7 +59,7 @@
struct TrackInfo {
unsigned long mTrackNum;
bool mEncrypted;
- sp<MetaData> mMeta;
+ MetaDataBase mMeta;
const MatroskaExtractor *mExtractor;
Vector<const mkvparser::CuePoint*> mCuePoints;
@@ -85,20 +85,21 @@
int64_t mSeekPreRollNs;
status_t synthesizeAVCC(TrackInfo *trackInfo, size_t index);
- status_t initTrackInfo(const mkvparser::Track *track, const sp<MetaData> &meta, TrackInfo *trackInfo);
+ status_t initTrackInfo(
+ const mkvparser::Track *track,
+ MetaDataBase &meta,
+ TrackInfo *trackInfo);
void addTracks();
void findThumbnails();
- void getColorInformation(const mkvparser::VideoTrack *vtrack, sp<MetaData> &meta);
+ void getColorInformation(
+ const mkvparser::VideoTrack *vtrack,
+ MetaDataBase &meta);
bool isLiveStreaming() const;
MatroskaExtractor(const MatroskaExtractor &);
MatroskaExtractor &operator=(const MatroskaExtractor &);
};
-bool SniffMatroska(
- DataSourceBase *source, String8 *mimeType, float *confidence,
- sp<AMessage> *);
-
} // namespace android
#endif // MATROSKA_EXTRACTOR_H_
diff --git a/media/extractors/mp3/MP3Extractor.cpp b/media/extractors/mp3/MP3Extractor.cpp
index 90ee653..33cff96 100644
--- a/media/extractors/mp3/MP3Extractor.cpp
+++ b/media/extractors/mp3/MP3Extractor.cpp
@@ -25,7 +25,7 @@
#include "XINGSeeker.h"
#include <media/DataSourceBase.h>
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/avc_utils.h>
@@ -209,17 +209,17 @@
return valid;
}
-class MP3Source : public MediaSourceBase {
+class MP3Source : public MediaTrack {
public:
MP3Source(
- const sp<MetaData> &meta, DataSourceBase *source,
+ MetaDataBase &meta, DataSourceBase *source,
off64_t first_frame_pos, uint32_t fixed_header,
- const sp<MP3Seeker> &seeker);
+ MP3Seeker *seeker);
- virtual status_t start(MetaData *params = NULL);
+ virtual status_t start(MetaDataBase *params = NULL);
virtual status_t stop();
- virtual sp<MetaData> getFormat();
+ virtual status_t getFormat(MetaDataBase &meta);
virtual status_t read(
MediaBufferBase **buffer, const ReadOptions *options = NULL);
@@ -229,14 +229,14 @@
private:
static const size_t kMaxFrameSize;
- sp<MetaData> mMeta;
+ MetaDataBase &mMeta;
DataSourceBase *mDataSource;
off64_t mFirstFramePos;
uint32_t mFixedHeader;
off64_t mCurrentPos;
int64_t mCurrentTimeUs;
bool mStarted;
- sp<MP3Seeker> mSeeker;
+ MP3Seeker *mSeeker;
MediaBufferGroup *mGroup;
int64_t mBasisTimeUs;
@@ -246,31 +246,31 @@
MP3Source &operator=(const MP3Source &);
};
+struct Mp3Meta {
+ off64_t pos;
+ off64_t post_id3_pos;
+ uint32_t header;
+};
+
MP3Extractor::MP3Extractor(
- DataSourceBase *source, const sp<AMessage> &meta)
+ DataSourceBase *source, Mp3Meta *meta)
: mInitCheck(NO_INIT),
mDataSource(source),
mFirstFramePos(-1),
- mFixedHeader(0) {
+ mFixedHeader(0),
+ mSeeker(NULL) {
off64_t pos = 0;
off64_t post_id3_pos;
uint32_t header;
bool success;
- int64_t meta_offset;
- uint32_t meta_header;
- int64_t meta_post_id3_offset;
- if (meta != NULL
- && meta->findInt64("offset", &meta_offset)
- && meta->findInt32("header", (int32_t *)&meta_header)
- && meta->findInt64("post-id3-offset", &meta_post_id3_offset)) {
+ if (meta != NULL) {
// The sniffer has already done all the hard work for us, simply
// accept its judgement.
- pos = (off64_t)meta_offset;
- header = meta_header;
- post_id3_pos = (off64_t)meta_post_id3_offset;
-
+ pos = meta->pos;
+ header = meta->header;
+ post_id3_pos = meta->post_id3_pos;
success = true;
} else {
success = Resync(mDataSource, 0, &pos, &post_id3_pos, &header);
@@ -283,8 +283,7 @@
mFirstFramePos = pos;
mFixedHeader = header;
- mMeta = new MetaData;
- sp<XINGSeeker> seeker = XINGSeeker::CreateFromSource(mDataSource, mFirstFramePos);
+ XINGSeeker *seeker = XINGSeeker::CreateFromSource(mDataSource, mFirstFramePos);
if (seeker == NULL) {
mSeeker = VBRISeeker::CreateFromSource(mDataSource, post_id3_pos);
@@ -293,8 +292,8 @@
int encd = seeker->getEncoderDelay();
int encp = seeker->getEncoderPadding();
if (encd != 0 || encp != 0) {
- mMeta->setInt32(kKeyEncoderDelay, encd);
- mMeta->setInt32(kKeyEncoderPadding, encp);
+ mMeta.setInt32(kKeyEncoderDelay, encd);
+ mMeta.setInt32(kKeyEncoderPadding, encp);
}
}
@@ -330,21 +329,21 @@
switch (layer) {
case 1:
- mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I);
+ mMeta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I);
break;
case 2:
- mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II);
+ mMeta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II);
break;
case 3:
- mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
+ mMeta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
break;
default:
TRESPASS();
}
- mMeta->setInt32(kKeySampleRate, sample_rate);
- mMeta->setInt32(kKeyBitRate, bitrate * 1000);
- mMeta->setInt32(kKeyChannelCount, num_channels);
+ mMeta.setInt32(kKeySampleRate, sample_rate);
+ mMeta.setInt32(kKeyBitRate, bitrate * 1000);
+ mMeta.setInt32(kKeyChannelCount, num_channels);
int64_t durationUs;
@@ -364,7 +363,7 @@
}
if (durationUs >= 0) {
- mMeta->setInt64(kKeyDuration, durationUs);
+ mMeta.setInt64(kKeyDuration, durationUs);
}
mInitCheck = OK;
@@ -391,8 +390,8 @@
int32_t delay, padding;
if (sscanf(value, " %*x %x %x %*x", &delay, &padding) == 2) {
- mMeta->setInt32(kKeyEncoderDelay, delay);
- mMeta->setInt32(kKeyEncoderPadding, padding);
+ mMeta.setInt32(kKeyEncoderDelay, delay);
+ mMeta.setInt32(kKeyEncoderPadding, padding);
}
break;
}
@@ -403,11 +402,15 @@
}
}
+MP3Extractor::~MP3Extractor() {
+ delete mSeeker;
+}
+
size_t MP3Extractor::countTracks() {
return mInitCheck != OK ? 0 : 1;
}
-MediaSourceBase *MP3Extractor::getTrack(size_t index) {
+MediaTrack *MP3Extractor::getTrack(size_t index) {
if (mInitCheck != OK || index != 0) {
return NULL;
}
@@ -417,13 +420,14 @@
mSeeker);
}
-sp<MetaData> MP3Extractor::getTrackMetaData(
+status_t MP3Extractor::getTrackMetaData(
+ MetaDataBase &meta,
size_t index, uint32_t /* flags */) {
if (mInitCheck != OK || index != 0) {
- return NULL;
+ return UNKNOWN_ERROR;
}
-
- return mMeta;
+ meta = mMeta;
+ return OK;
}
////////////////////////////////////////////////////////////////////////////////
@@ -436,9 +440,9 @@
// Set our max frame size to the nearest power of 2 above this size (aka, 4kB)
const size_t MP3Source::kMaxFrameSize = (1 << 12); /* 4096 bytes */
MP3Source::MP3Source(
- const sp<MetaData> &meta, DataSourceBase *source,
+ MetaDataBase &meta, DataSourceBase *source,
off64_t first_frame_pos, uint32_t fixed_header,
- const sp<MP3Seeker> &seeker)
+ MP3Seeker *seeker)
: mMeta(meta),
mDataSource(source),
mFirstFramePos(first_frame_pos),
@@ -458,7 +462,7 @@
}
}
-status_t MP3Source::start(MetaData *) {
+status_t MP3Source::start(MetaDataBase *) {
CHECK(!mStarted);
mGroup = new MediaBufferGroup;
@@ -487,8 +491,9 @@
return OK;
}
-sp<MetaData> MP3Source::getFormat() {
- return mMeta;
+status_t MP3Source::getFormat(MetaDataBase &meta) {
+ meta = mMeta;
+ return OK;
}
status_t MP3Source::read(
@@ -504,7 +509,7 @@
if (mSeeker == NULL
|| !mSeeker->getOffsetForTime(&actualSeekTimeUs, &mCurrentPos)) {
int32_t bitrate;
- if (!mMeta->findInt32(kKeyBitRate, &bitrate)) {
+ if (!mMeta.findInt32(kKeyBitRate, &bitrate)) {
// bitrate is in bits/sec.
ALOGI("no bitrate");
@@ -587,8 +592,8 @@
buffer->set_range(0, frame_size);
- buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs);
- buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+ buffer->meta_data().setInt64(kKeyTime, mCurrentTimeUs);
+ buffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
mCurrentPos += frame_size;
@@ -600,19 +605,17 @@
return OK;
}
-sp<MetaData> MP3Extractor::getMetaData() {
- sp<MetaData> meta = new MetaData;
-
+status_t MP3Extractor::getMetaData(MetaDataBase &meta) {
+ meta.clear();
if (mInitCheck != OK) {
- return meta;
+ return UNKNOWN_ERROR;
}
-
- meta->setCString(kKeyMIMEType, "audio/mpeg");
+ meta.setCString(kKeyMIMEType, "audio/mpeg");
ID3 id3(mDataSource);
if (!id3.isValid()) {
- return meta;
+ return OK;
}
struct Map {
@@ -651,7 +654,7 @@
it->getString(&s);
delete it;
- meta->setCString(kMap[i].key, s);
+ meta.setCString(kMap[i].key, s);
}
size_t dataSize;
@@ -659,26 +662,20 @@
const void *data = id3.getAlbumArt(&dataSize, &mime);
if (data) {
- meta->setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize);
- meta->setCString(kKeyAlbumArtMIME, mime.string());
+ meta.setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize);
+ meta.setCString(kKeyAlbumArtMIME, mime.string());
}
- return meta;
+ return OK;
}
static MediaExtractor* CreateExtractor(
DataSourceBase *source,
void *meta) {
- sp<AMessage> metaData = static_cast<AMessage *>(meta);
+ Mp3Meta *metaData = static_cast<Mp3Meta *>(meta);
return new MP3Extractor(source, metaData);
}
-static void FreeMeta(void *meta) {
- if (meta != nullptr) {
- static_cast<AMessage *>(meta)->decStrong(nullptr);
- }
-}
-
static MediaExtractor::CreatorFunc Sniff(
DataSourceBase *source, float *confidence, void **meta,
MediaExtractor::FreeMetaFunc *freeMeta) {
@@ -698,14 +695,12 @@
return NULL;
}
- AMessage *msg = new AMessage;
- msg->setInt64("offset", pos);
- msg->setInt32("header", header);
- msg->setInt64("post-id3-offset", post_id3_pos);
- *meta = msg;
- *freeMeta = &FreeMeta;
- // ref count will be decreased in FreeMeta.
- msg->incStrong(nullptr);
+ Mp3Meta *mp3Meta = new Mp3Meta;
+ mp3Meta->pos = pos;
+ mp3Meta->header = header;
+ mp3Meta->post_id3_pos = post_id3_pos;
+ *meta = mp3Meta;
+ *freeMeta = ::free;
*confidence = 0.2f;
diff --git a/media/extractors/mp3/MP3Extractor.h b/media/extractors/mp3/MP3Extractor.h
index 6257112..485b0ca 100644
--- a/media/extractors/mp3/MP3Extractor.h
+++ b/media/extractors/mp3/MP3Extractor.h
@@ -20,6 +20,7 @@
#include <utils/Errors.h>
#include <media/MediaExtractor.h>
+#include <media/stagefright/MetaDataBase.h>
namespace android {
@@ -27,16 +28,18 @@
class DataSourceBase;
struct MP3Seeker;
class String8;
+struct Mp3Meta;
class MP3Extractor : public MediaExtractor {
public:
- MP3Extractor(DataSourceBase *source, const sp<AMessage> &meta);
+ MP3Extractor(DataSourceBase *source, Mp3Meta *meta);
+ ~MP3Extractor();
virtual size_t countTracks();
- virtual MediaSourceBase *getTrack(size_t index);
- virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+ virtual MediaTrack *getTrack(size_t index);
+ virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
- virtual sp<MetaData> getMetaData();
+ virtual status_t getMetaData(MetaDataBase& meta);
virtual const char * name() { return "MP3Extractor"; }
private:
@@ -44,18 +47,14 @@
DataSourceBase *mDataSource;
off64_t mFirstFramePos;
- sp<MetaData> mMeta;
+ MetaDataBase mMeta;
uint32_t mFixedHeader;
- sp<MP3Seeker> mSeeker;
+ MP3Seeker *mSeeker;
MP3Extractor(const MP3Extractor &);
MP3Extractor &operator=(const MP3Extractor &);
};
-bool SniffMP3(
- DataSourceBase *source, String8 *mimeType, float *confidence,
- sp<AMessage> *meta);
-
} // namespace android
#endif // MP3_EXTRACTOR_H_
diff --git a/media/extractors/mp3/MP3Seeker.h b/media/extractors/mp3/MP3Seeker.h
index 599542e..0e3af25 100644
--- a/media/extractors/mp3/MP3Seeker.h
+++ b/media/extractors/mp3/MP3Seeker.h
@@ -23,7 +23,7 @@
namespace android {
-struct MP3Seeker : public RefBase {
+struct MP3Seeker {
MP3Seeker() {}
virtual bool getDuration(int64_t *durationUs) = 0;
@@ -33,7 +33,6 @@
// the actual time that seekpoint represents.
virtual bool getOffsetForTime(int64_t *timeUs, off64_t *pos) = 0;
-protected:
virtual ~MP3Seeker() {}
private:
diff --git a/media/extractors/mp3/VBRISeeker.cpp b/media/extractors/mp3/VBRISeeker.cpp
index 51c5d1f..523f14c 100644
--- a/media/extractors/mp3/VBRISeeker.cpp
+++ b/media/extractors/mp3/VBRISeeker.cpp
@@ -36,7 +36,7 @@
}
// static
-sp<VBRISeeker> VBRISeeker::CreateFromSource(
+VBRISeeker *VBRISeeker::CreateFromSource(
DataSourceBase *source, off64_t post_id3_pos) {
off64_t pos = post_id3_pos;
@@ -87,7 +87,7 @@
return NULL;
}
- sp<VBRISeeker> seeker = new (std::nothrow) VBRISeeker;
+ VBRISeeker *seeker = new (std::nothrow) VBRISeeker;
if (seeker == NULL) {
ALOGW("Couldn't allocate VBRISeeker");
return NULL;
@@ -97,6 +97,7 @@
uint8_t *buffer = new (std::nothrow) uint8_t[totalEntrySize];
if (!buffer) {
ALOGW("Couldn't allocate %zu bytes", totalEntrySize);
+ delete seeker;
return NULL;
}
@@ -104,7 +105,7 @@
if (n < (ssize_t)totalEntrySize) {
delete[] buffer;
buffer = NULL;
-
+ delete seeker;
return NULL;
}
diff --git a/media/extractors/mp3/VBRISeeker.h b/media/extractors/mp3/VBRISeeker.h
index e46af36..9213f6e 100644
--- a/media/extractors/mp3/VBRISeeker.h
+++ b/media/extractors/mp3/VBRISeeker.h
@@ -27,7 +27,7 @@
class DataSourceBase;
struct VBRISeeker : public MP3Seeker {
- static sp<VBRISeeker> CreateFromSource(
+ static VBRISeeker *CreateFromSource(
DataSourceBase *source, off64_t post_id3_pos);
virtual bool getDuration(int64_t *durationUs);
diff --git a/media/extractors/mp3/XINGSeeker.cpp b/media/extractors/mp3/XINGSeeker.cpp
index adfa8d2..95ca556 100644
--- a/media/extractors/mp3/XINGSeeker.cpp
+++ b/media/extractors/mp3/XINGSeeker.cpp
@@ -76,11 +76,8 @@
}
// static
-sp<XINGSeeker> XINGSeeker::CreateFromSource(
+XINGSeeker *XINGSeeker::CreateFromSource(
DataSourceBase *source, off64_t first_frame_pos) {
- sp<XINGSeeker> seeker = new XINGSeeker;
-
- seeker->mFirstFramePos = first_frame_pos;
uint8_t buffer[4];
int offset = first_frame_pos;
@@ -98,8 +95,6 @@
NULL, &samples_per_frame)) {
return NULL;
}
- seeker->mFirstFramePos += xingframesize;
-
uint8_t version = (buffer[1] >> 3) & 3;
// determine offset of XING header
@@ -132,9 +127,13 @@
offset += 4;
uint32_t flags = U32_AT(buffer);
+ XINGSeeker *seeker = new XINGSeeker;
+ seeker->mFirstFramePos = first_frame_pos + xingframesize;
+
if (flags & 0x0001) { // Frames field is present
if (source->readAt(offset, buffer, 4) < 4) {
- return NULL;
+ delete seeker;
+ return NULL;
}
int32_t frames = U32_AT(buffer);
// only update mDurationUs if the calculated duration is valid (non zero)
@@ -148,6 +147,7 @@
}
if (flags & 0x0002) { // Bytes field is present
if (source->readAt(offset, buffer, 4) < 4) {
+ delete seeker;
return NULL;
}
seeker->mSizeBytes = U32_AT(buffer);
@@ -155,6 +155,7 @@
}
if (flags & 0x0004) { // TOC field is present
if (source->readAt(offset + 1, seeker->mTOC, 99) < 99) {
+ delete seeker;
return NULL;
}
seeker->mTOCValid = true;
@@ -164,6 +165,7 @@
#if 0
if (flags & 0x0008) { // Quality indicator field is present
if (source->readAt(offset, buffer, 4) < 4) {
+ delete seeker;
return NULL;
}
// do something with the quality indicator
@@ -171,6 +173,7 @@
}
if (source->readAt(xingbase + 0xaf - 0x24, &buffer, 1) < 1) { // encoding flags
+ delete seeker;
return false;
}
diff --git a/media/extractors/mp3/XINGSeeker.h b/media/extractors/mp3/XINGSeeker.h
index db847bc..5867eae 100644
--- a/media/extractors/mp3/XINGSeeker.h
+++ b/media/extractors/mp3/XINGSeeker.h
@@ -25,7 +25,7 @@
class DataSourceBase;
struct XINGSeeker : public MP3Seeker {
- static sp<XINGSeeker> CreateFromSource(
+ static XINGSeeker *CreateFromSource(
DataSourceBase *source, off64_t first_frame_pos);
virtual bool getDuration(int64_t *durationUs);
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 40c84a5..78d2ac6 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -31,7 +31,7 @@
#include "ItemTable.h"
#include "include/ESDS.h"
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
#include <media/stagefright/foundation/ABitReader.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -65,10 +65,10 @@
kMaxAtomSize = 64 * 1024 * 1024,
};
-class MPEG4Source : public MediaSourceBase {
+class MPEG4Source : public MediaTrack {
public:
// Caller retains ownership of both "dataSource" and "sampleTable".
- MPEG4Source(const sp<MetaData> &format,
+ MPEG4Source(MetaDataBase &format,
DataSourceBase *dataSource,
int32_t timeScale,
const sp<SampleTable> &sampleTable,
@@ -78,10 +78,10 @@
const sp<ItemTable> &itemTable);
virtual status_t init();
- virtual status_t start(MetaData *params = NULL);
+ virtual status_t start(MetaDataBase *params = NULL);
virtual status_t stop();
- virtual sp<MetaData> getFormat();
+ virtual status_t getFormat(MetaDataBase &);
virtual status_t read(MediaBufferBase **buffer, const ReadOptions *options = NULL);
virtual bool supportNonblockingRead() { return true; }
@@ -92,7 +92,7 @@
private:
Mutex mLock;
- sp<MetaData> mFormat;
+ MetaDataBase &mFormat;
DataSourceBase *mDataSource;
int32_t mTimescale;
sp<SampleTable> mSampleTable;
@@ -353,8 +353,7 @@
mHasMoovBox(false),
mPreferHeif(mime != NULL && !strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_HEIF)),
mFirstTrack(NULL),
- mLastTrack(NULL),
- mFileMetaData(new MetaData) {
+ mLastTrack(NULL) {
ALOGV("mime=%s, mPreferHeif=%d", mime, mPreferHeif);
}
@@ -382,13 +381,13 @@
(CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK) : 0);
}
-sp<MetaData> MPEG4Extractor::getMetaData() {
+status_t MPEG4Extractor::getMetaData(MetaDataBase &meta) {
status_t err;
if ((err = readMetaData()) != OK) {
- return new MetaData;
+ return UNKNOWN_ERROR;
}
-
- return mFileMetaData;
+ meta = mFileMetaData;
+ return OK;
}
size_t MPEG4Extractor::countTracks() {
@@ -409,17 +408,18 @@
return n;
}
-sp<MetaData> MPEG4Extractor::getTrackMetaData(
+status_t MPEG4Extractor::getTrackMetaData(
+ MetaDataBase &meta,
size_t index, uint32_t flags) {
status_t err;
if ((err = readMetaData()) != OK) {
- return NULL;
+ return UNKNOWN_ERROR;
}
Track *track = mFirstTrack;
while (index > 0) {
if (track == NULL) {
- return NULL;
+ return UNKNOWN_ERROR;
}
track = track->next;
@@ -427,15 +427,15 @@
}
if (track == NULL) {
- return NULL;
+ return UNKNOWN_ERROR;
}
[=] {
int64_t duration;
int32_t samplerate;
if (track->has_elst && mHeaderTimescale != 0 &&
- track->meta->findInt64(kKeyDuration, &duration) &&
- track->meta->findInt32(kKeySampleRate, &samplerate)) {
+ track->meta.findInt64(kKeyDuration, &duration) &&
+ track->meta.findInt32(kKeySampleRate, &samplerate)) {
track->has_elst = false;
@@ -462,7 +462,7 @@
return;
}
ALOGV("delay = %" PRId64, delay);
- track->meta->setInt32(kKeyEncoderDelay, delay);
+ track->meta.setInt32(kKeyEncoderDelay, delay);
int64_t scaled_duration;
// scaled_duration = duration * mHeaderTimescale;
@@ -502,7 +502,7 @@
return;
}
ALOGV("paddingsamples = %" PRId64, paddingsamples);
- track->meta->setInt32(kKeyEncoderPadding, paddingsamples);
+ track->meta.setInt32(kKeyEncoderPadding, paddingsamples);
}
}();
@@ -511,7 +511,7 @@
track->includes_expensive_metadata = true;
const char *mime;
- CHECK(track->meta->findCString(kKeyMIMEType, &mime));
+ CHECK(track->meta.findCString(kKeyMIMEType, &mime));
if (!strncasecmp("video/", mime, 6)) {
// MPEG2 tracks do not provide CSD, so read the stream header
if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG2)) {
@@ -524,16 +524,16 @@
}
uint8_t header[kMaxTrackHeaderSize];
if (mDataSource->readAt(offset, &header, size) == (ssize_t)size) {
- track->meta->setData(kKeyStreamHeader, 'mdat', header, size);
+ track->meta.setData(kKeyStreamHeader, 'mdat', header, size);
}
}
}
if (mMoofOffset > 0) {
int64_t duration;
- if (track->meta->findInt64(kKeyDuration, &duration)) {
+ if (track->meta.findInt64(kKeyDuration, &duration)) {
// nothing fancy, just pick a frame near 1/4th of the duration
- track->meta->setInt64(
+ track->meta.setInt64(
kKeyThumbnailTime, duration / 4);
}
} else {
@@ -544,7 +544,7 @@
&& track->sampleTable->getMetaDataForSample(
sampleIndex, NULL /* offset */, NULL /* size */,
&sampleTime) == OK) {
- track->meta->setInt64(
+ track->meta.setInt64(
kKeyThumbnailTime,
((int64_t)sampleTime * 1000000) / track->timescale);
}
@@ -552,7 +552,8 @@
}
}
- return track->meta;
+ meta = track->meta;
+ return OK;
}
status_t MPEG4Extractor::readMetaData() {
@@ -610,8 +611,8 @@
}
mLastTrack = track;
- track->meta = meta;
- track->meta->setInt32(kKeyTrackID, imageIndex);
+ track->meta = *(meta.get());
+ track->meta.setInt32(kKeyTrackID, imageIndex);
track->includes_expensive_metadata = false;
track->skipTrack = false;
track->timescale = 0;
@@ -620,16 +621,16 @@
if (mInitCheck == OK) {
if (findTrackByMimePrefix("video/") != NULL) {
- mFileMetaData->setCString(
+ mFileMetaData.setCString(
kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG4);
} else if (findTrackByMimePrefix("audio/") != NULL) {
- mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
+ mFileMetaData.setCString(kKeyMIMEType, "audio/mp4");
} else if (findTrackByMimePrefix(
MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC) != NULL) {
- mFileMetaData->setCString(
+ mFileMetaData.setCString(
kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_HEIF);
} else {
- mFileMetaData->setCString(kKeyMIMEType, "application/octet-stream");
+ mFileMetaData.setCString(kKeyMIMEType, "application/octet-stream");
}
} else {
mInitCheck = err;
@@ -654,7 +655,7 @@
memcpy(ptr + 20, mPssh[i].data, mPssh[i].datalen);
ptr += (20 + mPssh[i].datalen);
}
- mFileMetaData->setData(kKeyPssh, 'pssh', buf, psshsize);
+ mFileMetaData.setData(kKeyPssh, 'pssh', buf, psshsize);
free(buf);
}
@@ -902,11 +903,10 @@
}
mLastTrack = track;
- track->meta = new MetaData;
track->includes_expensive_metadata = false;
track->skipTrack = false;
track->timescale = 0;
- track->meta->setCString(kKeyMIMEType, "application/octet-stream");
+ track->meta.setCString(kKeyMIMEType, "application/octet-stream");
track->has_elst = false;
}
@@ -930,7 +930,7 @@
if (isTrack) {
int32_t trackId;
// There must be exact one track header per track.
- if (!mLastTrack->meta->findInt32(kKeyTrackID, &trackId)) {
+ if (!mLastTrack->meta.findInt32(kKeyTrackID, &trackId)) {
mLastTrack->skipTrack = true;
}
@@ -1037,12 +1037,12 @@
return ERROR_MALFORMED;
}
- mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
+ mLastTrack->meta.setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
uint32_t num_channels = 0;
uint32_t sample_rate = 0;
if (AdjustChannelsAndRate(original_fourcc, &num_channels, &sample_rate)) {
- mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
- mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
+ mLastTrack->meta.setInt32(kKeyChannelCount, num_channels);
+ mLastTrack->meta.setInt32(kKeySampleRate, sample_rate);
}
break;
}
@@ -1095,9 +1095,9 @@
if (mLastTrack == NULL)
return ERROR_MALFORMED;
- mLastTrack->meta->setInt32(kKeyCryptoMode, defaultAlgorithmId);
- mLastTrack->meta->setInt32(kKeyCryptoDefaultIVSize, defaultIVSize);
- mLastTrack->meta->setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16);
+ mLastTrack->meta.setInt32(kKeyCryptoMode, defaultAlgorithmId);
+ mLastTrack->meta.setInt32(kKeyCryptoDefaultIVSize, defaultIVSize);
+ mLastTrack->meta.setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16);
break;
}
@@ -1231,7 +1231,7 @@
}
}
if (duration != 0 && mLastTrack->timescale != 0) {
- mLastTrack->meta->setInt64(
+ mLastTrack->meta.setInt64(
kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
}
@@ -1259,7 +1259,7 @@
lang_code[2] = (lang[1] & 0x1f) + 0x60;
lang_code[3] = '\0';
- mLastTrack->meta->setCString(
+ mLastTrack->meta.setCString(
kKeyMediaLanguage, lang_code);
break;
@@ -1294,7 +1294,7 @@
if (mLastTrack == NULL)
return ERROR_MALFORMED;
- CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
+ CHECK(mLastTrack->meta.findCString(kKeyMIMEType, &mime));
if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) &&
strcasecmp(mime, "application/octet-stream")) {
// For now we only support a single type of media per track.
@@ -1335,7 +1335,7 @@
}
String8 mimeFormat((const char *)(buffer->data()), chunk_data_size);
- mLastTrack->meta->setCString(kKeyMIMEType, mimeFormat.string());
+ mLastTrack->meta.setCString(kKeyMIMEType, mimeFormat.string());
break;
}
@@ -1411,13 +1411,13 @@
if (chunk_type != FOURCC('e', 'n', 'c', 'a')) {
// if the chunk type is enca, we'll get the type from the frma box later
- mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
+ mLastTrack->meta.setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate);
}
ALOGV("*** coding='%s' %d channels, size %d, rate %d\n",
chunk, num_channels, sample_size, sample_rate);
- mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
- mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
+ mLastTrack->meta.setInt32(kKeyChannelCount, num_channels);
+ mLastTrack->meta.setInt32(kKeySampleRate, sample_rate);
while (*offset < stop_offset) {
status_t err = parseChunk(offset, depth + 1);
@@ -1471,10 +1471,10 @@
if (chunk_type != FOURCC('e', 'n', 'c', 'v')) {
// if the chunk type is encv, we'll get the type from the frma box later
- mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
+ mLastTrack->meta.setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
}
- mLastTrack->meta->setInt32(kKeyWidth, width);
- mLastTrack->meta->setInt32(kKeyHeight, height);
+ mLastTrack->meta.setInt32(kKeyWidth, width);
+ mLastTrack->meta.setInt32(kKeyHeight, height);
off64_t stop_offset = *offset + chunk_size;
*offset = data_offset + sizeof(buffer);
@@ -1562,12 +1562,12 @@
ALOGE("max sample size too big: %zu", max_size);
return ERROR_MALFORMED;
}
- mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
+ mLastTrack->meta.setInt32(kKeyMaxInputSize, max_size + 10 * 2);
} else {
// No size was specified. Pick a conservatively large size.
uint32_t width, height;
- if (!mLastTrack->meta->findInt32(kKeyWidth, (int32_t*)&width) ||
- !mLastTrack->meta->findInt32(kKeyHeight,(int32_t*) &height)) {
+ if (!mLastTrack->meta.findInt32(kKeyWidth, (int32_t*)&width) ||
+ !mLastTrack->meta.findInt32(kKeyHeight,(int32_t*) &height)) {
ALOGE("No width or height, assuming worst case 1080p");
width = 1920;
height = 1080;
@@ -1582,7 +1582,7 @@
}
const char *mime;
- CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
+ CHECK(mLastTrack->meta.findCString(kKeyMIMEType, &mime));
if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)
|| !strcmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
// AVC & HEVC requires compression ratio of at least 2, and uses
@@ -1596,26 +1596,26 @@
// HACK: allow 10% overhead
// TODO: read sample size from traf atom for fragmented MPEG4.
max_size += max_size / 10;
- mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size);
+ mLastTrack->meta.setInt32(kKeyMaxInputSize, max_size);
}
// NOTE: setting another piece of metadata invalidates any pointers (such as the
// mimetype) previously obtained, so don't cache them.
const char *mime;
- CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
+ CHECK(mLastTrack->meta.findCString(kKeyMIMEType, &mime));
// Calculate average frame rate.
if (!strncasecmp("video/", mime, 6)) {
size_t nSamples = mLastTrack->sampleTable->countSamples();
if (nSamples == 0) {
int32_t trackId;
- if (mLastTrack->meta->findInt32(kKeyTrackID, &trackId)) {
+ if (mLastTrack->meta.findInt32(kKeyTrackID, &trackId)) {
for (size_t i = 0; i < mTrex.size(); i++) {
Trex *t = &mTrex.editItemAt(i);
if (t->track_ID == (uint32_t) trackId) {
if (t->default_sample_duration > 0) {
int32_t frameRate =
mLastTrack->timescale / t->default_sample_duration;
- mLastTrack->meta->setInt32(kKeyFrameRate, frameRate);
+ mLastTrack->meta.setInt32(kKeyFrameRate, frameRate);
}
break;
}
@@ -1623,15 +1623,15 @@
}
} else {
int64_t durationUs;
- if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) {
+ if (mLastTrack->meta.findInt64(kKeyDuration, &durationUs)) {
if (durationUs > 0) {
int32_t frameRate = (nSamples * 1000000LL +
(durationUs >> 1)) / durationUs;
- mLastTrack->meta->setInt32(kKeyFrameRate, frameRate);
+ mLastTrack->meta.setInt32(kKeyFrameRate, frameRate);
}
}
ALOGV("setting frame count %zu", nSamples);
- mLastTrack->meta->setInt32(kKeyFrameCount, nSamples);
+ mLastTrack->meta.setInt32(kKeyFrameCount, nSamples);
}
}
@@ -1739,7 +1739,7 @@
if (buffer[len - 1] != '/') {
buffer[len] = '/';
}
- mFileMetaData->setCString(kKeyLocation, &buffer[0]);
+ mFileMetaData.setCString(kKeyLocation, &buffer[0]);
break;
}
@@ -1769,7 +1769,7 @@
if (mLastTrack == NULL)
return ERROR_MALFORMED;
- mLastTrack->meta->setData(
+ mLastTrack->meta.setData(
kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
if (mPath.size() >= 2
@@ -1794,7 +1794,7 @@
uint8_t objectTypeIndication;
if (esds.getObjectTypeIndication(&objectTypeIndication) == OK) {
if (objectTypeIndication >= 0x60 && objectTypeIndication <= 0x65) {
- mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG2);
+ mLastTrack->meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG2);
}
}
}
@@ -1821,10 +1821,10 @@
uint32_t maxBitrate = U32_AT(&buffer[4]);
uint32_t avgBitrate = U32_AT(&buffer[8]);
if (maxBitrate > 0 && maxBitrate < INT32_MAX) {
- mLastTrack->meta->setInt32(kKeyMaxBitRate, (int32_t)maxBitrate);
+ mLastTrack->meta.setInt32(kKeyMaxBitRate, (int32_t)maxBitrate);
}
if (avgBitrate > 0 && avgBitrate < INT32_MAX) {
- mLastTrack->meta->setInt32(kKeyBitRate, (int32_t)avgBitrate);
+ mLastTrack->meta.setInt32(kKeyBitRate, (int32_t)avgBitrate);
}
break;
}
@@ -1848,7 +1848,7 @@
if (mLastTrack == NULL)
return ERROR_MALFORMED;
- mLastTrack->meta->setData(
+ mLastTrack->meta.setData(
kKeyAVCC, kTypeAVCC, buffer->data(), chunk_data_size);
break;
@@ -1870,7 +1870,7 @@
if (mLastTrack == NULL)
return ERROR_MALFORMED;
- mLastTrack->meta->setData(
+ mLastTrack->meta.setData(
kKeyHVCC, kTypeHVCC, buffer->data(), chunk_data_size);
*offset += chunk_size;
@@ -1906,7 +1906,7 @@
if (mLastTrack == NULL)
return ERROR_MALFORMED;
- mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
+ mLastTrack->meta.setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
break;
}
@@ -2034,12 +2034,12 @@
duration = d32;
}
if (duration != 0 && mHeaderTimescale != 0 && duration < UINT64_MAX / 1000000) {
- mFileMetaData->setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale);
+ mFileMetaData.setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale);
}
String8 s;
if (convertTimeToDate(creationTime, &s)) {
- mFileMetaData->setCString(kKeyDate, s.string());
+ mFileMetaData.setCString(kKeyDate, s.string());
}
@@ -2084,7 +2084,7 @@
}
if (duration != 0 && mHeaderTimescale != 0) {
- mFileMetaData->setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale);
+ mFileMetaData.setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale);
}
break;
@@ -2118,7 +2118,7 @@
// for a practical reason as various MPEG4 containers use it.
if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) {
if (mLastTrack != NULL) {
- mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
+ mLastTrack->meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
}
}
@@ -2165,7 +2165,7 @@
uint32_t type;
const void *data;
size_t size = 0;
- if (!mLastTrack->meta->findData(
+ if (!mLastTrack->meta.findData(
kKeyTextFormatData, &type, &data, &size)) {
size = 0;
}
@@ -2193,7 +2193,7 @@
return ERROR_IO;
}
- mLastTrack->meta->setData(
+ mLastTrack->meta.setData(
kKeyTextFormatData, 0, buffer, size + chunk_size);
delete[] buffer;
@@ -2206,31 +2206,29 @@
{
*offset += chunk_size;
- if (mFileMetaData != NULL) {
- ALOGV("chunk_data_size = %" PRId64 " and data_offset = %" PRId64,
- chunk_data_size, data_offset);
+ ALOGV("chunk_data_size = %" PRId64 " and data_offset = %" PRId64,
+ chunk_data_size, data_offset);
- if (chunk_data_size < 0 || static_cast<uint64_t>(chunk_data_size) >= SIZE_MAX - 1) {
- return ERROR_MALFORMED;
- }
- sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1);
- if (buffer->data() == NULL) {
- ALOGE("b/28471206");
- return NO_MEMORY;
- }
- if (mDataSource->readAt(
- data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) {
- return ERROR_IO;
- }
- const int kSkipBytesOfDataBox = 16;
- if (chunk_data_size <= kSkipBytesOfDataBox) {
- return ERROR_MALFORMED;
- }
-
- mFileMetaData->setData(
- kKeyAlbumArt, MetaData::TYPE_NONE,
- buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
+ if (chunk_data_size < 0 || static_cast<uint64_t>(chunk_data_size) >= SIZE_MAX - 1) {
+ return ERROR_MALFORMED;
}
+ sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1);
+ if (buffer->data() == NULL) {
+ ALOGE("b/28471206");
+ return NO_MEMORY;
+ }
+ if (mDataSource->readAt(
+ data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) {
+ return ERROR_IO;
+ }
+ const int kSkipBytesOfDataBox = 16;
+ if (chunk_data_size <= kSkipBytesOfDataBox) {
+ return ERROR_MALFORMED;
+ }
+
+ mFileMetaData.setData(
+ kKeyAlbumArt, MetaData::TYPE_NONE,
+ buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
break;
}
@@ -2462,9 +2460,9 @@
if (mLastTrack == NULL) {
return ERROR_MALFORMED;
}
- mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AC3);
- mLastTrack->meta->setInt32(kKeyChannelCount, channelCount);
- mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
+ mLastTrack->meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AC3);
+ mLastTrack->meta.setInt32(kKeyChannelCount, channelCount);
+ mLastTrack->meta.setInt32(kKeySampleRate, sampleRate);
return OK;
}
@@ -2584,8 +2582,8 @@
return ERROR_MALFORMED;
int64_t metaDuration;
- if (!mLastTrack->meta->findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) {
- mLastTrack->meta->setInt64(kKeyDuration, sidxDuration);
+ if (!mLastTrack->meta.findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) {
+ mLastTrack->meta.setInt64(kKeyDuration, sidxDuration);
}
return OK;
}
@@ -2683,7 +2681,7 @@
return ERROR_MALFORMED;
}
if (!strcasecmp(mMetaKeyMap[index].c_str(), "com.android.capture.fps")) {
- mFileMetaData->setFloat(kKeyCaptureFramerate, *(float *)&val);
+ mFileMetaData.setFloat(kKeyCaptureFramerate, *(float *)&val);
}
} else if (dataType == 67 && dataSize >= 4) {
// BE signed int32
@@ -2692,7 +2690,7 @@
return ERROR_MALFORMED;
}
if (!strcasecmp(mMetaKeyMap[index].c_str(), "com.android.video.temporal_layers_count")) {
- mFileMetaData->setInt32(kKeyTemporalLayerCount, val);
+ mFileMetaData.setInt32(kKeyTemporalLayerCount, val);
}
} else {
// add more keys if needed
@@ -2746,7 +2744,7 @@
if (mLastTrack == NULL)
return ERROR_MALFORMED;
- mLastTrack->meta->setInt32(kKeyTrackID, id);
+ mLastTrack->meta.setInt32(kKeyTrackID, id);
size_t matrixOffset = dynSize + 16;
int32_t a00 = U32_AT(&buffer[matrixOffset]);
@@ -2782,15 +2780,15 @@
}
if (rotationDegrees != 0) {
- mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees);
+ mLastTrack->meta.setInt32(kKeyRotation, rotationDegrees);
}
// Handle presentation display size, which could be different
// from the image size indicated by kKeyWidth and kKeyHeight.
uint32_t width = U32_AT(&buffer[dynSize + 52]);
uint32_t height = U32_AT(&buffer[dynSize + 56]);
- mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16);
- mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16);
+ mLastTrack->meta.setInt32(kKeyDisplayWidth, width >> 16);
+ mLastTrack->meta.setInt32(kKeyDisplayHeight, height >> 16);
return OK;
}
@@ -2875,7 +2873,7 @@
sprintf(tmp, "%d",
(int)buffer[size - 1]);
- mFileMetaData->setCString(kKeyCompilation, tmp);
+ mFileMetaData.setCString(kKeyCompilation, tmp);
}
break;
}
@@ -2887,7 +2885,7 @@
uint16_t* pTotalTracks = (uint16_t*)&buffer[12];
sprintf(tmp, "%d/%d", ntohs(*pTrack), ntohs(*pTotalTracks));
- mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
+ mFileMetaData.setCString(kKeyCDTrackNumber, tmp);
}
break;
}
@@ -2899,7 +2897,7 @@
uint16_t* pTotalDiscs = (uint16_t*)&buffer[12];
sprintf(tmp, "%d/%d", ntohs(*pDisc), ntohs(*pTotalDiscs));
- mFileMetaData->setCString(kKeyDiscNumber, tmp);
+ mFileMetaData.setCString(kKeyDiscNumber, tmp);
}
break;
}
@@ -2943,8 +2941,8 @@
return ERROR_MALFORMED;
}
- mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
- mLastTrack->meta->setInt32(kKeyEncoderPadding, padding);
+ mLastTrack->meta.setInt32(kKeyEncoderDelay, delay);
+ mLastTrack->meta.setInt32(kKeyEncoderPadding, padding);
}
}
@@ -2959,9 +2957,9 @@
break;
}
- if (size >= 8 && metadataKey && !mFileMetaData->hasData(metadataKey)) {
+ if (size >= 8 && metadataKey && !mFileMetaData.hasData(metadataKey)) {
if (metadataKey == kKeyAlbumArt) {
- mFileMetaData->setData(
+ mFileMetaData.setData(
kKeyAlbumArt, MetaData::TYPE_NONE,
buffer + 8, size - 8);
} else if (metadataKey == kKeyGenre) {
@@ -2978,18 +2976,18 @@
char genre[10];
sprintf(genre, "%d", genrecode);
- mFileMetaData->setCString(metadataKey, genre);
+ mFileMetaData.setCString(metadataKey, genre);
} else if (flags == 1) {
// custom genre string
buffer[size] = '\0';
- mFileMetaData->setCString(
+ mFileMetaData.setCString(
metadataKey, (const char *)buffer + 8);
}
} else {
buffer[size] = '\0';
- mFileMetaData->setCString(
+ mFileMetaData.setCString(
metadataKey, (const char *)buffer + 8);
}
}
@@ -3029,11 +3027,11 @@
primaries, transfer, coeffs, fullRange, aspects);
// only store the first color specification
- if (!mLastTrack->meta->hasData(kKeyColorPrimaries)) {
- mLastTrack->meta->setInt32(kKeyColorPrimaries, aspects.mPrimaries);
- mLastTrack->meta->setInt32(kKeyTransferFunction, aspects.mTransfer);
- mLastTrack->meta->setInt32(kKeyColorMatrix, aspects.mMatrixCoeffs);
- mLastTrack->meta->setInt32(kKeyColorRange, aspects.mRange);
+ if (!mLastTrack->meta.hasData(kKeyColorPrimaries)) {
+ mLastTrack->meta.setInt32(kKeyColorPrimaries, aspects.mPrimaries);
+ mLastTrack->meta.setInt32(kKeyTransferFunction, aspects.mTransfer);
+ mLastTrack->meta.setInt32(kKeyColorMatrix, aspects.mMatrixCoeffs);
+ mLastTrack->meta.setInt32(kKeyColorRange, aspects.mRange);
}
}
@@ -3088,7 +3086,7 @@
char tmp[4];
sprintf(tmp, "%u", buffer[size - 1]);
- mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
+ mFileMetaData.setCString(kKeyCDTrackNumber, tmp);
}
metadataKey = kKeyAlbum;
@@ -3109,7 +3107,7 @@
if (year < 10000) {
sprintf(tmp, "%u", year);
- mFileMetaData->setCString(kKeyYear, tmp);
+ mFileMetaData.setCString(kKeyYear, tmp);
}
break;
}
@@ -3154,11 +3152,11 @@
if (isUTF8) {
buffer[size] = 0;
- mFileMetaData->setCString(metadataKey, (const char *)buffer + 6);
+ mFileMetaData.setCString(metadataKey, (const char *)buffer + 6);
} else {
// Convert from UTF-16 string to UTF-8 string.
String8 tmpUTF8str(framedata, len16);
- mFileMetaData->setCString(metadataKey, tmpUTF8str.string());
+ mFileMetaData.setCString(metadataKey, tmpUTF8str.string());
}
}
@@ -3193,7 +3191,7 @@
static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
for (size_t i = 0; i < kNumMapEntries; ++i) {
- if (!mFileMetaData->hasData(kMap[i].key)) {
+ if (!mFileMetaData.hasData(kMap[i].key)) {
ID3::Iterator *it = new ID3::Iterator(id3, kMap[i].tag1);
if (it->done()) {
delete it;
@@ -3209,7 +3207,7 @@
it->getString(&s);
delete it;
- mFileMetaData->setCString(kMap[i].key, s);
+ mFileMetaData.setCString(kMap[i].key, s);
}
}
@@ -3218,13 +3216,13 @@
const void *data = id3.getAlbumArt(&dataSize, &mime);
if (data) {
- mFileMetaData->setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize);
- mFileMetaData->setCString(kKeyAlbumArtMIME, mime.string());
+ mFileMetaData.setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize);
+ mFileMetaData.setCString(kKeyAlbumArtMIME, mime.string());
}
}
}
-MediaSourceBase *MPEG4Extractor::getTrack(size_t index) {
+MediaTrack *MPEG4Extractor::getTrack(size_t index) {
status_t err;
if ((err = readMetaData()) != OK) {
return NULL;
@@ -3247,7 +3245,7 @@
Trex *trex = NULL;
int32_t trackId;
- if (track->meta->findInt32(kKeyTrackID, &trackId)) {
+ if (track->meta.findInt32(kKeyTrackID, &trackId)) {
for (size_t i = 0; i < mTrex.size(); i++) {
Trex *t = &mTrex.editItemAt(i);
if (t->track_ID == (uint32_t) trackId) {
@@ -3263,7 +3261,7 @@
ALOGV("getTrack called, pssh: %zu", mPssh.size());
const char *mime;
- if (!track->meta->findCString(kKeyMIMEType, &mime)) {
+ if (!track->meta.findCString(kKeyMIMEType, &mime)) {
return NULL;
}
@@ -3272,7 +3270,7 @@
uint32_t type;
const void *data;
size_t size;
- if (!track->meta->findData(kKeyAVCC, &type, &data, &size)) {
+ if (!track->meta.findData(kKeyAVCC, &type, &data, &size)) {
return NULL;
}
@@ -3286,7 +3284,7 @@
uint32_t type;
const void *data;
size_t size;
- if (!track->meta->findData(kKeyHVCC, &type, &data, &size)) {
+ if (!track->meta.findData(kKeyHVCC, &type, &data, &size)) {
return NULL;
}
@@ -3313,25 +3311,25 @@
// static
status_t MPEG4Extractor::verifyTrack(Track *track) {
const char *mime;
- CHECK(track->meta->findCString(kKeyMIMEType, &mime));
+ CHECK(track->meta.findCString(kKeyMIMEType, &mime));
uint32_t type;
const void *data;
size_t size;
if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
- if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
+ if (!track->meta.findData(kKeyAVCC, &type, &data, &size)
|| type != kTypeAVCC) {
return ERROR_MALFORMED;
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
- if (!track->meta->findData(kKeyHVCC, &type, &data, &size)
+ if (!track->meta.findData(kKeyHVCC, &type, &data, &size)
|| type != kTypeHVCC) {
return ERROR_MALFORMED;
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
|| !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG2)
|| !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
- if (!track->meta->findData(kKeyESDS, &type, &data, &size)
+ if (!track->meta.findData(kKeyESDS, &type, &data, &size)
|| type != kTypeESDS) {
return ERROR_MALFORMED;
}
@@ -3417,7 +3415,7 @@
if (mLastTrack == NULL)
return ERROR_MALFORMED;
- mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
+ mLastTrack->meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
return OK;
}
@@ -3434,10 +3432,10 @@
uint32_t avgBitrate = 0;
esds.getBitRate(&maxBitrate, &avgBitrate);
if (maxBitrate > 0 && maxBitrate < INT32_MAX) {
- mLastTrack->meta->setInt32(kKeyMaxBitRate, (int32_t)maxBitrate);
+ mLastTrack->meta.setInt32(kKeyMaxBitRate, (int32_t)maxBitrate);
}
if (avgBitrate > 0 && avgBitrate < INT32_MAX) {
- mLastTrack->meta->setInt32(kKeyBitRate, (int32_t)avgBitrate);
+ mLastTrack->meta.setInt32(kKeyBitRate, (int32_t)avgBitrate);
}
}
@@ -3481,7 +3479,7 @@
return ERROR_MALFORMED;
//keep AOT type
- mLastTrack->meta->setInt32(kKeyAACAOT, objectType);
+ mLastTrack->meta.setInt32(kKeyAACAOT, objectType);
uint32_t freqIndex = br.getBits(4);
@@ -3519,7 +3517,7 @@
extSampleRate = kSamplingRate[extFreqIndex];
}
//TODO: save the extension sampling rate value in meta data =>
- // mLastTrack->meta->setInt32(kKeyExtSampleRate, extSampleRate);
+ // mLastTrack->meta.setInt32(kKeyExtSampleRate, extSampleRate);
}
switch (numChannels) {
@@ -3672,24 +3670,24 @@
return ERROR_MALFORMED;
int32_t prevSampleRate;
- CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
+ CHECK(mLastTrack->meta.findInt32(kKeySampleRate, &prevSampleRate));
if (prevSampleRate != sampleRate) {
ALOGV("mpeg4 audio sample rate different from previous setting. "
"was: %d, now: %d", prevSampleRate, sampleRate);
}
- mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
+ mLastTrack->meta.setInt32(kKeySampleRate, sampleRate);
int32_t prevChannelCount;
- CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
+ CHECK(mLastTrack->meta.findInt32(kKeyChannelCount, &prevChannelCount));
if (prevChannelCount != numChannels) {
ALOGV("mpeg4 audio channel count different from previous setting. "
"was: %d, now: %d", prevChannelCount, numChannels);
}
- mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
+ mLastTrack->meta.setInt32(kKeyChannelCount, numChannels);
return OK;
}
@@ -3697,7 +3695,7 @@
////////////////////////////////////////////////////////////////////////////////
MPEG4Source::MPEG4Source(
- const sp<MetaData> &format,
+ MetaDataBase &format,
DataSourceBase *dataSource,
int32_t timeScale,
const sp<SampleTable> &sampleTable,
@@ -3734,20 +3732,20 @@
memset(&mTrackFragmentHeaderInfo, 0, sizeof(mTrackFragmentHeaderInfo));
- mFormat->findInt32(kKeyCryptoMode, &mCryptoMode);
+ mFormat.findInt32(kKeyCryptoMode, &mCryptoMode);
mDefaultIVSize = 0;
- mFormat->findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize);
+ mFormat.findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize);
uint32_t keytype;
const void *key;
size_t keysize;
- if (mFormat->findData(kKeyCryptoKey, &keytype, &key, &keysize)) {
+ if (mFormat.findData(kKeyCryptoKey, &keytype, &key, &keysize)) {
CHECK(keysize <= 16);
memset(mCryptoKey, 0, 16);
memcpy(mCryptoKey, key, keysize);
}
const char *mime;
- bool success = mFormat->findCString(kKeyMIMEType, &mime);
+ bool success = mFormat.findCString(kKeyMIMEType, &mime);
CHECK(success);
mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
@@ -3758,7 +3756,7 @@
uint32_t type;
const void *data;
size_t size;
- CHECK(format->findData(kKeyAVCC, &type, &data, &size));
+ CHECK(format.findData(kKeyAVCC, &type, &data, &size));
const uint8_t *ptr = (const uint8_t *)data;
@@ -3771,7 +3769,7 @@
uint32_t type;
const void *data;
size_t size;
- CHECK(format->findData(kKeyHVCC, &type, &data, &size));
+ CHECK(format.findData(kKeyHVCC, &type, &data, &size));
const uint8_t *ptr = (const uint8_t *)data;
@@ -3781,7 +3779,7 @@
mNALLengthSize = 1 + (ptr[14 + 7] & 3);
}
- CHECK(format->findInt32(kKeyTrackID, &mTrackId));
+ CHECK(format.findInt32(kKeyTrackID, &mTrackId));
}
@@ -3801,7 +3799,7 @@
free(mCurrentSampleInfoOffsets);
}
-status_t MPEG4Source::start(MetaData *params) {
+status_t MPEG4Source::start(MetaDataBase *params) {
Mutex::Autolock autoLock(mLock);
CHECK(!mStarted);
@@ -3815,7 +3813,7 @@
}
int32_t tmp;
- CHECK(mFormat->findInt32(kKeyMaxInputSize, &tmp));
+ CHECK(mFormat.findInt32(kKeyMaxInputSize, &tmp));
size_t max_size = tmp;
// A somewhat arbitrary limit that should be sufficient for 8k video frames
@@ -4142,7 +4140,7 @@
drmoffset += mCurrentMoofOffset;
int ivlength;
- CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength));
+ CHECK(mFormat.findInt32(kKeyCryptoDefaultIVSize, &ivlength));
// only 0, 8 and 16 byte initialization vectors are supported
if (ivlength != 0 && ivlength != 8 && ivlength != 16) {
@@ -4459,10 +4457,10 @@
return OK;
}
-sp<MetaData> MPEG4Source::getFormat() {
+status_t MPEG4Source::getFormat(MetaDataBase &meta) {
Mutex::Autolock autoLock(mLock);
-
- return mFormat;
+ meta = mFormat;
+ return OK;
}
size_t MPEG4Source::parseNALSize(const uint8_t *data) const {
@@ -4510,7 +4508,7 @@
CHECK(mSampleTable == NULL);
CHECK(mItemTable != NULL);
int32_t imageIndex;
- if (!mFormat->findInt32(kKeyTrackID, &imageIndex)) {
+ if (!mFormat.findInt32(kKeyTrackID, &imageIndex)) {
return ERROR_MALFORMED;
}
@@ -4664,19 +4662,19 @@
CHECK(mBuffer != NULL);
mBuffer->set_range(0, size);
- mBuffer->meta_data()->clear();
- mBuffer->meta_data()->setInt64(
+ mBuffer->meta_data().clear();
+ mBuffer->meta_data().setInt64(
kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
- mBuffer->meta_data()->setInt64(
+ mBuffer->meta_data().setInt64(
kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
if (targetSampleTimeUs >= 0) {
- mBuffer->meta_data()->setInt64(
+ mBuffer->meta_data().setInt64(
kKeyTargetTime, targetSampleTimeUs);
}
if (isSyncSample) {
- mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+ mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
}
++mCurrentSampleIndex;
@@ -4732,7 +4730,7 @@
// the start code (0x00 00 00 01).
ssize_t num_bytes_read = 0;
int32_t drm = 0;
- bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
+ bool usesDRM = (mFormat.findInt32(kKeyIsDRM, &drm) && drm != 0);
if (usesDRM) {
num_bytes_read =
mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
@@ -4799,25 +4797,25 @@
mBuffer->set_range(0, dstOffset);
}
- mBuffer->meta_data()->clear();
- mBuffer->meta_data()->setInt64(
+ mBuffer->meta_data().clear();
+ mBuffer->meta_data().setInt64(
kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
- mBuffer->meta_data()->setInt64(
+ mBuffer->meta_data().setInt64(
kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
if (targetSampleTimeUs >= 0) {
- mBuffer->meta_data()->setInt64(
+ mBuffer->meta_data().setInt64(
kKeyTargetTime, targetSampleTimeUs);
}
if (mIsAVC) {
uint32_t layerId = FindAVCLayerId(
(const uint8_t *)mBuffer->data(), mBuffer->range_length());
- mBuffer->meta_data()->setInt32(kKeyTemporalLayerId, layerId);
+ mBuffer->meta_data().setInt32(kKeyTemporalLayerId, layerId);
}
if (isSyncSample) {
- mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+ mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
}
++mCurrentSampleIndex;
@@ -4945,18 +4943,18 @@
}
const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
- const sp<MetaData> bufmeta = mBuffer->meta_data();
- bufmeta->clear();
+ MetaDataBase &bufmeta = mBuffer->meta_data();
+ bufmeta.clear();
if (smpl->encryptedsizes.size()) {
// store clear/encrypted lengths in metadata
- bufmeta->setData(kKeyPlainSizes, 0,
+ bufmeta.setData(kKeyPlainSizes, 0,
smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
- bufmeta->setData(kKeyEncryptedSizes, 0,
+ bufmeta.setData(kKeyEncryptedSizes, 0,
smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
- bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
- bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
- bufmeta->setInt32(kKeyCryptoMode, mCryptoMode);
- bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
+ bufmeta.setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
+ bufmeta.setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
+ bufmeta.setInt32(kKeyCryptoMode, mCryptoMode);
+ bufmeta.setData(kKeyCryptoKey, 0, mCryptoKey, 16);
}
if ((!mIsAVC && !mIsHEVC)|| mWantsNALFragments) {
@@ -4982,24 +4980,24 @@
CHECK(mBuffer != NULL);
mBuffer->set_range(0, size);
- mBuffer->meta_data()->setInt64(
+ mBuffer->meta_data().setInt64(
kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
- mBuffer->meta_data()->setInt64(
+ mBuffer->meta_data().setInt64(
kKeyDuration, ((int64_t)smpl->duration * 1000000) / mTimescale);
if (targetSampleTimeUs >= 0) {
- mBuffer->meta_data()->setInt64(
+ mBuffer->meta_data().setInt64(
kKeyTargetTime, targetSampleTimeUs);
}
if (mIsAVC) {
uint32_t layerId = FindAVCLayerId(
(const uint8_t *)mBuffer->data(), mBuffer->range_length());
- mBuffer->meta_data()->setInt32(kKeyTemporalLayerId, layerId);
+ mBuffer->meta_data().setInt32(kKeyTemporalLayerId, layerId);
}
if (isSyncSample) {
- mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+ mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
}
++mCurrentSampleIndex;
@@ -5057,7 +5055,7 @@
// the start code (0x00 00 00 01).
ssize_t num_bytes_read = 0;
int32_t drm = 0;
- bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
+ bool usesDRM = (mFormat.findInt32(kKeyIsDRM, &drm) && drm != 0);
void *data = NULL;
bool isMalFormed = false;
if (usesDRM) {
@@ -5068,8 +5066,7 @@
}
} else {
int32_t max_size;
- if (mFormat == NULL
- || !mFormat->findInt32(kKeyMaxInputSize, &max_size)
+ if (!mFormat.findInt32(kKeyMaxInputSize, &max_size)
|| !isInRange((size_t)0u, (size_t)max_size, size)) {
isMalFormed = true;
} else {
@@ -5149,18 +5146,18 @@
mBuffer->set_range(0, dstOffset);
}
- mBuffer->meta_data()->setInt64(
+ mBuffer->meta_data().setInt64(
kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
- mBuffer->meta_data()->setInt64(
+ mBuffer->meta_data().setInt64(
kKeyDuration, ((int64_t)smpl->duration * 1000000) / mTimescale);
if (targetSampleTimeUs >= 0) {
- mBuffer->meta_data()->setInt64(
+ mBuffer->meta_data().setInt64(
kKeyTargetTime, targetSampleTimeUs);
}
if (isSyncSample) {
- mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+ mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
}
++mCurrentSampleIndex;
@@ -5176,8 +5173,7 @@
const char *mimePrefix) {
for (Track *track = mFirstTrack; track != NULL; track = track->next) {
const char *mime;
- if (track->meta != NULL
- && track->meta->findCString(kKeyMIMEType, &mime)
+ if (track->meta.findCString(kKeyMIMEType, &mime)
&& !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) {
return track;
}
diff --git a/media/extractors/mp4/MPEG4Extractor.h b/media/extractors/mp4/MPEG4Extractor.h
index 5c86345..9a9f0d1 100644
--- a/media/extractors/mp4/MPEG4Extractor.h
+++ b/media/extractors/mp4/MPEG4Extractor.h
@@ -22,6 +22,7 @@
#include <media/DataSourceBase.h>
#include <media/MediaExtractor.h>
+#include <media/stagefright/MetaDataBase.h>
#include <media/stagefright/foundation/AString.h>
#include <utils/List.h>
#include <utils/Vector.h>
@@ -56,10 +57,10 @@
explicit MPEG4Extractor(DataSourceBase *source, const char *mime = NULL);
virtual size_t countTracks();
- virtual MediaSourceBase *getTrack(size_t index);
- virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+ virtual MediaTrack *getTrack(size_t index);
+ virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
- virtual sp<MetaData> getMetaData();
+ virtual status_t getMetaData(MetaDataBase& meta);
virtual uint32_t flags() const;
virtual const char * name() { return "MPEG4Extractor"; }
@@ -75,7 +76,7 @@
};
struct Track {
Track *next;
- sp<MetaData> meta;
+ MetaDataBase meta;
uint32_t timescale;
sp<SampleTable> sampleTable;
bool includes_expensive_metadata;
@@ -105,7 +106,7 @@
Track *mFirstTrack, *mLastTrack;
- sp<MetaData> mFileMetaData;
+ MetaDataBase mFileMetaData;
Vector<uint32_t> mPath;
String8 mLastCommentMean;
diff --git a/media/extractors/mpeg2/MPEG2PSExtractor.cpp b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
index c2de6e7..6980b82 100644
--- a/media/extractors/mpeg2/MPEG2PSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
@@ -24,7 +24,7 @@
#include "mpeg2ts/ESQueue.h"
#include <media/DataSourceBase.h>
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
#include <media/stagefright/foundation/ABitReader.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -40,13 +40,13 @@
namespace android {
-struct MPEG2PSExtractor::Track : public MediaSourceBase, public RefBase {
+struct MPEG2PSExtractor::Track : public MediaTrack, public RefBase {
Track(MPEG2PSExtractor *extractor,
unsigned stream_id, unsigned stream_type);
- virtual status_t start(MetaData *params);
+ virtual status_t start(MetaDataBase *params);
virtual status_t stop();
- virtual sp<MetaData> getFormat();
+ virtual status_t getFormat(MetaDataBase &);
virtual status_t read(
MediaBufferBase **buffer, const ReadOptions *options);
@@ -72,12 +72,12 @@
DISALLOW_EVIL_CONSTRUCTORS(Track);
};
-struct MPEG2PSExtractor::WrappedTrack : public MediaSourceBase {
+struct MPEG2PSExtractor::WrappedTrack : public MediaTrack {
WrappedTrack(MPEG2PSExtractor *extractor, const sp<Track> &track);
- virtual status_t start(MetaData *params);
+ virtual status_t start(MetaDataBase *params);
virtual status_t stop();
- virtual sp<MetaData> getFormat();
+ virtual status_t getFormat(MetaDataBase &);
virtual status_t read(
MediaBufferBase **buffer, const ReadOptions *options);
@@ -108,9 +108,10 @@
}
// Remove all tracks that were unable to determine their format.
+ MetaDataBase meta;
for (size_t i = mTracks.size(); i > 0;) {
i--;
- if (mTracks.valueAt(i)->getFormat() == NULL) {
+ if (mTracks.valueAt(i)->getFormat(meta) != OK) {
mTracks.removeItemsAt(i);
}
}
@@ -125,7 +126,7 @@
return mTracks.size();
}
-MediaSourceBase *MPEG2PSExtractor::getTrack(size_t index) {
+MediaTrack *MPEG2PSExtractor::getTrack(size_t index) {
if (index >= mTracks.size()) {
return NULL;
}
@@ -133,20 +134,20 @@
return new WrappedTrack(this, mTracks.valueAt(index));
}
-sp<MetaData> MPEG2PSExtractor::getTrackMetaData(
+status_t MPEG2PSExtractor::getTrackMetaData(
+ MetaDataBase &meta,
size_t index, uint32_t /* flags */) {
if (index >= mTracks.size()) {
- return NULL;
+ return UNKNOWN_ERROR;
}
- return mTracks.valueAt(index)->getFormat();
+ return mTracks.valueAt(index)->getFormat(meta);
}
-sp<MetaData> MPEG2PSExtractor::getMetaData() {
- sp<MetaData> meta = new MetaData;
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2PS);
+status_t MPEG2PSExtractor::getMetaData(MetaDataBase &meta) {
+ meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2PS);
- return meta;
+ return OK;
}
uint32_t MPEG2PSExtractor::flags() const {
@@ -634,12 +635,12 @@
mQueue = NULL;
}
-status_t MPEG2PSExtractor::Track::start(MetaData *params) {
+status_t MPEG2PSExtractor::Track::start(MetaDataBase *) {
if (mSource == NULL) {
return NO_INIT;
}
- return mSource->start(params);
+ return mSource->start(NULL); // AnotherPacketSource::start doesn't use its argument
}
status_t MPEG2PSExtractor::Track::stop() {
@@ -650,12 +651,14 @@
return mSource->stop();
}
-sp<MetaData> MPEG2PSExtractor::Track::getFormat() {
+status_t MPEG2PSExtractor::Track::getFormat(MetaDataBase &meta) {
if (mSource == NULL) {
- return NULL;
+ return NO_INIT;
}
- return mSource->getFormat();
+ sp<MetaData> sourceMeta = mSource->getFormat();
+ meta = *sourceMeta;
+ return OK;
}
status_t MPEG2PSExtractor::Track::read(
@@ -731,7 +734,7 @@
MPEG2PSExtractor::WrappedTrack::~WrappedTrack() {
}
-status_t MPEG2PSExtractor::WrappedTrack::start(MetaData *params) {
+status_t MPEG2PSExtractor::WrappedTrack::start(MetaDataBase *params) {
return mTrack->start(params);
}
@@ -739,8 +742,8 @@
return mTrack->stop();
}
-sp<MetaData> MPEG2PSExtractor::WrappedTrack::getFormat() {
- return mTrack->getFormat();
+status_t MPEG2PSExtractor::WrappedTrack::getFormat(MetaDataBase &meta) {
+ return mTrack->getFormat(meta);
}
status_t MPEG2PSExtractor::WrappedTrack::read(
diff --git a/media/extractors/mpeg2/MPEG2PSExtractor.h b/media/extractors/mpeg2/MPEG2PSExtractor.h
index 2541f4d..8b9dad9 100644
--- a/media/extractors/mpeg2/MPEG2PSExtractor.h
+++ b/media/extractors/mpeg2/MPEG2PSExtractor.h
@@ -20,6 +20,7 @@
#include <media/stagefright/foundation/ABase.h>
#include <media/MediaExtractor.h>
+#include <media/stagefright/MetaDataBase.h>
#include <utils/threads.h>
#include <utils/KeyedVector.h>
@@ -34,10 +35,10 @@
explicit MPEG2PSExtractor(DataSourceBase *source);
virtual size_t countTracks();
- virtual MediaSourceBase *getTrack(size_t index);
- virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+ virtual MediaTrack *getTrack(size_t index);
+ virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
- virtual sp<MetaData> getMetaData();
+ virtual status_t getMetaData(MetaDataBase& meta);
virtual uint32_t flags() const;
virtual const char * name() { return "MPEG2PSExtractor"; }
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.cpp b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
index 7887a7c..c83f7ce 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
@@ -24,7 +24,7 @@
#include <media/DataSourceBase.h>
#include <media/IStreamSource.h>
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooper.h>
@@ -49,16 +49,16 @@
static const int kMaxDurationReadSize = 250000LL;
static const int kMaxDurationRetry = 6;
-struct MPEG2TSSource : public MediaSourceBase {
+struct MPEG2TSSource : public MediaTrack {
MPEG2TSSource(
MPEG2TSExtractor *extractor,
const sp<AnotherPacketSource> &impl,
bool doesSeek);
virtual ~MPEG2TSSource();
- virtual status_t start(MetaData *params = NULL);
+ virtual status_t start(MetaDataBase *params = NULL);
virtual status_t stop();
- virtual sp<MetaData> getFormat();
+ virtual status_t getFormat(MetaDataBase &);
virtual status_t read(
MediaBufferBase **buffer, const ReadOptions *options = NULL);
@@ -86,16 +86,18 @@
MPEG2TSSource::~MPEG2TSSource() {
}
-status_t MPEG2TSSource::start(MetaData *params) {
- return mImpl->start(params);
+status_t MPEG2TSSource::start(MetaDataBase *) {
+ return mImpl->start(NULL); // AnotherPacketSource::start() doesn't use its argument
}
status_t MPEG2TSSource::stop() {
return mImpl->stop();
}
-sp<MetaData> MPEG2TSSource::getFormat() {
- return mImpl->getFormat();
+status_t MPEG2TSSource::getFormat(MetaDataBase &meta) {
+ sp<MetaData> implMeta = mImpl->getFormat();
+ meta = *implMeta;
+ return OK;
}
status_t MPEG2TSSource::read(
@@ -133,7 +135,7 @@
return mSourceImpls.size();
}
-MediaSourceBase *MPEG2TSExtractor::getTrack(size_t index) {
+MediaTrack *MPEG2TSExtractor::getTrack(size_t index) {
if (index >= mSourceImpls.size()) {
return NULL;
}
@@ -144,23 +146,28 @@
(mSeekSyncPoints == &mSyncPoints.editItemAt(index)));
}
-sp<MetaData> MPEG2TSExtractor::getTrackMetaData(
+status_t MPEG2TSExtractor::getTrackMetaData(
+ MetaDataBase &meta,
size_t index, uint32_t /* flags */) {
- return index < mSourceImpls.size()
+ sp<MetaData> implMeta = index < mSourceImpls.size()
? mSourceImpls.editItemAt(index)->getFormat() : NULL;
+ if (implMeta == NULL) {
+ return UNKNOWN_ERROR;
+ }
+ meta = *implMeta;
+ return OK;
}
-sp<MetaData> MPEG2TSExtractor::getMetaData() {
- sp<MetaData> meta = new MetaData;
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
+status_t MPEG2TSExtractor::getMetaData(MetaDataBase &meta) {
+ meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
- return meta;
+ return OK;
}
//static
-bool MPEG2TSExtractor::isScrambledFormat(const sp<MetaData> &format) {
+bool MPEG2TSExtractor::isScrambledFormat(MetaDataBase &format) {
const char *mime;
- return format->findCString(kKeyMIMEType, &mime)
+ return format.findCString(kKeyMIMEType, &mime)
&& (!strcasecmp(MEDIA_MIMETYPE_VIDEO_SCRAMBLED, mime)
|| !strcasecmp(MEDIA_MIMETYPE_AUDIO_SCRAMBLED, mime));
}
@@ -213,7 +220,7 @@
if (format != NULL) {
haveVideo = true;
addSource(impl);
- if (!isScrambledFormat(format)) {
+ if (!isScrambledFormat(*(format.get()))) {
mSyncPoints.push();
mSeekSyncPoints = &mSyncPoints.editTop();
}
@@ -229,7 +236,7 @@
if (format != NULL) {
haveAudio = true;
addSource(impl);
- if (!isScrambledFormat(format)) {
+ if (!isScrambledFormat(*(format.get()))) {
mSyncPoints.push();
if (!haveVideo) {
mSeekSyncPoints = &mSyncPoints.editTop();
@@ -470,7 +477,7 @@
}
status_t MPEG2TSExtractor::seek(int64_t seekTimeUs,
- const MediaSourceBase::ReadOptions::SeekMode &seekMode) {
+ const MediaTrack::ReadOptions::SeekMode &seekMode) {
if (mSeekSyncPoints == NULL || mSeekSyncPoints->isEmpty()) {
ALOGW("No sync point to seek to.");
// ... and therefore we have nothing useful to do here.
@@ -491,18 +498,18 @@
}
switch (seekMode) {
- case MediaSourceBase::ReadOptions::SEEK_NEXT_SYNC:
+ case MediaTrack::ReadOptions::SEEK_NEXT_SYNC:
if (index == mSeekSyncPoints->size()) {
ALOGW("Next sync not found; starting from the latest sync.");
--index;
}
break;
- case MediaSourceBase::ReadOptions::SEEK_CLOSEST_SYNC:
- case MediaSourceBase::ReadOptions::SEEK_CLOSEST:
+ case MediaTrack::ReadOptions::SEEK_CLOSEST_SYNC:
+ case MediaTrack::ReadOptions::SEEK_CLOSEST:
ALOGW("seekMode not supported: %d; falling back to PREVIOUS_SYNC",
seekMode);
// fall-through
- case MediaSourceBase::ReadOptions::SEEK_PREVIOUS_SYNC:
+ case MediaTrack::ReadOptions::SEEK_PREVIOUS_SYNC:
if (index == 0) {
ALOGW("Previous sync not found; starting from the earliest "
"sync.");
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.h b/media/extractors/mpeg2/MPEG2TSExtractor.h
index df07fac..cbdd3cb 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.h
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.h
@@ -1,4 +1,5 @@
/*
+
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,7 +21,8 @@
#include <media/stagefright/foundation/ABase.h>
#include <media/MediaExtractor.h>
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
+#include <media/stagefright/MetaDataBase.h>
#include <utils/threads.h>
#include <utils/KeyedVector.h>
#include <utils/Vector.h>
@@ -40,10 +42,10 @@
explicit MPEG2TSExtractor(DataSourceBase *source);
virtual size_t countTracks();
- virtual MediaSourceBase *getTrack(size_t index);
- virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+ virtual MediaTrack *getTrack(size_t index);
+ virtual status_t getTrackMetaData(MetaDataBase &meta, size_t index, uint32_t flags);
- virtual sp<MetaData> getMetaData();
+ virtual status_t getMetaData(MetaDataBase& meta);
virtual status_t setMediaCas(const uint8_t* /*casToken*/, size_t /*size*/) override;
@@ -72,7 +74,7 @@
off64_t mOffset;
- static bool isScrambledFormat(const sp<MetaData> &format);
+ static bool isScrambledFormat(MetaDataBase &format);
void init();
void addSource(const sp<AnotherPacketSource> &impl);
diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/extractors/ogg/OggExtractor.cpp
index 6d7576f..4d49013 100644
--- a/media/extractors/ogg/OggExtractor.cpp
+++ b/media/extractors/ogg/OggExtractor.cpp
@@ -22,7 +22,8 @@
#include <cutils/properties.h>
#include <media/DataSourceBase.h>
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
+#include <media/VorbisComment.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/base64.h>
@@ -31,7 +32,7 @@
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MetaDataBase.h>
#include <utils/String8.h>
extern "C" {
@@ -45,12 +46,12 @@
namespace android {
-struct OggSource : public MediaSourceBase {
+struct OggSource : public MediaTrack {
explicit OggSource(OggExtractor *extractor);
- virtual sp<MetaData> getFormat();
+ virtual status_t getFormat(MetaDataBase &);
- virtual status_t start(MetaData *params = NULL);
+ virtual status_t start(MetaDataBase *params = NULL);
virtual status_t stop();
virtual status_t read(
@@ -75,7 +76,7 @@
int64_t seekPreRollUs);
virtual ~MyOggExtractor();
- sp<MetaData> getFormat() const;
+ status_t getFormat(MetaDataBase &) const;
// Returns an approximate bitrate in bits per second.
virtual uint64_t approxBitrate() const = 0;
@@ -86,7 +87,10 @@
status_t init();
- sp<MetaData> getFileMetaData() { return mFileMeta; }
+ status_t getFileMetaData(MetaDataBase &meta) {
+ meta = mFileMeta;
+ return OK;
+ }
protected:
struct Page {
@@ -124,8 +128,8 @@
vorbis_info mVi;
vorbis_comment mVc;
- sp<MetaData> mMeta;
- sp<MetaData> mFileMeta;
+ MetaDataBase mMeta;
+ MetaDataBase mFileMeta;
Vector<TOCEntry> mTableOfContents;
@@ -219,9 +223,6 @@
int64_t mStartGranulePosition;
};
-static void extractAlbumArt(
- const sp<MetaData> &fileMeta, const void *data, size_t size);
-
////////////////////////////////////////////////////////////////////////////////
OggSource::OggSource(OggExtractor *extractor)
@@ -235,11 +236,11 @@
}
}
-sp<MetaData> OggSource::getFormat() {
- return mExtractor->mImpl->getFormat();
+status_t OggSource::getFormat(MetaDataBase &meta) {
+ return mExtractor->mImpl->getFormat(meta);
}
-status_t OggSource::start(MetaData * /* params */) {
+status_t OggSource::start(MetaDataBase * /* params */) {
if (mStarted) {
return INVALID_OPERATION;
}
@@ -277,14 +278,14 @@
#if 0
int64_t timeUs;
- if (packet->meta_data()->findInt64(kKeyTime, &timeUs)) {
+ if (packet->meta_data().findInt64(kKeyTime, &timeUs)) {
ALOGI("found time = %lld us", timeUs);
} else {
ALOGI("NO time");
}
#endif
- packet->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+ packet->meta_data().setInt32(kKeyIsSyncFrame, 1);
*out = packet;
@@ -321,8 +322,9 @@
vorbis_info_clear(&mVi);
}
-sp<MetaData> MyOggExtractor::getFormat() const {
- return mMeta;
+status_t MyOggExtractor::getFormat(MetaDataBase &meta) const {
+ meta = mMeta;
+ return OK;
}
status_t MyOggExtractor::findNextPage(
@@ -606,17 +608,17 @@
int32_t currentPageSamples;
// Calculate timestamps by accumulating durations starting from the first sample of a page;
// We assume that we only seek to page boundaries.
- if ((*out)->meta_data()->findInt32(kKeyValidSamples, ¤tPageSamples)) {
+ if ((*out)->meta_data().findInt32(kKeyValidSamples, ¤tPageSamples)) {
// first packet in page
if (mOffset == mFirstDataOffset) {
currentPageSamples -= mStartGranulePosition;
- (*out)->meta_data()->setInt32(kKeyValidSamples, currentPageSamples);
+ (*out)->meta_data().setInt32(kKeyValidSamples, currentPageSamples);
}
mCurGranulePosition = mCurrentPage.mGranulePosition - currentPageSamples;
}
int64_t timeUs = getTimeUsOfGranule(mCurGranulePosition);
- (*out)->meta_data()->setInt64(kKeyTime, timeUs);
+ (*out)->meta_data().setInt64(kKeyTime, timeUs);
uint32_t frames = getNumSamplesInPacket(*out);
mCurGranulePosition += frames;
@@ -745,7 +747,7 @@
// We've just read the entire packet.
if (mFirstPacketInPage) {
- buffer->meta_data()->setInt32(
+ buffer->meta_data().setInt32(
kKeyValidSamples, mCurrentPageSamples);
mFirstPacketInPage = false;
}
@@ -767,7 +769,7 @@
mCurrentPage.mPrevPacketPos += actualBlockSize / 2;
mCurrentPage.mPrevPacketSize = curBlockSize;
}
- buffer->meta_data()->setInt64(kKeyTime, timeUs);
+ buffer->meta_data().setInt64(kKeyTime, timeUs);
}
*out = buffer;
@@ -813,10 +815,10 @@
// is already complete.
if (timeUs >= 0) {
- buffer->meta_data()->setInt64(kKeyTime, timeUs);
+ buffer->meta_data().setInt64(kKeyTime, timeUs);
}
- buffer->meta_data()->setInt32(
+ buffer->meta_data().setInt32(
kKeyValidSamples, mCurrentPageSamples);
mFirstPacketInPage = false;
@@ -829,8 +831,7 @@
}
status_t MyOggExtractor::init() {
- mMeta = new MetaData;
- mMeta->setCString(kKeyMIMEType, mMimeType);
+ mMeta.setCString(kKeyMIMEType, mMimeType);
status_t err;
MediaBufferBase *packet;
@@ -863,7 +864,7 @@
int64_t durationUs = getTimeUsOfGranule(lastGranulePosition);
- mMeta->setInt64(kKeyDuration, durationUs);
+ mMeta.setInt64(kKeyDuration, durationUs);
buildTableOfContents();
}
@@ -979,25 +980,35 @@
mChannelCount = data[9];
mCodecDelay = U16LE_AT(&data[10]);
- mMeta->setData(kKeyOpusHeader, 0, data, size);
- mMeta->setInt32(kKeySampleRate, kOpusSampleRate);
- mMeta->setInt32(kKeyChannelCount, mChannelCount);
- mMeta->setInt64(kKeyOpusSeekPreRoll /* ns */, kOpusSeekPreRollUs * 1000 /* = 80 ms*/);
- mMeta->setInt64(kKeyOpusCodecDelay /* ns */,
+ mMeta.setData(kKeyOpusHeader, 0, data, size);
+ mMeta.setInt32(kKeySampleRate, kOpusSampleRate);
+ mMeta.setInt32(kKeyChannelCount, mChannelCount);
+ mMeta.setInt64(kKeyOpusSeekPreRoll /* ns */, kOpusSeekPreRollUs * 1000 /* = 80 ms*/);
+ mMeta.setInt64(kKeyOpusCodecDelay /* ns */,
mCodecDelay /* sample/s */ * 1000000000ll / kOpusSampleRate);
return OK;
}
+struct TmpData {
+ uint8_t *data;
+ TmpData(size_t size) {
+ data = (uint8_t*) malloc(size);
+ }
+ ~TmpData() {
+ free(data);
+ }
+};
+
status_t MyOpusExtractor::verifyOpusComments(MediaBufferBase *buffer) {
// add artificial framing bit so we can reuse _vorbis_unpack_comment
int32_t commentSize = buffer->range_length() + 1;
- sp<ABuffer> aBuf = new ABuffer(commentSize);
- if (aBuf->capacity() <= buffer->range_length()) {
+ TmpData commentDataHolder(commentSize);
+ uint8_t *commentData = commentDataHolder.data;
+ if (commentData == nullptr) {
return ERROR_MALFORMED;
}
- uint8_t* commentData = aBuf->data();
memcpy(commentData,
(uint8_t *)buffer->data() + buffer->range_offset(),
buffer->range_length());
@@ -1120,10 +1131,10 @@
return ERROR_MALFORMED;
}
- mMeta->setData(kKeyVorbisInfo, 0, data, size);
- mMeta->setInt32(kKeySampleRate, mVi.rate);
- mMeta->setInt32(kKeyChannelCount, mVi.channels);
- mMeta->setInt32(kKeyBitRate, mVi.bitrate_nominal);
+ mMeta.setData(kKeyVorbisInfo, 0, data, size);
+ mMeta.setInt32(kKeySampleRate, mVi.rate);
+ mMeta.setInt32(kKeyChannelCount, mVi.channels);
+ mMeta.setInt32(kKeyBitRate, mVi.bitrate_nominal);
ALOGV("lower-bitrate = %ld", mVi.bitrate_lower);
ALOGV("upper-bitrate = %ld", mVi.bitrate_upper);
@@ -1138,7 +1149,7 @@
if (mSource->getSize(&size) == OK) {
uint64_t bps = approxBitrate();
if (bps != 0) {
- mMeta->setInt64(kKeyDuration, size * 8000000ll / bps);
+ mMeta.setInt64(kKeyDuration, size * 8000000ll / bps);
}
}
break;
@@ -1160,7 +1171,7 @@
return ERROR_MALFORMED;
}
- mMeta->setData(kKeyVorbisBooks, 0, data, size);
+ mMeta.setData(kKeyVorbisBooks, 0, data, size);
break;
}
}
@@ -1176,138 +1187,14 @@
return (mVi.bitrate_lower + mVi.bitrate_upper) / 2;
}
-// also exists in FLACExtractor, candidate for moving to utility/support library?
-static void parseVorbisComment(
- const sp<MetaData> &fileMeta, const char *comment, size_t commentLength)
-{
- struct {
- const char *const mTag;
- uint32_t mKey;
- } kMap[] = {
- { "TITLE", kKeyTitle },
- { "ARTIST", kKeyArtist },
- { "ALBUMARTIST", kKeyAlbumArtist },
- { "ALBUM ARTIST", kKeyAlbumArtist },
- { "COMPILATION", kKeyCompilation },
- { "ALBUM", kKeyAlbum },
- { "COMPOSER", kKeyComposer },
- { "GENRE", kKeyGenre },
- { "AUTHOR", kKeyAuthor },
- { "TRACKNUMBER", kKeyCDTrackNumber },
- { "DISCNUMBER", kKeyDiscNumber },
- { "DATE", kKeyDate },
- { "YEAR", kKeyYear },
- { "LYRICIST", kKeyWriter },
- { "METADATA_BLOCK_PICTURE", kKeyAlbumArt },
- { "ANDROID_LOOP", kKeyAutoLoop },
- };
-
- for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) {
- size_t tagLen = strlen(kMap[j].mTag);
- if (!strncasecmp(kMap[j].mTag, comment, tagLen)
- && comment[tagLen] == '=') {
- if (kMap[j].mKey == kKeyAlbumArt) {
- extractAlbumArt(
- fileMeta,
- &comment[tagLen + 1],
- commentLength - tagLen - 1);
- } else if (kMap[j].mKey == kKeyAutoLoop) {
- if (!strcasecmp(&comment[tagLen + 1], "true")) {
- fileMeta->setInt32(kKeyAutoLoop, true);
- }
- } else {
- fileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]);
- }
- }
- }
-
-}
-
-// also exists in FLACExtractor, candidate for moving to utility/support library?
-static void extractAlbumArt(
- const sp<MetaData> &fileMeta, const void *data, size_t size) {
- ALOGV("extractAlbumArt from '%s'", (const char *)data);
-
- sp<ABuffer> flacBuffer = decodeBase64(AString((const char *)data, size));
- if (flacBuffer == NULL) {
- ALOGE("malformed base64 encoded data.");
- return;
- }
-
- size_t flacSize = flacBuffer->size();
- uint8_t *flac = flacBuffer->data();
- ALOGV("got flac of size %zu", flacSize);
-
- uint32_t picType;
- uint32_t typeLen;
- uint32_t descLen;
- uint32_t dataLen;
- char type[128];
-
- if (flacSize < 8) {
- return;
- }
-
- picType = U32_AT(flac);
-
- if (picType != 3) {
- // This is not a front cover.
- return;
- }
-
- typeLen = U32_AT(&flac[4]);
- if (typeLen > sizeof(type) - 1) {
- return;
- }
-
- // we've already checked above that flacSize >= 8
- if (flacSize - 8 < typeLen) {
- return;
- }
-
- memcpy(type, &flac[8], typeLen);
- type[typeLen] = '\0';
-
- ALOGV("picType = %d, type = '%s'", picType, type);
-
- if (!strcmp(type, "-->")) {
- // This is not inline cover art, but an external url instead.
- return;
- }
-
- if (flacSize < 32 || flacSize - 32 < typeLen) {
- return;
- }
-
- descLen = U32_AT(&flac[8 + typeLen]);
- if (flacSize - 32 - typeLen < descLen) {
- return;
- }
-
- dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]);
-
- // we've already checked above that (flacSize - 32 - typeLen - descLen) >= 0
- if (flacSize - 32 - typeLen - descLen < dataLen) {
- return;
- }
-
- ALOGV("got image data, %zu trailing bytes",
- flacSize - 32 - typeLen - descLen - dataLen);
-
- fileMeta->setData(
- kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen);
-
- fileMeta->setCString(kKeyAlbumArtMIME, type);
-}
void MyOggExtractor::parseFileMetaData() {
- mFileMeta = new MetaData;
- mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG);
+ mFileMeta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG);
for (int i = 0; i < mVc.comments; ++i) {
const char *comment = mVc.user_comments[i];
size_t commentLength = mVc.comment_lengths[i];
- parseVorbisComment(mFileMeta, comment, commentLength);
+ parseVorbisComment(&mFileMeta, comment, commentLength);
//ALOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]);
}
}
@@ -1348,7 +1235,7 @@
return mInitCheck != OK ? 0 : 1;
}
-MediaSourceBase *OggExtractor::getTrack(size_t index) {
+MediaTrack *OggExtractor::getTrack(size_t index) {
if (index >= 1) {
return NULL;
}
@@ -1356,17 +1243,18 @@
return new OggSource(this);
}
-sp<MetaData> OggExtractor::getTrackMetaData(
+status_t OggExtractor::getTrackMetaData(
+ MetaDataBase &meta,
size_t index, uint32_t /* flags */) {
if (index >= 1) {
- return NULL;
+ return UNKNOWN_ERROR;
}
- return mImpl->getFormat();
+ return mImpl->getFormat(meta);
}
-sp<MetaData> OggExtractor::getMetaData() {
- return mImpl->getFileMetaData();
+status_t OggExtractor::getMetaData(MetaDataBase &meta) {
+ return mImpl->getFileMetaData(meta);
}
static MediaExtractor* CreateExtractor(
diff --git a/media/extractors/ogg/OggExtractor.h b/media/extractors/ogg/OggExtractor.h
index c9c37eb..9fe2944 100644
--- a/media/extractors/ogg/OggExtractor.h
+++ b/media/extractors/ogg/OggExtractor.h
@@ -34,10 +34,10 @@
explicit OggExtractor(DataSourceBase *source);
virtual size_t countTracks();
- virtual MediaSourceBase *getTrack(size_t index);
- virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+ virtual MediaTrack *getTrack(size_t index);
+ virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
- virtual sp<MetaData> getMetaData();
+ virtual status_t getMetaData(MetaDataBase& meta);
virtual const char * name() { return "OggExtractor"; }
protected:
@@ -55,10 +55,6 @@
OggExtractor &operator=(const OggExtractor &);
};
-bool SniffOgg(
- DataSourceBase *source, String8 *mimeType, float *confidence,
- sp<AMessage> *);
-
} // namespace android
#endif // OGG_EXTRACTOR_H_
diff --git a/media/extractors/wav/Android.bp b/media/extractors/wav/Android.bp
index 65c71ef..17836bb 100644
--- a/media/extractors/wav/Android.bp
+++ b/media/extractors/wav/Android.bp
@@ -10,7 +10,6 @@
"liblog",
"libmediaextractor",
"libstagefright_foundation",
- "libutils",
],
static_libs: [
diff --git a/media/extractors/wav/WAVExtractor.cpp b/media/extractors/wav/WAVExtractor.cpp
index a18cee5..f5a1b01 100644
--- a/media/extractors/wav/WAVExtractor.cpp
+++ b/media/extractors/wav/WAVExtractor.cpp
@@ -22,7 +22,7 @@
#include <audio_utils/primitives.h>
#include <media/DataSourceBase.h>
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDefs.h>
@@ -55,17 +55,17 @@
return ptr[1] << 8 | ptr[0];
}
-struct WAVSource : public MediaSourceBase {
+struct WAVSource : public MediaTrack {
WAVSource(
DataSourceBase *dataSource,
- const sp<MetaData> &meta,
+ MetaDataBase &meta,
uint16_t waveFormat,
int32_t bitsPerSample,
off64_t offset, size_t size);
- virtual status_t start(MetaData *params = NULL);
+ virtual status_t start(MetaDataBase *params = NULL);
virtual status_t stop();
- virtual sp<MetaData> getFormat();
+ virtual status_t getFormat(MetaDataBase &meta);
virtual status_t read(
MediaBufferBase **buffer, const ReadOptions *options = NULL);
@@ -79,7 +79,7 @@
static const size_t kMaxFrameSize;
DataSourceBase *mDataSource;
- sp<MetaData> mMeta;
+ MetaDataBase &mMeta;
uint16_t mWaveFormat;
int32_t mSampleRate;
int32_t mNumChannels;
@@ -104,23 +104,20 @@
WAVExtractor::~WAVExtractor() {
}
-sp<MetaData> WAVExtractor::getMetaData() {
- sp<MetaData> meta = new MetaData;
-
- if (mInitCheck != OK) {
- return meta;
+status_t WAVExtractor::getMetaData(MetaDataBase &meta) {
+ meta.clear();
+ if (mInitCheck == OK) {
+ meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_WAV);
}
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_WAV);
-
- return meta;
+ return OK;
}
size_t WAVExtractor::countTracks() {
return mInitCheck == OK ? 1 : 0;
}
-MediaSourceBase *WAVExtractor::getTrack(size_t index) {
+MediaTrack *WAVExtractor::getTrack(size_t index) {
if (mInitCheck != OK || index > 0) {
return NULL;
}
@@ -130,13 +127,15 @@
mWaveFormat, mBitsPerSample, mDataOffset, mDataSize);
}
-sp<MetaData> WAVExtractor::getTrackMetaData(
+status_t WAVExtractor::getTrackMetaData(
+ MetaDataBase &meta,
size_t index, uint32_t /* flags */) {
if (mInitCheck != OK || index > 0) {
- return NULL;
+ return UNKNOWN_ERROR;
}
- return mTrackMeta;
+ meta = mTrackMeta;
+ return OK;
}
status_t WAVExtractor::init() {
@@ -285,33 +284,33 @@
mDataOffset = offset;
mDataSize = chunkSize;
- mTrackMeta = new MetaData;
+ mTrackMeta.clear();
switch (mWaveFormat) {
case WAVE_FORMAT_PCM:
case WAVE_FORMAT_IEEE_FLOAT:
- mTrackMeta->setCString(
+ mTrackMeta.setCString(
kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
break;
case WAVE_FORMAT_ALAW:
- mTrackMeta->setCString(
+ mTrackMeta.setCString(
kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_G711_ALAW);
break;
case WAVE_FORMAT_MSGSM:
- mTrackMeta->setCString(
+ mTrackMeta.setCString(
kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MSGSM);
break;
default:
CHECK_EQ(mWaveFormat, (uint16_t)WAVE_FORMAT_MULAW);
- mTrackMeta->setCString(
+ mTrackMeta.setCString(
kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_G711_MLAW);
break;
}
- mTrackMeta->setInt32(kKeyChannelCount, mNumChannels);
- mTrackMeta->setInt32(kKeyChannelMask, mChannelMask);
- mTrackMeta->setInt32(kKeySampleRate, mSampleRate);
- mTrackMeta->setInt32(kKeyPcmEncoding, kAudioEncodingPcm16bit);
+ mTrackMeta.setInt32(kKeyChannelCount, mNumChannels);
+ mTrackMeta.setInt32(kKeyChannelMask, mChannelMask);
+ mTrackMeta.setInt32(kKeySampleRate, mSampleRate);
+ mTrackMeta.setInt32(kKeyPcmEncoding, kAudioEncodingPcm16bit);
int64_t durationUs = 0;
if (mWaveFormat == WAVE_FORMAT_MSGSM) {
@@ -333,7 +332,7 @@
1000000LL * num_samples / mSampleRate;
}
- mTrackMeta->setInt64(kKeyDuration, durationUs);
+ mTrackMeta.setInt64(kKeyDuration, durationUs);
return OK;
}
@@ -349,7 +348,7 @@
WAVSource::WAVSource(
DataSourceBase *dataSource,
- const sp<MetaData> &meta,
+ MetaDataBase &meta,
uint16_t waveFormat,
int32_t bitsPerSample,
off64_t offset, size_t size)
@@ -363,10 +362,10 @@
mSize(size),
mStarted(false),
mGroup(NULL) {
- CHECK(mMeta->findInt32(kKeySampleRate, &mSampleRate));
- CHECK(mMeta->findInt32(kKeyChannelCount, &mNumChannels));
+ CHECK(mMeta.findInt32(kKeySampleRate, &mSampleRate));
+ CHECK(mMeta.findInt32(kKeyChannelCount, &mNumChannels));
- mMeta->setInt32(kKeyMaxInputSize, kMaxFrameSize);
+ mMeta.setInt32(kKeyMaxInputSize, kMaxFrameSize);
}
WAVSource::~WAVSource() {
@@ -375,7 +374,7 @@
}
}
-status_t WAVSource::start(MetaData * /* params */) {
+status_t WAVSource::start(MetaDataBase * /* params */) {
ALOGV("WAVSource::start");
CHECK(!mStarted);
@@ -408,10 +407,11 @@
return OK;
}
-sp<MetaData> WAVSource::getFormat() {
+status_t WAVSource::getFormat(MetaDataBase &meta) {
ALOGV("WAVSource::getFormat");
- return mMeta;
+ meta = mMeta;
+ return OK;
}
status_t WAVSource::read(
@@ -532,9 +532,9 @@
/ (mNumChannels * bytesPerSample) / mSampleRate;
}
- buffer->meta_data()->setInt64(kKeyTime, timeStampUs);
+ buffer->meta_data().setInt64(kKeyTime, timeStampUs);
- buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+ buffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
mCurrentPos += n;
*out = buffer;
diff --git a/media/extractors/wav/WAVExtractor.h b/media/extractors/wav/WAVExtractor.h
index 67661ed..467d0b7 100644
--- a/media/extractors/wav/WAVExtractor.h
+++ b/media/extractors/wav/WAVExtractor.h
@@ -20,6 +20,7 @@
#include <utils/Errors.h>
#include <media/MediaExtractor.h>
+#include <media/stagefright/MetaDataBase.h>
namespace android {
@@ -32,10 +33,10 @@
explicit WAVExtractor(DataSourceBase *source);
virtual size_t countTracks();
- virtual MediaSourceBase *getTrack(size_t index);
- virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+ virtual MediaTrack *getTrack(size_t index);
+ virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
- virtual sp<MetaData> getMetaData();
+ virtual status_t getMetaData(MetaDataBase& meta);
virtual const char * name() { return "WAVExtractor"; }
virtual ~WAVExtractor();
@@ -51,7 +52,7 @@
uint16_t mBitsPerSample;
off64_t mDataOffset;
size_t mDataSize;
- sp<MetaData> mTrackMeta;
+ MetaDataBase mTrackMeta;
status_t init();
diff --git a/media/libaaudio/tests/Android.bp b/media/libaaudio/tests/Android.bp
index 45d417f..beec9e2 100644
--- a/media/libaaudio/tests/Android.bp
+++ b/media/libaaudio/tests/Android.bp
@@ -148,3 +148,15 @@
"libutils",
],
}
+
+cc_test {
+ name: "test_interference",
+ defaults: ["libaaudio_tests_defaults"],
+ srcs: ["test_interference.cpp"],
+ shared_libs: [
+ "libaaudio",
+ "libbinder",
+ "libcutils",
+ "libutils",
+ ],
+}
diff --git a/media/libaaudio/tests/test_interference.cpp b/media/libaaudio/tests/test_interference.cpp
new file mode 100644
index 0000000..7eaf225
--- /dev/null
+++ b/media/libaaudio/tests/test_interference.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+// Play a shared stream that might use MMAP.
+// Then play a second stream at a different sample rate.
+// Make sure the first stream is still running.
+// See: b/73369112 | AAudio disconnects shared stream if second MMAP open fails
+
+#include <memory.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <android-base/macros.h>
+#include <aaudio/AAudio.h>
+
+#include <gtest/gtest.h>
+
+// Callback function that fills the audio output buffer.
+aaudio_data_callback_result_t MyDataCallbackProc(
+ AAudioStream *stream,
+ void *userData,
+ void *audioData,
+ int32_t numFrames) {
+ (void) userData;
+ int32_t numSamples = AAudioStream_getChannelCount(stream) * numFrames;
+ aaudio_format_t format = AAudioStream_getFormat(stream);
+ if (format == AAUDIO_FORMAT_PCM_I16) {
+ memset(audioData, 0, numSamples * sizeof(int16_t));
+ } else if (format == AAUDIO_FORMAT_PCM_FLOAT) {
+ memset(audioData, 0, numSamples * sizeof(float));
+ }
+ return AAUDIO_CALLBACK_RESULT_CONTINUE;
+}
+
+//void foo() { // for tricking the Android Studio formatter
+TEST(test_interference, aaudio_mmap_interference) {
+
+ AAudioStreamBuilder *aaudioBuilder = nullptr;
+ AAudioStream *aaudioStream1 = nullptr;
+ AAudioStream *aaudioStream2 = nullptr;
+
+ // Use an AAudioStreamBuilder to contain requested parameters.
+ ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
+
+ // Request stream properties.
+ AAudioStreamBuilder_setSampleRate(aaudioBuilder, 48000);
+ AAudioStreamBuilder_setDataCallback(aaudioBuilder, MyDataCallbackProc, nullptr);
+ AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
+
+ // Create an AAudioStream using the Builder.
+ ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream1));
+ // Start it running.
+ ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream1));
+
+ // Verify that the stream is running.
+ sleep(1);
+ EXPECT_LT(0, AAudioStream_getFramesRead(aaudioStream1));
+ ASSERT_EQ(AAUDIO_STREAM_STATE_STARTED, AAudioStream_getState(aaudioStream1));
+
+ // Now try to open a second stream with a different rate.
+ AAudioStreamBuilder_setSampleRate(aaudioBuilder, 44100);
+ ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream2));
+ ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream2));
+
+ // Verify that the second stream is running.
+ sleep(1);
+ EXPECT_LT(0, AAudioStream_getFramesRead(aaudioStream2));
+
+ EXPECT_EQ(AAUDIO_STREAM_STATE_STARTED, AAudioStream_getState(aaudioStream2));
+
+ // Now verify that the first stream is still running.
+ EXPECT_EQ(AAUDIO_STREAM_STATE_STARTED, AAudioStream_getState(aaudioStream1));
+
+ int32_t framesRead1_1 = AAudioStream_getFramesRead(aaudioStream1);
+ EXPECT_LT(0, framesRead1_1);
+ sleep(1);
+ int32_t framesRead1_2 = AAudioStream_getFramesRead(aaudioStream1);
+ EXPECT_LT(0, framesRead1_2);
+ EXPECT_LT(framesRead1_1, framesRead1_2); // advancing?
+
+ AAudioStream_close(aaudioStream2);
+ AAudioStream_close(aaudioStream1);
+ AAudioStreamBuilder_delete(aaudioBuilder);
+}
diff --git a/media/libmedia/IMediaSource.cpp b/media/libmedia/IMediaSource.cpp
index f6b9255..f185fd4 100644
--- a/media/libmedia/IMediaSource.cpp
+++ b/media/libmedia/IMediaSource.cpp
@@ -171,13 +171,13 @@
size_t length = reply.readInt32();
buf = new RemoteMediaBufferWrapper(mem);
buf->set_range(offset, length);
- buf->meta_data()->updateFromParcel(reply);
+ buf->meta_data().updateFromParcel(reply);
} else { // INLINE_BUFFER
int32_t len = reply.readInt32();
ALOGV("INLINE_BUFFER status %d and len %d", ret, len);
buf = new MediaBuffer(len);
reply.read(buf->data(), len);
- buf->meta_data()->updateFromParcel(reply);
+ buf->meta_data().updateFromParcel(reply);
}
buffers->push_back(buf);
++bufferCount;
@@ -408,7 +408,7 @@
}
reply->writeInt32(offset);
reply->writeInt32(length);
- buf->meta_data()->writeToParcel(*reply);
+ buf->meta_data().writeToParcel(*reply);
transferBuf->addRemoteRefcount(1);
if (transferBuf != buf) {
transferBuf->release(); // release local ref
@@ -421,7 +421,7 @@
buf, buf->mMemory->size(), length);
reply->writeInt32(INLINE_BUFFER);
reply->writeByteArray(length, (uint8_t*)buf->data() + offset);
- buf->meta_data()->writeToParcel(*reply);
+ buf->meta_data().writeToParcel(*reply);
inlineTransferSize += length;
if (inlineTransferSize > kInlineMaxTransfer) {
maxNumBuffers = 0; // stop readMultiple if inline transfer is too large.
diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp
index 34deb59..0d3c1ba 100644
--- a/media/libmedia/JetPlayer.cpp
+++ b/media/libmedia/JetPlayer.cpp
@@ -36,6 +36,7 @@
mPaused(false),
mMaxTracks(maxTracks),
mEasData(NULL),
+ mIoWrapper(NULL),
mTrackBufferSize(trackBufferSize)
{
ALOGV("JetPlayer constructor");
@@ -50,7 +51,6 @@
{
ALOGV("~JetPlayer");
release();
-
}
//-------------------------------------------------------------------------------------------------
@@ -138,7 +138,8 @@
JET_Shutdown(mEasData);
EAS_Shutdown(mEasData);
}
- mIoWrapper.clear();
+ delete mIoWrapper;
+ mIoWrapper = NULL;
if (mAudioTrack != 0) {
mAudioTrack->stop();
mAudioTrack->flush();
@@ -329,6 +330,7 @@
Mutex::Autolock lock(mMutex);
+ delete mIoWrapper;
mIoWrapper = new MidiIoWrapper(path);
EAS_RESULT result = JET_OpenFile(mEasData, mIoWrapper->getLocator());
@@ -347,6 +349,7 @@
Mutex::Autolock lock(mMutex);
+ delete mIoWrapper;
mIoWrapper = new MidiIoWrapper(fd, offset, length);
EAS_RESULT result = JET_OpenFile(mEasData, mIoWrapper->getLocator());
diff --git a/media/libmedia/MediaCodecInfo.cpp b/media/libmedia/MediaCodecInfo.cpp
index a570ffe..5308e1c 100644
--- a/media/libmedia/MediaCodecInfo.cpp
+++ b/media/libmedia/MediaCodecInfo.cpp
@@ -141,6 +141,10 @@
return mIsEncoder;
}
+uint32_t MediaCodecInfo::rank() const {
+ return mRank;
+}
+
void MediaCodecInfo::getSupportedMimes(Vector<AString> *mimes) const {
mimes->clear();
for (size_t ix = 0; ix < mCaps.size(); ix++) {
@@ -170,10 +174,12 @@
AString name = AString::FromParcel(parcel);
AString owner = AString::FromParcel(parcel);
bool isEncoder = static_cast<bool>(parcel.readInt32());
+ uint32_t rank = parcel.readUint32();
sp<MediaCodecInfo> info = new MediaCodecInfo;
info->mName = name;
info->mOwner = owner;
info->mIsEncoder = isEncoder;
+ info->mRank = rank;
size_t size = static_cast<size_t>(parcel.readInt32());
for (size_t i = 0; i < size; i++) {
AString mime = AString::FromParcel(parcel);
@@ -191,6 +197,7 @@
mName.writeToParcel(parcel);
mOwner.writeToParcel(parcel);
parcel->writeInt32(mIsEncoder);
+ parcel->writeUint32(mRank);
parcel->writeInt32(mCaps.size());
for (size_t i = 0; i < mCaps.size(); i++) {
mCaps.keyAt(i).writeToParcel(parcel);
@@ -210,7 +217,7 @@
return -1;
}
-MediaCodecInfo::MediaCodecInfo() {
+MediaCodecInfo::MediaCodecInfo() : mRank(0x100) {
}
void MediaCodecInfoWriter::setName(const char* name) {
@@ -225,6 +232,10 @@
mInfo->mIsEncoder = isEncoder;
}
+void MediaCodecInfoWriter::setRank(uint32_t rank) {
+ mInfo->mRank = rank;
+}
+
std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>
MediaCodecInfoWriter::addMime(const char *mime) {
ssize_t ix = mInfo->getCapabilityIndex(mime);
diff --git a/media/libmedia/NdkWrapper.cpp b/media/libmedia/NdkWrapper.cpp
index 936e92f..5e47b48 100644
--- a/media/libmedia/NdkWrapper.cpp
+++ b/media/libmedia/NdkWrapper.cpp
@@ -574,17 +574,13 @@
//////////// AMediaCodecCryptoInfoWrapper
// static
-sp<AMediaCodecCryptoInfoWrapper> AMediaCodecCryptoInfoWrapper::Create(sp<MetaData> meta) {
- if (meta == NULL) {
- ALOGE("Create: Unexpected. No meta data for sample.");
- return NULL;
- }
+sp<AMediaCodecCryptoInfoWrapper> AMediaCodecCryptoInfoWrapper::Create(MetaDataBase &meta) {
uint32_t type;
const void *crypteddata;
size_t cryptedsize;
- if (!meta->findData(kKeyEncryptedSizes, &type, &crypteddata, &cryptedsize)) {
+ if (!meta.findData(kKeyEncryptedSizes, &type, &crypteddata, &cryptedsize)) {
return NULL;
}
@@ -597,7 +593,7 @@
const void *cleardata;
size_t clearsize;
- if (meta->findData(kKeyPlainSizes, &type, &cleardata, &clearsize)) {
+ if (meta.findData(kKeyPlainSizes, &type, &cleardata, &clearsize)) {
if (clearsize != cryptedsize) {
// The two must be of the same length.
ALOGE("Create: mismatch cryptedsize: %zu != clearsize: %zu", cryptedsize, clearsize);
@@ -607,7 +603,7 @@
const void *key;
size_t keysize;
- if (meta->findData(kKeyCryptoKey, &type, &key, &keysize)) {
+ if (meta.findData(kKeyCryptoKey, &type, &key, &keysize)) {
if (keysize != kAESBlockSize) {
// Keys must be 16 bytes in length.
ALOGE("Create: Keys must be %zu bytes in length: %zu", kAESBlockSize, keysize);
@@ -617,7 +613,7 @@
const void *iv;
size_t ivsize;
- if (meta->findData(kKeyCryptoIV, &type, &iv, &ivsize)) {
+ if (meta.findData(kKeyCryptoIV, &type, &iv, &ivsize)) {
if (ivsize != kAESBlockSize) {
// IVs must be 16 bytes in length.
ALOGE("Create: IV must be %zu bytes in length: %zu", kAESBlockSize, ivsize);
@@ -626,7 +622,7 @@
}
int32_t mode;
- if (!meta->findInt32(kKeyCryptoMode, &mode)) {
+ if (!meta.findInt32(kKeyCryptoMode, &mode)) {
mode = CryptoPlugin::kMode_AES_CTR;
}
diff --git a/media/libmedia/include/media/JetPlayer.h b/media/libmedia/include/media/JetPlayer.h
index 63d1980..bb569bc 100644
--- a/media/libmedia/include/media/JetPlayer.h
+++ b/media/libmedia/include/media/JetPlayer.h
@@ -87,7 +87,7 @@
int mMaxTracks; // max number of MIDI tracks, usually 32
EAS_DATA_HANDLE mEasData;
- sp<MidiIoWrapper> mIoWrapper;
+ MidiIoWrapper* mIoWrapper;
EAS_PCM* mAudioBuffer;// EAS renders the MIDI data into this buffer,
sp<AudioTrack> mAudioTrack; // and we play it in this audio track
int mTrackBufferSize;
diff --git a/media/libmedia/include/media/MediaCodecInfo.h b/media/libmedia/include/media/MediaCodecInfo.h
index ab2cd24..b3777d3 100644
--- a/media/libmedia/include/media/MediaCodecInfo.h
+++ b/media/libmedia/include/media/MediaCodecInfo.h
@@ -170,6 +170,7 @@
* Currently, this is the "instance name" of the IOmx service.
*/
const char *getOwnerName() const;
+ uint32_t rank() const;
/**
* Serialization over Binder
@@ -182,6 +183,7 @@
AString mOwner;
bool mIsEncoder;
KeyedVector<AString, sp<Capabilities> > mCaps;
+ uint32_t mRank;
ssize_t getCapabilityIndex(const char *mime) const;
@@ -252,6 +254,13 @@
* @return `true` if `mime` is removed; `false` if `mime` is not found.
*/
bool removeMime(const char* mime);
+ /**
+ * Set rank of the codec. MediaCodecList will stable-sort the list according
+ * to rank in non-descending order.
+ *
+ * @param rank The rank of the component.
+ */
+ void setRank(uint32_t rank);
private:
/**
* The associated `MediaCodecInfo`.
diff --git a/media/libmedia/include/media/MidiIoWrapper.h b/media/libmedia/include/media/MidiIoWrapper.h
index a27b410..b5e565e 100644
--- a/media/libmedia/include/media/MidiIoWrapper.h
+++ b/media/libmedia/include/media/MidiIoWrapper.h
@@ -23,11 +23,11 @@
namespace android {
-class MidiIoWrapper : public RefBase {
+class MidiIoWrapper {
public:
- MidiIoWrapper(const char *path);
- MidiIoWrapper(int fd, off64_t offset, int64_t size);
- MidiIoWrapper(DataSourceBase *source);
+ explicit MidiIoWrapper(const char *path);
+ explicit MidiIoWrapper(int fd, off64_t offset, int64_t size);
+ explicit MidiIoWrapper(DataSourceBase *source);
~MidiIoWrapper();
diff --git a/media/libmedia/include/media/NdkWrapper.h b/media/libmedia/include/media/NdkWrapper.h
index 49d728d..b71b758 100644
--- a/media/libmedia/include/media/NdkWrapper.h
+++ b/media/libmedia/include/media/NdkWrapper.h
@@ -149,7 +149,7 @@
};
struct AMediaCodecCryptoInfoWrapper : public RefBase {
- static sp<AMediaCodecCryptoInfoWrapper> Create(sp<MetaData> meta);
+ static sp<AMediaCodecCryptoInfoWrapper> Create(MetaDataBase &meta);
AMediaCodecCryptoInfoWrapper(int numsubsamples,
uint8_t key[16],
diff --git a/media/libmediaextractor/Android.bp b/media/libmediaextractor/Android.bp
index 79af058..b9b47cd 100644
--- a/media/libmediaextractor/Android.bp
+++ b/media/libmediaextractor/Android.bp
@@ -27,10 +27,12 @@
"MediaBuffer.cpp",
"MediaBufferBase.cpp",
"MediaBufferGroup.cpp",
- "MediaSourceBase.cpp",
"MediaSource.cpp",
+ "MediaTrack.cpp",
"MediaExtractor.cpp",
"MetaData.cpp",
+ "MetaDataBase.cpp",
+ "VorbisComment.cpp",
],
clang: true,
diff --git a/media/libmediaextractor/MediaBuffer.cpp b/media/libmediaextractor/MediaBuffer.cpp
index dac3d50..39f8d6e 100644
--- a/media/libmediaextractor/MediaBuffer.cpp
+++ b/media/libmediaextractor/MediaBuffer.cpp
@@ -145,8 +145,8 @@
mRangeLength = length;
}
-sp<MetaData> MediaBuffer::meta_data() {
- return mMetaData;
+MetaDataBase& MediaBuffer::meta_data() {
+ return *mMetaData;
}
void MediaBuffer::reset() {
@@ -170,6 +170,7 @@
if (mMemory.get() != nullptr) {
getSharedControl()->setDeadObject();
}
+ delete mMetaData;
}
void MediaBuffer::setObserver(MediaBufferObserver *observer) {
@@ -180,7 +181,7 @@
MediaBufferBase *MediaBuffer::clone() {
MediaBuffer *buffer = new MediaBuffer(mData, mSize);
buffer->set_range(mRangeOffset, mRangeLength);
- buffer->mMetaData = new MetaData(*mMetaData.get());
+ buffer->mMetaData = new MetaDataBase(*mMetaData);
add_ref();
buffer->mOriginal = this;
diff --git a/media/libmediaextractor/MediaExtractor.cpp b/media/libmediaextractor/MediaExtractor.cpp
index 2241567..a6b3dc9 100644
--- a/media/libmediaextractor/MediaExtractor.cpp
+++ b/media/libmediaextractor/MediaExtractor.cpp
@@ -35,10 +35,6 @@
MediaExtractor::~MediaExtractor() {}
-sp<MetaData> MediaExtractor::getMetaData() {
- return new MetaData;
-}
-
uint32_t MediaExtractor::flags() const {
return CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_PAUSE | CAN_SEEK;
}
diff --git a/media/libmediaextractor/MediaSourceBase.cpp b/media/libmediaextractor/MediaTrack.cpp
similarity index 69%
rename from media/libmediaextractor/MediaSourceBase.cpp
rename to media/libmediaextractor/MediaTrack.cpp
index 6d45c90..4963f58 100644
--- a/media/libmediaextractor/MediaSourceBase.cpp
+++ b/media/libmediaextractor/MediaTrack.cpp
@@ -14,51 +14,51 @@
* limitations under the License.
*/
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
namespace android {
-MediaSourceBase::MediaSourceBase() {}
+MediaTrack::MediaTrack() {}
-MediaSourceBase::~MediaSourceBase() {}
+MediaTrack::~MediaTrack() {}
////////////////////////////////////////////////////////////////////////////////
-MediaSourceBase::ReadOptions::ReadOptions() {
+MediaTrack::ReadOptions::ReadOptions() {
reset();
}
-void MediaSourceBase::ReadOptions::reset() {
+void MediaTrack::ReadOptions::reset() {
mOptions = 0;
mSeekTimeUs = 0;
mNonBlocking = false;
}
-void MediaSourceBase::ReadOptions::setNonBlocking() {
+void MediaTrack::ReadOptions::setNonBlocking() {
mNonBlocking = true;
}
-void MediaSourceBase::ReadOptions::clearNonBlocking() {
+void MediaTrack::ReadOptions::clearNonBlocking() {
mNonBlocking = false;
}
-bool MediaSourceBase::ReadOptions::getNonBlocking() const {
+bool MediaTrack::ReadOptions::getNonBlocking() const {
return mNonBlocking;
}
-void MediaSourceBase::ReadOptions::setSeekTo(int64_t time_us, SeekMode mode) {
+void MediaTrack::ReadOptions::setSeekTo(int64_t time_us, SeekMode mode) {
mOptions |= kSeekTo_Option;
mSeekTimeUs = time_us;
mSeekMode = mode;
}
-void MediaSourceBase::ReadOptions::clearSeekTo() {
+void MediaTrack::ReadOptions::clearSeekTo() {
mOptions &= ~kSeekTo_Option;
mSeekTimeUs = 0;
mSeekMode = SEEK_CLOSEST_SYNC;
}
-bool MediaSourceBase::ReadOptions::getSeekTo(
+bool MediaTrack::ReadOptions::getSeekTo(
int64_t *time_us, SeekMode *mode) const {
*time_us = mSeekTimeUs;
*mode = mSeekMode;
diff --git a/media/libmediaextractor/MetaData.cpp b/media/libmediaextractor/MetaData.cpp
index 69beea1..1d0a607 100644
--- a/media/libmediaextractor/MetaData.cpp
+++ b/media/libmediaextractor/MetaData.cpp
@@ -31,500 +31,20 @@
namespace android {
-struct MetaData::typed_data {
- typed_data();
- ~typed_data();
- typed_data(const MetaData::typed_data &);
- typed_data &operator=(const MetaData::typed_data &);
-
- void clear();
- void setData(uint32_t type, const void *data, size_t size);
- void getData(uint32_t *type, const void **data, size_t *size) const;
- // may include hexdump of binary data if verbose=true
- String8 asString(bool verbose) const;
-
-private:
- uint32_t mType;
- size_t mSize;
-
- union {
- void *ext_data;
- float reservoir;
- } u;
-
- bool usesReservoir() const {
- return mSize <= sizeof(u.reservoir);
- }
-
- void *allocateStorage(size_t size);
- void freeStorage();
-
- void *storage() {
- return usesReservoir() ? &u.reservoir : u.ext_data;
- }
-
- const void *storage() const {
- return usesReservoir() ? &u.reservoir : u.ext_data;
- }
-};
-
-struct MetaData::Rect {
- int32_t mLeft, mTop, mRight, mBottom;
-};
-
-
-struct MetaData::MetaDataInternal {
- KeyedVector<uint32_t, MetaData::typed_data> mItems;
-};
-
-
-MetaData::MetaData()
- : mInternalData(new MetaDataInternal()) {
+MetaData::MetaData() {
}
MetaData::MetaData(const MetaData &from)
- : RefBase(),
- mInternalData(new MetaDataInternal()) {
- mInternalData->mItems = from.mInternalData->mItems;
+ : MetaDataBase(from) {
+}
+MetaData::MetaData(const MetaDataBase &from)
+ : MetaDataBase(from) {
}
MetaData::~MetaData() {
- clear();
- delete mInternalData;
}
-void MetaData::clear() {
- mInternalData->mItems.clear();
-}
-
-bool MetaData::remove(uint32_t key) {
- ssize_t i = mInternalData->mItems.indexOfKey(key);
-
- if (i < 0) {
- return false;
- }
-
- mInternalData->mItems.removeItemsAt(i);
-
- return true;
-}
-
-bool MetaData::setCString(uint32_t key, const char *value) {
- return setData(key, TYPE_C_STRING, value, strlen(value) + 1);
-}
-
-bool MetaData::setInt32(uint32_t key, int32_t value) {
- return setData(key, TYPE_INT32, &value, sizeof(value));
-}
-
-bool MetaData::setInt64(uint32_t key, int64_t value) {
- return setData(key, TYPE_INT64, &value, sizeof(value));
-}
-
-bool MetaData::setFloat(uint32_t key, float value) {
- return setData(key, TYPE_FLOAT, &value, sizeof(value));
-}
-
-bool MetaData::setPointer(uint32_t key, void *value) {
- return setData(key, TYPE_POINTER, &value, sizeof(value));
-}
-
-bool MetaData::setRect(
- uint32_t key,
- int32_t left, int32_t top,
- int32_t right, int32_t bottom) {
- Rect r;
- r.mLeft = left;
- r.mTop = top;
- r.mRight = right;
- r.mBottom = bottom;
-
- return setData(key, TYPE_RECT, &r, sizeof(r));
-}
-
-/**
- * Note that the returned pointer becomes invalid when additional metadata is set.
- */
-bool MetaData::findCString(uint32_t key, const char **value) const {
- uint32_t type;
- const void *data;
- size_t size;
- if (!findData(key, &type, &data, &size) || type != TYPE_C_STRING) {
- return false;
- }
-
- *value = (const char *)data;
-
- return true;
-}
-
-bool MetaData::findInt32(uint32_t key, int32_t *value) const {
- uint32_t type = 0;
- const void *data;
- size_t size;
- if (!findData(key, &type, &data, &size) || type != TYPE_INT32) {
- return false;
- }
-
- CHECK_EQ(size, sizeof(*value));
-
- *value = *(int32_t *)data;
-
- return true;
-}
-
-bool MetaData::findInt64(uint32_t key, int64_t *value) const {
- uint32_t type = 0;
- const void *data;
- size_t size;
- if (!findData(key, &type, &data, &size) || type != TYPE_INT64) {
- return false;
- }
-
- CHECK_EQ(size, sizeof(*value));
-
- *value = *(int64_t *)data;
-
- return true;
-}
-
-bool MetaData::findFloat(uint32_t key, float *value) const {
- uint32_t type = 0;
- const void *data;
- size_t size;
- if (!findData(key, &type, &data, &size) || type != TYPE_FLOAT) {
- return false;
- }
-
- CHECK_EQ(size, sizeof(*value));
-
- *value = *(float *)data;
-
- return true;
-}
-
-bool MetaData::findPointer(uint32_t key, void **value) const {
- uint32_t type = 0;
- const void *data;
- size_t size;
- if (!findData(key, &type, &data, &size) || type != TYPE_POINTER) {
- return false;
- }
-
- CHECK_EQ(size, sizeof(*value));
-
- *value = *(void **)data;
-
- return true;
-}
-
-bool MetaData::findRect(
- uint32_t key,
- int32_t *left, int32_t *top,
- int32_t *right, int32_t *bottom) const {
- uint32_t type = 0;
- const void *data;
- size_t size;
- if (!findData(key, &type, &data, &size) || type != TYPE_RECT) {
- return false;
- }
-
- CHECK_EQ(size, sizeof(Rect));
-
- const Rect *r = (const Rect *)data;
- *left = r->mLeft;
- *top = r->mTop;
- *right = r->mRight;
- *bottom = r->mBottom;
-
- return true;
-}
-
-bool MetaData::setData(
- uint32_t key, uint32_t type, const void *data, size_t size) {
- bool overwrote_existing = true;
-
- ssize_t i = mInternalData->mItems.indexOfKey(key);
- if (i < 0) {
- typed_data item;
- i = mInternalData->mItems.add(key, item);
-
- overwrote_existing = false;
- }
-
- typed_data &item = mInternalData->mItems.editValueAt(i);
-
- item.setData(type, data, size);
-
- return overwrote_existing;
-}
-
-bool MetaData::findData(uint32_t key, uint32_t *type,
- const void **data, size_t *size) const {
- ssize_t i = mInternalData->mItems.indexOfKey(key);
-
- if (i < 0) {
- return false;
- }
-
- const typed_data &item = mInternalData->mItems.valueAt(i);
-
- item.getData(type, data, size);
-
- return true;
-}
-
-bool MetaData::hasData(uint32_t key) const {
- ssize_t i = mInternalData->mItems.indexOfKey(key);
-
- if (i < 0) {
- return false;
- }
-
- return true;
-}
-
-MetaData::typed_data::typed_data()
- : mType(0),
- mSize(0) {
-}
-
-MetaData::typed_data::~typed_data() {
- clear();
-}
-
-MetaData::typed_data::typed_data(const typed_data &from)
- : mType(from.mType),
- mSize(0) {
-
- void *dst = allocateStorage(from.mSize);
- if (dst) {
- memcpy(dst, from.storage(), mSize);
- }
-}
-
-MetaData::typed_data &MetaData::typed_data::operator=(
- const MetaData::typed_data &from) {
- if (this != &from) {
- clear();
- mType = from.mType;
- void *dst = allocateStorage(from.mSize);
- if (dst) {
- memcpy(dst, from.storage(), mSize);
- }
- }
-
- return *this;
-}
-
-void MetaData::typed_data::clear() {
- freeStorage();
-
- mType = 0;
-}
-
-void MetaData::typed_data::setData(
- uint32_t type, const void *data, size_t size) {
- clear();
-
- mType = type;
-
- void *dst = allocateStorage(size);
- if (dst) {
- memcpy(dst, data, size);
- }
-}
-
-void MetaData::typed_data::getData(
- uint32_t *type, const void **data, size_t *size) const {
- *type = mType;
- *size = mSize;
- *data = storage();
-}
-
-void *MetaData::typed_data::allocateStorage(size_t size) {
- mSize = size;
-
- if (usesReservoir()) {
- return &u.reservoir;
- }
-
- u.ext_data = malloc(mSize);
- if (u.ext_data == NULL) {
- ALOGE("Couldn't allocate %zu bytes for item", size);
- mSize = 0;
- }
- return u.ext_data;
-}
-
-void MetaData::typed_data::freeStorage() {
- if (!usesReservoir()) {
- if (u.ext_data) {
- free(u.ext_data);
- u.ext_data = NULL;
- }
- }
-
- mSize = 0;
-}
-
-String8 MetaData::typed_data::asString(bool verbose) const {
- String8 out;
- const void *data = storage();
- switch(mType) {
- case TYPE_NONE:
- out = String8::format("no type, size %zu)", mSize);
- break;
- case TYPE_C_STRING:
- out = String8::format("(char*) %s", (const char *)data);
- break;
- case TYPE_INT32:
- out = String8::format("(int32_t) %d", *(int32_t *)data);
- break;
- case TYPE_INT64:
- out = String8::format("(int64_t) %" PRId64, *(int64_t *)data);
- break;
- case TYPE_FLOAT:
- out = String8::format("(float) %f", *(float *)data);
- break;
- case TYPE_POINTER:
- out = String8::format("(void*) %p", *(void **)data);
- break;
- case TYPE_RECT:
- {
- const Rect *r = (const Rect *)data;
- out = String8::format("Rect(%d, %d, %d, %d)",
- r->mLeft, r->mTop, r->mRight, r->mBottom);
- break;
- }
-
- default:
- out = String8::format("(unknown type %d, size %zu)", mType, mSize);
- if (verbose && mSize <= 48) { // if it's less than three lines of hex data, dump it
- AString foo;
- hexdump(data, mSize, 0, &foo);
- out.append("\n");
- out.append(foo.c_str());
- }
- break;
- }
- return out;
-}
-
-static void MakeFourCCString(uint32_t x, char *s) {
- s[0] = x >> 24;
- s[1] = (x >> 16) & 0xff;
- s[2] = (x >> 8) & 0xff;
- s[3] = x & 0xff;
- s[4] = '\0';
-}
-
-String8 MetaData::toString() const {
- String8 s;
- for (int i = mInternalData->mItems.size(); --i >= 0;) {
- int32_t key = mInternalData->mItems.keyAt(i);
- char cc[5];
- MakeFourCCString(key, cc);
- const typed_data &item = mInternalData->mItems.valueAt(i);
- s.appendFormat("%s: %s", cc, item.asString(false).string());
- if (i != 0) {
- s.append(", ");
- }
- }
- return s;
-}
-void MetaData::dumpToLog() const {
- for (int i = mInternalData->mItems.size(); --i >= 0;) {
- int32_t key = mInternalData->mItems.keyAt(i);
- char cc[5];
- MakeFourCCString(key, cc);
- const typed_data &item = mInternalData->mItems.valueAt(i);
- ALOGI("%s: %s", cc, item.asString(true /* verbose */).string());
- }
-}
-
-status_t MetaData::writeToParcel(Parcel &parcel) {
- status_t ret;
- size_t numItems = mInternalData->mItems.size();
- ret = parcel.writeUint32(uint32_t(numItems));
- if (ret) {
- return ret;
- }
- for (size_t i = 0; i < numItems; i++) {
- int32_t key = mInternalData->mItems.keyAt(i);
- const typed_data &item = mInternalData->mItems.valueAt(i);
- uint32_t type;
- const void *data;
- size_t size;
- item.getData(&type, &data, &size);
- ret = parcel.writeInt32(key);
- if (ret) {
- return ret;
- }
- ret = parcel.writeUint32(type);
- if (ret) {
- return ret;
- }
- if (type == TYPE_NONE) {
- android::Parcel::WritableBlob blob;
- ret = parcel.writeUint32(static_cast<uint32_t>(size));
- if (ret) {
- return ret;
- }
- ret = parcel.writeBlob(size, false, &blob);
- if (ret) {
- return ret;
- }
- memcpy(blob.data(), data, size);
- blob.release();
- } else {
- ret = parcel.writeByteArray(size, (uint8_t*)data);
- if (ret) {
- return ret;
- }
- }
- }
- return OK;
-}
-
-status_t MetaData::updateFromParcel(const Parcel &parcel) {
- uint32_t numItems;
- if (parcel.readUint32(&numItems) == OK) {
-
- for (size_t i = 0; i < numItems; i++) {
- int32_t key;
- uint32_t type;
- uint32_t size;
- status_t ret = parcel.readInt32(&key);
- ret |= parcel.readUint32(&type);
- ret |= parcel.readUint32(&size);
- if (ret != OK) {
- break;
- }
- // copy data from Blob, which may be inline in Parcel storage,
- // then advance position
- if (type == TYPE_NONE) {
- android::Parcel::ReadableBlob blob;
- ret = parcel.readBlob(size, &blob);
- if (ret != OK) {
- break;
- }
- setData(key, type, blob.data(), size);
- blob.release();
- } else {
- // copy data directly from Parcel storage, then advance position
- setData(key, type, parcel.readInplace(size), size);
- }
- }
-
- return OK;
- }
- ALOGW("no metadata in parcel");
- return UNKNOWN_ERROR;
-}
-
-
/* static */
sp<MetaData> MetaData::createFromParcel(const Parcel &parcel) {
@@ -533,7 +53,5 @@
return meta;
}
-
-
} // namespace android
diff --git a/media/libmediaextractor/MetaDataBase.cpp b/media/libmediaextractor/MetaDataBase.cpp
new file mode 100644
index 0000000..bfea6f1
--- /dev/null
+++ b/media/libmediaextractor/MetaDataBase.cpp
@@ -0,0 +1,533 @@
+/*
+ * 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 "MetaDataBase"
+#include <inttypes.h>
+#include <binder/Parcel.h>
+#include <utils/KeyedVector.h>
+#include <utils/Log.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/MetaDataBase.h>
+
+namespace android {
+
+struct MetaDataBase::typed_data {
+ typed_data();
+ ~typed_data();
+
+ typed_data(const MetaDataBase::typed_data &);
+ typed_data &operator=(const MetaDataBase::typed_data &);
+
+ void clear();
+ void setData(uint32_t type, const void *data, size_t size);
+ void getData(uint32_t *type, const void **data, size_t *size) const;
+ // may include hexdump of binary data if verbose=true
+ String8 asString(bool verbose) const;
+
+private:
+ uint32_t mType;
+ size_t mSize;
+
+ union {
+ void *ext_data;
+ float reservoir;
+ } u;
+
+ bool usesReservoir() const {
+ return mSize <= sizeof(u.reservoir);
+ }
+
+ void *allocateStorage(size_t size);
+ void freeStorage();
+
+ void *storage() {
+ return usesReservoir() ? &u.reservoir : u.ext_data;
+ }
+
+ const void *storage() const {
+ return usesReservoir() ? &u.reservoir : u.ext_data;
+ }
+};
+
+struct MetaDataBase::Rect {
+ int32_t mLeft, mTop, mRight, mBottom;
+};
+
+
+struct MetaDataBase::MetaDataInternal {
+ KeyedVector<uint32_t, MetaDataBase::typed_data> mItems;
+};
+
+
+MetaDataBase::MetaDataBase()
+ : mInternalData(new MetaDataInternal()) {
+}
+
+MetaDataBase::MetaDataBase(const MetaDataBase &from)
+ : mInternalData(new MetaDataInternal()) {
+ mInternalData->mItems = from.mInternalData->mItems;
+}
+
+MetaDataBase& MetaDataBase::operator = (const MetaDataBase &rhs) {
+ this->mInternalData->mItems = rhs.mInternalData->mItems;
+ return *this;
+}
+
+MetaDataBase::~MetaDataBase() {
+ clear();
+ delete mInternalData;
+}
+
+void MetaDataBase::clear() {
+ mInternalData->mItems.clear();
+}
+
+bool MetaDataBase::remove(uint32_t key) {
+ ssize_t i = mInternalData->mItems.indexOfKey(key);
+
+ if (i < 0) {
+ return false;
+ }
+
+ mInternalData->mItems.removeItemsAt(i);
+
+ return true;
+}
+
+bool MetaDataBase::setCString(uint32_t key, const char *value) {
+ return setData(key, TYPE_C_STRING, value, strlen(value) + 1);
+}
+
+bool MetaDataBase::setInt32(uint32_t key, int32_t value) {
+ return setData(key, TYPE_INT32, &value, sizeof(value));
+}
+
+bool MetaDataBase::setInt64(uint32_t key, int64_t value) {
+ return setData(key, TYPE_INT64, &value, sizeof(value));
+}
+
+bool MetaDataBase::setFloat(uint32_t key, float value) {
+ return setData(key, TYPE_FLOAT, &value, sizeof(value));
+}
+
+bool MetaDataBase::setPointer(uint32_t key, void *value) {
+ return setData(key, TYPE_POINTER, &value, sizeof(value));
+}
+
+bool MetaDataBase::setRect(
+ uint32_t key,
+ int32_t left, int32_t top,
+ int32_t right, int32_t bottom) {
+ Rect r;
+ r.mLeft = left;
+ r.mTop = top;
+ r.mRight = right;
+ r.mBottom = bottom;
+
+ return setData(key, TYPE_RECT, &r, sizeof(r));
+}
+
+/**
+ * Note that the returned pointer becomes invalid when additional metadata is set.
+ */
+bool MetaDataBase::findCString(uint32_t key, const char **value) const {
+ uint32_t type;
+ const void *data;
+ size_t size;
+ if (!findData(key, &type, &data, &size) || type != TYPE_C_STRING) {
+ return false;
+ }
+
+ *value = (const char *)data;
+
+ return true;
+}
+
+bool MetaDataBase::findInt32(uint32_t key, int32_t *value) const {
+ uint32_t type = 0;
+ const void *data;
+ size_t size;
+ if (!findData(key, &type, &data, &size) || type != TYPE_INT32) {
+ return false;
+ }
+
+ CHECK_EQ(size, sizeof(*value));
+
+ *value = *(int32_t *)data;
+
+ return true;
+}
+
+bool MetaDataBase::findInt64(uint32_t key, int64_t *value) const {
+ uint32_t type = 0;
+ const void *data;
+ size_t size;
+ if (!findData(key, &type, &data, &size) || type != TYPE_INT64) {
+ return false;
+ }
+
+ CHECK_EQ(size, sizeof(*value));
+
+ *value = *(int64_t *)data;
+
+ return true;
+}
+
+bool MetaDataBase::findFloat(uint32_t key, float *value) const {
+ uint32_t type = 0;
+ const void *data;
+ size_t size;
+ if (!findData(key, &type, &data, &size) || type != TYPE_FLOAT) {
+ return false;
+ }
+
+ CHECK_EQ(size, sizeof(*value));
+
+ *value = *(float *)data;
+
+ return true;
+}
+
+bool MetaDataBase::findPointer(uint32_t key, void **value) const {
+ uint32_t type = 0;
+ const void *data;
+ size_t size;
+ if (!findData(key, &type, &data, &size) || type != TYPE_POINTER) {
+ return false;
+ }
+
+ CHECK_EQ(size, sizeof(*value));
+
+ *value = *(void **)data;
+
+ return true;
+}
+
+bool MetaDataBase::findRect(
+ uint32_t key,
+ int32_t *left, int32_t *top,
+ int32_t *right, int32_t *bottom) const {
+ uint32_t type = 0;
+ const void *data;
+ size_t size;
+ if (!findData(key, &type, &data, &size) || type != TYPE_RECT) {
+ return false;
+ }
+
+ CHECK_EQ(size, sizeof(Rect));
+
+ const Rect *r = (const Rect *)data;
+ *left = r->mLeft;
+ *top = r->mTop;
+ *right = r->mRight;
+ *bottom = r->mBottom;
+
+ return true;
+}
+
+bool MetaDataBase::setData(
+ uint32_t key, uint32_t type, const void *data, size_t size) {
+ bool overwrote_existing = true;
+
+ ssize_t i = mInternalData->mItems.indexOfKey(key);
+ if (i < 0) {
+ typed_data item;
+ i = mInternalData->mItems.add(key, item);
+
+ overwrote_existing = false;
+ }
+
+ typed_data &item = mInternalData->mItems.editValueAt(i);
+
+ item.setData(type, data, size);
+
+ return overwrote_existing;
+}
+
+bool MetaDataBase::findData(uint32_t key, uint32_t *type,
+ const void **data, size_t *size) const {
+ ssize_t i = mInternalData->mItems.indexOfKey(key);
+
+ if (i < 0) {
+ return false;
+ }
+
+ const typed_data &item = mInternalData->mItems.valueAt(i);
+
+ item.getData(type, data, size);
+
+ return true;
+}
+
+bool MetaDataBase::hasData(uint32_t key) const {
+ ssize_t i = mInternalData->mItems.indexOfKey(key);
+
+ if (i < 0) {
+ return false;
+ }
+
+ return true;
+}
+
+MetaDataBase::typed_data::typed_data()
+ : mType(0),
+ mSize(0) {
+}
+
+MetaDataBase::typed_data::~typed_data() {
+ clear();
+}
+
+MetaDataBase::typed_data::typed_data(const typed_data &from)
+ : mType(from.mType),
+ mSize(0) {
+
+ void *dst = allocateStorage(from.mSize);
+ if (dst) {
+ memcpy(dst, from.storage(), mSize);
+ }
+}
+
+MetaDataBase::typed_data &MetaDataBase::typed_data::operator=(
+ const MetaDataBase::typed_data &from) {
+ if (this != &from) {
+ clear();
+ mType = from.mType;
+ void *dst = allocateStorage(from.mSize);
+ if (dst) {
+ memcpy(dst, from.storage(), mSize);
+ }
+ }
+
+ return *this;
+}
+
+void MetaDataBase::typed_data::clear() {
+ freeStorage();
+
+ mType = 0;
+}
+
+void MetaDataBase::typed_data::setData(
+ uint32_t type, const void *data, size_t size) {
+ clear();
+
+ mType = type;
+
+ void *dst = allocateStorage(size);
+ if (dst) {
+ memcpy(dst, data, size);
+ }
+}
+
+void MetaDataBase::typed_data::getData(
+ uint32_t *type, const void **data, size_t *size) const {
+ *type = mType;
+ *size = mSize;
+ *data = storage();
+}
+
+void *MetaDataBase::typed_data::allocateStorage(size_t size) {
+ mSize = size;
+
+ if (usesReservoir()) {
+ return &u.reservoir;
+ }
+
+ u.ext_data = malloc(mSize);
+ if (u.ext_data == NULL) {
+ ALOGE("Couldn't allocate %zu bytes for item", size);
+ mSize = 0;
+ }
+ return u.ext_data;
+}
+
+void MetaDataBase::typed_data::freeStorage() {
+ if (!usesReservoir()) {
+ if (u.ext_data) {
+ free(u.ext_data);
+ u.ext_data = NULL;
+ }
+ }
+
+ mSize = 0;
+}
+
+String8 MetaDataBase::typed_data::asString(bool verbose) const {
+ String8 out;
+ const void *data = storage();
+ switch(mType) {
+ case TYPE_NONE:
+ out = String8::format("no type, size %zu)", mSize);
+ break;
+ case TYPE_C_STRING:
+ out = String8::format("(char*) %s", (const char *)data);
+ break;
+ case TYPE_INT32:
+ out = String8::format("(int32_t) %d", *(int32_t *)data);
+ break;
+ case TYPE_INT64:
+ out = String8::format("(int64_t) %" PRId64, *(int64_t *)data);
+ break;
+ case TYPE_FLOAT:
+ out = String8::format("(float) %f", *(float *)data);
+ break;
+ case TYPE_POINTER:
+ out = String8::format("(void*) %p", *(void **)data);
+ break;
+ case TYPE_RECT:
+ {
+ const Rect *r = (const Rect *)data;
+ out = String8::format("Rect(%d, %d, %d, %d)",
+ r->mLeft, r->mTop, r->mRight, r->mBottom);
+ break;
+ }
+
+ default:
+ out = String8::format("(unknown type %d, size %zu)", mType, mSize);
+ if (verbose && mSize <= 48) { // if it's less than three lines of hex data, dump it
+ AString foo;
+ hexdump(data, mSize, 0, &foo);
+ out.append("\n");
+ out.append(foo.c_str());
+ }
+ break;
+ }
+ return out;
+}
+
+static void MakeFourCCString(uint32_t x, char *s) {
+ s[0] = x >> 24;
+ s[1] = (x >> 16) & 0xff;
+ s[2] = (x >> 8) & 0xff;
+ s[3] = x & 0xff;
+ s[4] = '\0';
+}
+
+String8 MetaDataBase::toString() const {
+ String8 s;
+ for (int i = mInternalData->mItems.size(); --i >= 0;) {
+ int32_t key = mInternalData->mItems.keyAt(i);
+ char cc[5];
+ MakeFourCCString(key, cc);
+ const typed_data &item = mInternalData->mItems.valueAt(i);
+ s.appendFormat("%s: %s", cc, item.asString(false).string());
+ if (i != 0) {
+ s.append(", ");
+ }
+ }
+ return s;
+}
+
+void MetaDataBase::dumpToLog() const {
+ for (int i = mInternalData->mItems.size(); --i >= 0;) {
+ int32_t key = mInternalData->mItems.keyAt(i);
+ char cc[5];
+ MakeFourCCString(key, cc);
+ const typed_data &item = mInternalData->mItems.valueAt(i);
+ ALOGI("%s: %s", cc, item.asString(true /* verbose */).string());
+ }
+}
+
+status_t MetaDataBase::writeToParcel(Parcel &parcel) {
+ status_t ret;
+ size_t numItems = mInternalData->mItems.size();
+ ret = parcel.writeUint32(uint32_t(numItems));
+ if (ret) {
+ return ret;
+ }
+ for (size_t i = 0; i < numItems; i++) {
+ int32_t key = mInternalData->mItems.keyAt(i);
+ const typed_data &item = mInternalData->mItems.valueAt(i);
+ uint32_t type;
+ const void *data;
+ size_t size;
+ item.getData(&type, &data, &size);
+ ret = parcel.writeInt32(key);
+ if (ret) {
+ return ret;
+ }
+ ret = parcel.writeUint32(type);
+ if (ret) {
+ return ret;
+ }
+ if (type == TYPE_NONE) {
+ android::Parcel::WritableBlob blob;
+ ret = parcel.writeUint32(static_cast<uint32_t>(size));
+ if (ret) {
+ return ret;
+ }
+ ret = parcel.writeBlob(size, false, &blob);
+ if (ret) {
+ return ret;
+ }
+ memcpy(blob.data(), data, size);
+ blob.release();
+ } else {
+ ret = parcel.writeByteArray(size, (uint8_t*)data);
+ if (ret) {
+ return ret;
+ }
+ }
+ }
+ return OK;
+}
+
+status_t MetaDataBase::updateFromParcel(const Parcel &parcel) {
+ uint32_t numItems;
+ if (parcel.readUint32(&numItems) == OK) {
+
+ for (size_t i = 0; i < numItems; i++) {
+ int32_t key;
+ uint32_t type;
+ uint32_t size;
+ status_t ret = parcel.readInt32(&key);
+ ret |= parcel.readUint32(&type);
+ ret |= parcel.readUint32(&size);
+ if (ret != OK) {
+ break;
+ }
+ // copy data from Blob, which may be inline in Parcel storage,
+ // then advance position
+ if (type == TYPE_NONE) {
+ android::Parcel::ReadableBlob blob;
+ ret = parcel.readBlob(size, &blob);
+ if (ret != OK) {
+ break;
+ }
+ setData(key, type, blob.data(), size);
+ blob.release();
+ } else {
+ // copy data directly from Parcel storage, then advance position
+ setData(key, type, parcel.readInplace(size), size);
+ }
+ }
+
+ return OK;
+ }
+ ALOGW("no metadata in parcel");
+ return UNKNOWN_ERROR;
+}
+
+} // namespace android
+
diff --git a/media/libmediaextractor/VorbisComment.cpp b/media/libmediaextractor/VorbisComment.cpp
new file mode 100644
index 0000000..fabaf51
--- /dev/null
+++ b/media/libmediaextractor/VorbisComment.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2018 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 "VorbisComment"
+#include <utils/Log.h>
+
+#include "media/VorbisComment.h"
+
+#include <media/stagefright/foundation/base64.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/ByteUtils.h>
+#include <media/stagefright/MetaDataBase.h>
+
+namespace android {
+
+static void extractAlbumArt(
+ MetaDataBase *fileMeta, const void *data, size_t size) {
+ ALOGV("extractAlbumArt from '%s'", (const char *)data);
+
+ sp<ABuffer> flacBuffer = decodeBase64(AString((const char *)data, size));
+ if (flacBuffer == NULL) {
+ ALOGE("malformed base64 encoded data.");
+ return;
+ }
+
+ size_t flacSize = flacBuffer->size();
+ uint8_t *flac = flacBuffer->data();
+ ALOGV("got flac of size %zu", flacSize);
+
+ uint32_t picType;
+ uint32_t typeLen;
+ uint32_t descLen;
+ uint32_t dataLen;
+ char type[128];
+
+ if (flacSize < 8) {
+ return;
+ }
+
+ picType = U32_AT(flac);
+
+ if (picType != 3) {
+ // This is not a front cover.
+ return;
+ }
+
+ typeLen = U32_AT(&flac[4]);
+ if (typeLen > sizeof(type) - 1) {
+ return;
+ }
+
+ // we've already checked above that flacSize >= 8
+ if (flacSize - 8 < typeLen) {
+ return;
+ }
+
+ memcpy(type, &flac[8], typeLen);
+ type[typeLen] = '\0';
+
+ ALOGV("picType = %d, type = '%s'", picType, type);
+
+ if (!strcmp(type, "-->")) {
+ // This is not inline cover art, but an external url instead.
+ return;
+ }
+
+ if (flacSize < 32 || flacSize - 32 < typeLen) {
+ return;
+ }
+
+ descLen = U32_AT(&flac[8 + typeLen]);
+ if (flacSize - 32 - typeLen < descLen) {
+ return;
+ }
+
+ dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]);
+
+ // we've already checked above that (flacSize - 32 - typeLen - descLen) >= 0
+ if (flacSize - 32 - typeLen - descLen < dataLen) {
+ return;
+ }
+
+ ALOGV("got image data, %zu trailing bytes",
+ flacSize - 32 - typeLen - descLen - dataLen);
+
+ fileMeta->setData(
+ kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen);
+
+ fileMeta->setCString(kKeyAlbumArtMIME, type);
+}
+
+void parseVorbisComment(
+ MetaDataBase *fileMeta, const char *comment, size_t commentLength)
+{
+ struct {
+ const char *const mTag;
+ uint32_t mKey;
+ } kMap[] = {
+ { "TITLE", kKeyTitle },
+ { "ARTIST", kKeyArtist },
+ { "ALBUMARTIST", kKeyAlbumArtist },
+ { "ALBUM ARTIST", kKeyAlbumArtist },
+ { "COMPILATION", kKeyCompilation },
+ { "ALBUM", kKeyAlbum },
+ { "COMPOSER", kKeyComposer },
+ { "GENRE", kKeyGenre },
+ { "AUTHOR", kKeyAuthor },
+ { "TRACKNUMBER", kKeyCDTrackNumber },
+ { "DISCNUMBER", kKeyDiscNumber },
+ { "DATE", kKeyDate },
+ { "YEAR", kKeyYear },
+ { "LYRICIST", kKeyWriter },
+ { "METADATA_BLOCK_PICTURE", kKeyAlbumArt },
+ { "ANDROID_LOOP", kKeyAutoLoop },
+ };
+
+ for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) {
+ size_t tagLen = strlen(kMap[j].mTag);
+ if (!strncasecmp(kMap[j].mTag, comment, tagLen)
+ && comment[tagLen] == '=') {
+ if (kMap[j].mKey == kKeyAlbumArt) {
+ extractAlbumArt(
+ fileMeta,
+ &comment[tagLen + 1],
+ commentLength - tagLen - 1);
+ } else if (kMap[j].mKey == kKeyAutoLoop) {
+ if (!strcasecmp(&comment[tagLen + 1], "true")) {
+ fileMeta->setInt32(kKeyAutoLoop, true);
+ }
+ } else {
+ fileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]);
+ }
+ }
+ }
+
+}
+
+} // namespace android
diff --git a/media/libmediaextractor/include/media/DataSource.h b/media/libmediaextractor/include/media/DataSource.h
index a066183..1ae2e21 100644
--- a/media/libmediaextractor/include/media/DataSource.h
+++ b/media/libmediaextractor/include/media/DataSource.h
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <media/stagefright/MediaErrors.h>
#include <media/DataSourceBase.h>
+#include <media/IDataSource.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/threads.h>
@@ -35,6 +36,11 @@
public:
DataSource() {}
+ // returns a pointer to IDataSource if it is wrapped.
+ virtual sp<IDataSource> getIDataSource() const {
+ return nullptr;
+ }
+
protected:
virtual ~DataSource() {}
diff --git a/media/libmediaextractor/include/media/MediaExtractor.h b/media/libmediaextractor/include/media/MediaExtractor.h
index c329903..4ba98da 100644
--- a/media/libmediaextractor/include/media/MediaExtractor.h
+++ b/media/libmediaextractor/include/media/MediaExtractor.h
@@ -28,8 +28,8 @@
namespace android {
class DataSourceBase;
-class MetaData;
-struct MediaSourceBase;
+class MetaDataBase;
+struct MediaTrack;
class ExtractorAllocTracker {
@@ -49,17 +49,18 @@
public:
virtual ~MediaExtractor();
virtual size_t countTracks() = 0;
- virtual MediaSourceBase *getTrack(size_t index) = 0;
+ virtual MediaTrack *getTrack(size_t index) = 0;
enum GetTrackMetaDataFlags {
kIncludeExtensiveMetaData = 1
};
- virtual sp<MetaData> getTrackMetaData(
+ virtual status_t getTrackMetaData(
+ MetaDataBase& meta,
size_t index, uint32_t flags = 0) = 0;
// Return container specific meta-data. The default implementation
// returns an empty metadata object.
- virtual sp<MetaData> getMetaData();
+ virtual status_t getMetaData(MetaDataBase& meta) = 0;
enum Flags {
CAN_SEEK_BACKWARD = 1, // the "seek 10secs back button"
diff --git a/media/libmediaextractor/include/media/MediaSource.h b/media/libmediaextractor/include/media/MediaSource.h
index 45070d6..73c4703 100644
--- a/media/libmediaextractor/include/media/MediaSource.h
+++ b/media/libmediaextractor/include/media/MediaSource.h
@@ -1,4 +1,5 @@
/*
+
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -24,15 +25,71 @@
#include <media/stagefright/MetaData.h>
#include <utils/RefBase.h>
-#include "media/MediaSourceBase.h"
+#include <media/MediaTrack.h>
namespace android {
class MediaBuffer;
-struct MediaSource : public MediaSourceBase, public virtual RefBase {
+struct MediaSource : public virtual RefBase {
MediaSource();
+ // To be called before any other methods on this object, except
+ // getFormat().
+ virtual status_t start(MetaData *params = NULL) = 0;
+
+ // Any blocking read call returns immediately with a result of NO_INIT.
+ // It is an error to call any methods other than start after this call
+ // returns. Any buffers the object may be holding onto at the time of
+ // the stop() call are released.
+ // Also, it is imperative that any buffers output by this object and
+ // held onto by callers be released before a call to stop() !!!
+ virtual status_t stop() = 0;
+
+ // Returns the format of the data output by this media source.
+ virtual sp<MetaData> getFormat() = 0;
+
+ // Options that modify read() behaviour. The default is to
+ // a) not request a seek
+ // b) not be late, i.e. lateness_us = 0
+ typedef MediaTrack::ReadOptions ReadOptions;
+
+ // Returns a new buffer of data. Call blocks until a
+ // buffer is available, an error is encountered of the end of the stream
+ // is reached.
+ // End of stream is signalled by a result of ERROR_END_OF_STREAM.
+ // A result of INFO_FORMAT_CHANGED indicates that the format of this
+ // MediaSource has changed mid-stream, the client can continue reading
+ // but should be prepared for buffers of the new configuration.
+ virtual status_t read(
+ MediaBufferBase **buffer, const ReadOptions *options = NULL) = 0;
+
+ // Causes this source to suspend pulling data from its upstream source
+ // until a subsequent read-with-seek. This is currently not supported
+ // as such by any source. E.g. MediaCodecSource does not suspend its
+ // upstream source, and instead discard upstream data while paused.
+ virtual status_t pause() {
+ return ERROR_UNSUPPORTED;
+ }
+
+ // The consumer of this media source requests the source stops sending
+ // buffers with timestamp larger than or equal to stopTimeUs. stopTimeUs
+ // must be in the same time base as the startTime passed in start(). If
+ // source does not support this request, ERROR_UNSUPPORTED will be returned.
+ // If stopTimeUs is invalid, BAD_VALUE will be returned. This could be
+ // called at any time even before source starts and it could be called
+ // multiple times. Setting stopTimeUs to be -1 will effectively cancel the stopTimeUs
+ // set previously. If stopTimeUs is larger than or equal to last buffer's timestamp,
+ // source will start to drop buffer when it gets a buffer with timestamp larger
+ // than or equal to stopTimeUs. If stopTimeUs is smaller than or equal to last
+ // buffer's timestamp, source will drop all the incoming buffers immediately.
+ // After setting stopTimeUs, source may still stop sending buffers with timestamp
+ // less than stopTimeUs if it is stopped by the consumer.
+ virtual status_t setStopTimeUs(int64_t /* stopTimeUs */) {
+ return ERROR_UNSUPPORTED;
+ }
+
+protected:
virtual ~MediaSource();
private:
diff --git a/media/libmediaextractor/include/media/MediaSourceBase.h b/media/libmediaextractor/include/media/MediaTrack.h
similarity index 65%
rename from media/libmediaextractor/include/media/MediaSourceBase.h
rename to media/libmediaextractor/include/media/MediaTrack.h
index ab56613..adea61a 100644
--- a/media/libmediaextractor/include/media/MediaSourceBase.h
+++ b/media/libmediaextractor/include/media/MediaTrack.h
@@ -42,14 +42,14 @@
}
};
-struct MediaSourceBase
+struct MediaTrack
// : public SourceBaseAllocTracker
{
- MediaSourceBase();
+ MediaTrack();
// To be called before any other methods on this object, except
// getFormat().
- virtual status_t start(MetaData *params = NULL) = 0;
+ virtual status_t start(MetaDataBase *params = NULL) = 0;
// Any blocking read call returns immediately with a result of NO_INIT.
// It is an error to call any methods other than start after this call
@@ -59,8 +59,8 @@
// held onto by callers be released before a call to stop() !!!
virtual status_t stop() = 0;
- // Returns the format of the data output by this media source.
- virtual sp<MetaData> getFormat() = 0;
+ // Returns the format of the data output by this media track.
+ virtual status_t getFormat(MetaDataBase& format) = 0;
// Options that modify read() behaviour. The default is to
// a) not request a seek
@@ -113,36 +113,11 @@
virtual status_t read(
MediaBufferBase **buffer, const ReadOptions *options = NULL) = 0;
- // Causes this source to suspend pulling data from its upstream source
- // until a subsequent read-with-seek. This is currently not supported
- // as such by any source. E.g. MediaCodecSource does not suspend its
- // upstream source, and instead discard upstream data while paused.
- virtual status_t pause() {
- return ERROR_UNSUPPORTED;
- }
-
- // The consumer of this media source requests the source stops sending
- // buffers with timestamp larger than or equal to stopTimeUs. stopTimeUs
- // must be in the same time base as the startTime passed in start(). If
- // source does not support this request, ERROR_UNSUPPORTED will be returned.
- // If stopTimeUs is invalid, BAD_VALUE will be returned. This could be
- // called at any time even before source starts and it could be called
- // multiple times. Setting stopTimeUs to be -1 will effectively cancel the stopTimeUs
- // set previously. If stopTimeUs is larger than or equal to last buffer's timestamp,
- // source will start to drop buffer when it gets a buffer with timestamp larger
- // than or equal to stopTimeUs. If stopTimeUs is smaller than or equal to last
- // buffer's timestamp, source will drop all the incoming buffers immediately.
- // After setting stopTimeUs, source may still stop sending buffers with timestamp
- // less than stopTimeUs if it is stopped by the consumer.
- virtual status_t setStopTimeUs(int64_t /* stopTimeUs */) {
- return ERROR_UNSUPPORTED;
- }
-
- virtual ~MediaSourceBase();
+ virtual ~MediaTrack();
private:
- MediaSourceBase(const MediaSourceBase &);
- MediaSourceBase &operator=(const MediaSourceBase &);
+ MediaTrack(const MediaTrack &);
+ MediaTrack &operator=(const MediaTrack &);
};
} // namespace android
diff --git a/media/libmediaextractor/include/media/VorbisComment.h b/media/libmediaextractor/include/media/VorbisComment.h
new file mode 100644
index 0000000..8ba3295
--- /dev/null
+++ b/media/libmediaextractor/include/media/VorbisComment.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef VORBIS_COMMENT_H_
+#define VORBIS_COMMENT_H_
+
+namespace android {
+
+class MetaDataBase;
+
+void parseVorbisComment(
+ MetaDataBase *fileMeta, const char *comment, size_t commentLength);
+
+} // namespace android
+
+#endif // VORBIS_COMMENT_H_
diff --git a/media/libmediaextractor/include/media/stagefright/MediaBuffer.h b/media/libmediaextractor/include/media/stagefright/MediaBuffer.h
index 85b4521..f944d51 100644
--- a/media/libmediaextractor/include/media/stagefright/MediaBuffer.h
+++ b/media/libmediaextractor/include/media/stagefright/MediaBuffer.h
@@ -33,7 +33,7 @@
struct ABuffer;
class MediaBuffer;
class MediaBufferObserver;
-class MetaData;
+class MetaDataBase;
class MediaBuffer : public MediaBufferBase {
public:
@@ -73,7 +73,7 @@
virtual void set_range(size_t offset, size_t length);
- virtual sp<MetaData> meta_data();
+ MetaDataBase& meta_data();
// Clears meta data and resets the range to the full extent.
virtual void reset();
@@ -154,7 +154,7 @@
bool mOwnsData;
- sp<MetaData> mMetaData;
+ MetaDataBase* mMetaData;
MediaBuffer *mOriginal;
diff --git a/media/libmediaextractor/include/media/stagefright/MediaBufferBase.h b/media/libmediaextractor/include/media/stagefright/MediaBufferBase.h
index 81dd7d9..6c8d94a 100644
--- a/media/libmediaextractor/include/media/stagefright/MediaBufferBase.h
+++ b/media/libmediaextractor/include/media/stagefright/MediaBufferBase.h
@@ -18,12 +18,10 @@
#define MEDIA_BUFFER_BASE_H_
-#include <utils/RefBase.h>
-
namespace android {
class MediaBufferBase;
-class MetaData;
+class MetaDataBase;
class MediaBufferObserver {
public:
@@ -61,7 +59,7 @@
virtual void set_range(size_t offset, size_t length) = 0;
- virtual sp<MetaData> meta_data() = 0;
+ virtual MetaDataBase& meta_data() = 0;
// Clears meta data and resets the range to the full extent.
virtual void reset() = 0;
diff --git a/media/libmediaextractor/include/media/stagefright/MetaData.h b/media/libmediaextractor/include/media/stagefright/MetaData.h
index 7562a72..f625358 100644
--- a/media/libmediaextractor/include/media/stagefright/MetaData.h
+++ b/media/libmediaextractor/include/media/stagefright/MetaData.h
@@ -24,275 +24,24 @@
#include <utils/RefBase.h>
#include <utils/String8.h>
+#include <media/stagefright/MetaDataBase.h>
namespace android {
-class Parcel;
-
-// The following keys map to int32_t data unless indicated otherwise.
-enum {
- kKeyMIMEType = 'mime', // cstring
- kKeyWidth = 'widt', // int32_t, image pixel
- kKeyHeight = 'heig', // int32_t, image pixel
- kKeyDisplayWidth = 'dWid', // int32_t, display/presentation
- kKeyDisplayHeight = 'dHgt', // int32_t, display/presentation
- kKeySARWidth = 'sarW', // int32_t, sampleAspectRatio width
- kKeySARHeight = 'sarH', // int32_t, sampleAspectRatio height
- kKeyThumbnailWidth = 'thbW', // int32_t, thumbnail width
- kKeyThumbnailHeight = 'thbH', // int32_t, thumbnail height
-
- // a rectangle, if absent assumed to be (0, 0, width - 1, height - 1)
- kKeyCropRect = 'crop',
-
- kKeyRotation = 'rotA', // int32_t (angle in degrees)
- kKeyIFramesInterval = 'ifiv', // int32_t
- kKeyStride = 'strd', // int32_t
- kKeySliceHeight = 'slht', // int32_t
- kKeyChannelCount = '#chn', // int32_t
- kKeyChannelMask = 'chnm', // int32_t
- kKeySampleRate = 'srte', // int32_t (audio sampling rate Hz)
- kKeyPcmEncoding = 'PCMe', // int32_t (audio encoding enum)
- kKeyFrameRate = 'frmR', // int32_t (video frame rate fps)
- kKeyBitRate = 'brte', // int32_t (bps)
- kKeyMaxBitRate = 'mxBr', // int32_t (bps)
- kKeyStreamHeader = 'stHd', // raw data
- kKeyESDS = 'esds', // raw data
- kKeyAACProfile = 'aacp', // int32_t
- kKeyAVCC = 'avcc', // raw data
- kKeyHVCC = 'hvcc', // raw data
- kKeyThumbnailHVCC = 'thvc', // raw data
- kKeyD263 = 'd263', // raw data
- kKeyVorbisInfo = 'vinf', // raw data
- kKeyVorbisBooks = 'vboo', // raw data
- kKeyOpusHeader = 'ohdr', // raw data
- kKeyOpusCodecDelay = 'ocod', // uint64_t (codec delay in ns)
- kKeyOpusSeekPreRoll = 'ospr', // uint64_t (seek preroll in ns)
- kKeyFlacMetadata = 'flMd', // raw data
- kKeyVp9CodecPrivate = 'vp9p', // raw data (vp9 csd information)
- kKeyWantsNALFragments = 'NALf',
- kKeyIsSyncFrame = 'sync', // int32_t (bool)
- kKeyIsCodecConfig = 'conf', // int32_t (bool)
- kKeyTime = 'time', // int64_t (usecs)
- kKeyDecodingTime = 'decT', // int64_t (decoding timestamp in usecs)
- kKeyNTPTime = 'ntpT', // uint64_t (ntp-timestamp)
- kKeyTargetTime = 'tarT', // int64_t (usecs)
- kKeyDriftTime = 'dftT', // int64_t (usecs)
- kKeyAnchorTime = 'ancT', // int64_t (usecs)
- kKeyDuration = 'dura', // int64_t (usecs)
- kKeyPixelFormat = 'pixf', // int32_t
- kKeyColorFormat = 'colf', // int32_t
- kKeyColorSpace = 'cols', // int32_t
- kKeyPlatformPrivate = 'priv', // pointer
- kKeyDecoderComponent = 'decC', // cstring
- kKeyBufferID = 'bfID',
- kKeyMaxInputSize = 'inpS',
- kKeyMaxWidth = 'maxW',
- kKeyMaxHeight = 'maxH',
- kKeyThumbnailTime = 'thbT', // int64_t (usecs)
- kKeyTrackID = 'trID',
- kKeyIsDRM = 'idrm', // int32_t (bool)
- kKeyEncoderDelay = 'encd', // int32_t (frames)
- kKeyEncoderPadding = 'encp', // int32_t (frames)
-
- kKeyAlbum = 'albu', // cstring
- kKeyArtist = 'arti', // cstring
- kKeyAlbumArtist = 'aart', // cstring
- kKeyComposer = 'comp', // cstring
- kKeyGenre = 'genr', // cstring
- kKeyTitle = 'titl', // cstring
- kKeyYear = 'year', // cstring
- kKeyAlbumArt = 'albA', // compressed image data
- kKeyAlbumArtMIME = 'alAM', // cstring
- kKeyAuthor = 'auth', // cstring
- kKeyCDTrackNumber = 'cdtr', // cstring
- kKeyDiscNumber = 'dnum', // cstring
- kKeyDate = 'date', // cstring
- kKeyWriter = 'writ', // cstring
- kKeyCompilation = 'cpil', // cstring
- kKeyLocation = 'loc ', // cstring
- kKeyTimeScale = 'tmsl', // int32_t
- kKeyCaptureFramerate = 'capF', // float (capture fps)
-
- // video profile and level
- kKeyVideoProfile = 'vprf', // int32_t
- kKeyVideoLevel = 'vlev', // int32_t
-
- // Set this key to enable authoring files in 64-bit offset
- kKey64BitFileOffset = 'fobt', // int32_t (bool)
- kKey2ByteNalLength = '2NAL', // int32_t (bool)
-
- // Identify the file output format for authoring
- // Please see <media/mediarecorder.h> for the supported
- // file output formats.
- kKeyFileType = 'ftyp', // int32_t
-
- // Track authoring progress status
- // kKeyTrackTimeStatus is used to track progress in elapsed time
- kKeyTrackTimeStatus = 'tktm', // int64_t
-
- kKeyRealTimeRecording = 'rtrc', // bool (int32_t)
- kKeyNumBuffers = 'nbbf', // int32_t
-
- // Ogg files can be tagged to be automatically looping...
- kKeyAutoLoop = 'autL', // bool (int32_t)
-
- kKeyValidSamples = 'valD', // int32_t
-
- kKeyIsUnreadable = 'unre', // bool (int32_t)
-
- // An indication that a video buffer has been rendered.
- kKeyRendered = 'rend', // bool (int32_t)
-
- // The language code for this media
- kKeyMediaLanguage = 'lang', // cstring
-
- // To store the timed text format data
- kKeyTextFormatData = 'text', // raw data
-
- kKeyIsADTS = 'adts', // bool (int32_t)
- kKeyAACAOT = 'aaot', // int32_t
-
- // If a MediaBuffer's data represents (at least partially) encrypted
- // data, the following fields aid in decryption.
- // The data can be thought of as pairs of plain and encrypted data
- // fragments, i.e. plain and encrypted data alternate.
- // The first fragment is by convention plain data (if that's not the
- // case, simply specify plain fragment size of 0).
- // kKeyEncryptedSizes and kKeyPlainSizes each map to an array of
- // size_t values. The sum total of all size_t values of both arrays
- // must equal the amount of data (i.e. MediaBuffer's range_length()).
- // If both arrays are present, they must be of the same size.
- // If only encrypted sizes are present it is assumed that all
- // plain sizes are 0, i.e. all fragments are encrypted.
- // To programmatically set these array, use the MetaData::setData API, i.e.
- // const size_t encSizes[];
- // meta->setData(
- // kKeyEncryptedSizes, 0 /* type */, encSizes, sizeof(encSizes));
- // A plain sizes array by itself makes no sense.
- kKeyEncryptedSizes = 'encr', // size_t[]
- kKeyPlainSizes = 'plai', // size_t[]
- kKeyCryptoKey = 'cryK', // uint8_t[16]
- kKeyCryptoIV = 'cryI', // uint8_t[16]
- kKeyCryptoMode = 'cryM', // int32_t
-
- kKeyCryptoDefaultIVSize = 'cryS', // int32_t
-
- kKeyPssh = 'pssh', // raw data
- kKeyCASystemID = 'caid', // int32_t
- kKeyCASessionID = 'seid', // raw data
-
- // Please see MediaFormat.KEY_IS_AUTOSELECT.
- kKeyTrackIsAutoselect = 'auto', // bool (int32_t)
- // Please see MediaFormat.KEY_IS_DEFAULT.
- kKeyTrackIsDefault = 'dflt', // bool (int32_t)
- // Similar to MediaFormat.KEY_IS_FORCED_SUBTITLE but pertains to av tracks as well.
- kKeyTrackIsForced = 'frcd', // bool (int32_t)
-
- // H264 supplemental enhancement information offsets/sizes
- kKeySEI = 'sei ', // raw data
-
- // MPEG user data offsets
- kKeyMpegUserData = 'mpud', // size_t[]
-
- // Size of NALU length in mkv/mp4
- kKeyNalLengthSize = 'nals', // int32_t
-
- // HDR related
- kKeyHdrStaticInfo = 'hdrS', // HDRStaticInfo
-
- // color aspects
- kKeyColorRange = 'cRng', // int32_t, color range, value defined by ColorAspects.Range
- kKeyColorPrimaries = 'cPrm', // int32_t,
- // color Primaries, value defined by ColorAspects.Primaries
- kKeyTransferFunction = 'tFun', // int32_t,
- // transfer Function, value defined by ColorAspects.Transfer.
- kKeyColorMatrix = 'cMtx', // int32_t,
- // color Matrix, value defined by ColorAspects.MatrixCoeffs.
- kKeyTemporalLayerId = 'iLyr', // int32_t, temporal layer-id. 0-based (0 => base layer)
- kKeyTemporalLayerCount = 'cLyr', // int32_t, number of temporal layers encoded
-
- kKeyGridWidth = 'grdW', // int32_t, HEIF grid width
- kKeyGridHeight = 'grdH', // int32_t, HEIF grid height
- kKeyGridRows = 'grdR', // int32_t, HEIF grid rows
- kKeyGridCols = 'grdC', // int32_t, HEIF grid columns
- kKeyIccProfile = 'prof', // raw data, ICC prifile data
- kKeyIsPrimaryImage = 'prim', // bool (int32_t), image track is the primary image
- kKeyFrameCount = 'nfrm', // int32_t, total number of frame in video track
-};
-
-enum {
- kTypeESDS = 'esds',
- kTypeAVCC = 'avcc',
- kTypeHVCC = 'hvcc',
- kTypeD263 = 'd263',
-};
-
-class MetaData final : public RefBase {
+class MetaData final : public MetaDataBase, public RefBase {
public:
MetaData();
MetaData(const MetaData &from);
-
- enum Type {
- TYPE_NONE = 'none',
- TYPE_C_STRING = 'cstr',
- TYPE_INT32 = 'in32',
- TYPE_INT64 = 'in64',
- TYPE_FLOAT = 'floa',
- TYPE_POINTER = 'ptr ',
- TYPE_RECT = 'rect',
- };
-
- void clear();
- bool remove(uint32_t key);
-
- bool setCString(uint32_t key, const char *value);
- bool setInt32(uint32_t key, int32_t value);
- bool setInt64(uint32_t key, int64_t value);
- bool setFloat(uint32_t key, float value);
- bool setPointer(uint32_t key, void *value);
-
- bool setRect(
- uint32_t key,
- int32_t left, int32_t top,
- int32_t right, int32_t bottom);
-
- bool findCString(uint32_t key, const char **value) const;
- bool findInt32(uint32_t key, int32_t *value) const;
- bool findInt64(uint32_t key, int64_t *value) const;
- bool findFloat(uint32_t key, float *value) const;
- bool findPointer(uint32_t key, void **value) const;
-
- bool findRect(
- uint32_t key,
- int32_t *left, int32_t *top,
- int32_t *right, int32_t *bottom) const;
-
- bool setData(uint32_t key, uint32_t type, const void *data, size_t size);
-
- bool findData(uint32_t key, uint32_t *type,
- const void **data, size_t *size) const;
-
- bool hasData(uint32_t key) const;
-
- String8 toString() const;
- void dumpToLog() const;
+ MetaData(const MetaDataBase &from);
protected:
virtual ~MetaData();
private:
- friend class BpMediaSource;
friend class BnMediaSource;
+ friend class BpMediaSource;
friend class BpMediaExtractor;
- friend class BnMediaExtractor;
-
- status_t writeToParcel(Parcel &parcel);
- status_t updateFromParcel(const Parcel &parcel);
static sp<MetaData> createFromParcel(const Parcel &parcel);
- struct typed_data;
- struct Rect;
- struct MetaDataInternal;
- MetaDataInternal *mInternalData;
};
} // namespace android
diff --git a/media/libmediaextractor/include/media/stagefright/MetaDataBase.h b/media/libmediaextractor/include/media/stagefright/MetaDataBase.h
new file mode 100644
index 0000000..6010af4
--- /dev/null
+++ b/media/libmediaextractor/include/media/stagefright/MetaDataBase.h
@@ -0,0 +1,301 @@
+/*
+ * 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.
+ */
+
+#ifndef META_DATA_BASE_H_
+
+#define META_DATA_BASE_H_
+
+#include <sys/types.h>
+
+#include <stdint.h>
+
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+
+namespace android {
+
+// The following keys map to int32_t data unless indicated otherwise.
+enum {
+ kKeyMIMEType = 'mime', // cstring
+ kKeyWidth = 'widt', // int32_t, image pixel
+ kKeyHeight = 'heig', // int32_t, image pixel
+ kKeyDisplayWidth = 'dWid', // int32_t, display/presentation
+ kKeyDisplayHeight = 'dHgt', // int32_t, display/presentation
+ kKeySARWidth = 'sarW', // int32_t, sampleAspectRatio width
+ kKeySARHeight = 'sarH', // int32_t, sampleAspectRatio height
+ kKeyThumbnailWidth = 'thbW', // int32_t, thumbnail width
+ kKeyThumbnailHeight = 'thbH', // int32_t, thumbnail height
+
+ // a rectangle, if absent assumed to be (0, 0, width - 1, height - 1)
+ kKeyCropRect = 'crop',
+
+ kKeyRotation = 'rotA', // int32_t (angle in degrees)
+ kKeyIFramesInterval = 'ifiv', // int32_t
+ kKeyStride = 'strd', // int32_t
+ kKeySliceHeight = 'slht', // int32_t
+ kKeyChannelCount = '#chn', // int32_t
+ kKeyChannelMask = 'chnm', // int32_t
+ kKeySampleRate = 'srte', // int32_t (audio sampling rate Hz)
+ kKeyPcmEncoding = 'PCMe', // int32_t (audio encoding enum)
+ kKeyFrameRate = 'frmR', // int32_t (video frame rate fps)
+ kKeyBitRate = 'brte', // int32_t (bps)
+ kKeyMaxBitRate = 'mxBr', // int32_t (bps)
+ kKeyStreamHeader = 'stHd', // raw data
+ kKeyESDS = 'esds', // raw data
+ kKeyAACProfile = 'aacp', // int32_t
+ kKeyAVCC = 'avcc', // raw data
+ kKeyHVCC = 'hvcc', // raw data
+ kKeyThumbnailHVCC = 'thvc', // raw data
+ kKeyD263 = 'd263', // raw data
+ kKeyVorbisInfo = 'vinf', // raw data
+ kKeyVorbisBooks = 'vboo', // raw data
+ kKeyOpusHeader = 'ohdr', // raw data
+ kKeyOpusCodecDelay = 'ocod', // uint64_t (codec delay in ns)
+ kKeyOpusSeekPreRoll = 'ospr', // uint64_t (seek preroll in ns)
+ kKeyFlacMetadata = 'flMd', // raw data
+ kKeyVp9CodecPrivate = 'vp9p', // raw data (vp9 csd information)
+ kKeyWantsNALFragments = 'NALf',
+ kKeyIsSyncFrame = 'sync', // int32_t (bool)
+ kKeyIsCodecConfig = 'conf', // int32_t (bool)
+ kKeyTime = 'time', // int64_t (usecs)
+ kKeyDecodingTime = 'decT', // int64_t (decoding timestamp in usecs)
+ kKeyNTPTime = 'ntpT', // uint64_t (ntp-timestamp)
+ kKeyTargetTime = 'tarT', // int64_t (usecs)
+ kKeyDriftTime = 'dftT', // int64_t (usecs)
+ kKeyAnchorTime = 'ancT', // int64_t (usecs)
+ kKeyDuration = 'dura', // int64_t (usecs)
+ kKeyPixelFormat = 'pixf', // int32_t
+ kKeyColorFormat = 'colf', // int32_t
+ kKeyColorSpace = 'cols', // int32_t
+ kKeyPlatformPrivate = 'priv', // pointer
+ kKeyDecoderComponent = 'decC', // cstring
+ kKeyBufferID = 'bfID',
+ kKeyMaxInputSize = 'inpS',
+ kKeyMaxWidth = 'maxW',
+ kKeyMaxHeight = 'maxH',
+ kKeyThumbnailTime = 'thbT', // int64_t (usecs)
+ kKeyTrackID = 'trID',
+ kKeyIsDRM = 'idrm', // int32_t (bool)
+ kKeyEncoderDelay = 'encd', // int32_t (frames)
+ kKeyEncoderPadding = 'encp', // int32_t (frames)
+
+ kKeyAlbum = 'albu', // cstring
+ kKeyArtist = 'arti', // cstring
+ kKeyAlbumArtist = 'aart', // cstring
+ kKeyComposer = 'comp', // cstring
+ kKeyGenre = 'genr', // cstring
+ kKeyTitle = 'titl', // cstring
+ kKeyYear = 'year', // cstring
+ kKeyAlbumArt = 'albA', // compressed image data
+ kKeyAlbumArtMIME = 'alAM', // cstring
+ kKeyAuthor = 'auth', // cstring
+ kKeyCDTrackNumber = 'cdtr', // cstring
+ kKeyDiscNumber = 'dnum', // cstring
+ kKeyDate = 'date', // cstring
+ kKeyWriter = 'writ', // cstring
+ kKeyCompilation = 'cpil', // cstring
+ kKeyLocation = 'loc ', // cstring
+ kKeyTimeScale = 'tmsl', // int32_t
+ kKeyCaptureFramerate = 'capF', // float (capture fps)
+
+ // video profile and level
+ kKeyVideoProfile = 'vprf', // int32_t
+ kKeyVideoLevel = 'vlev', // int32_t
+
+ // Set this key to enable authoring files in 64-bit offset
+ kKey64BitFileOffset = 'fobt', // int32_t (bool)
+ kKey2ByteNalLength = '2NAL', // int32_t (bool)
+
+ // Identify the file output format for authoring
+ // Please see <media/mediarecorder.h> for the supported
+ // file output formats.
+ kKeyFileType = 'ftyp', // int32_t
+
+ // Track authoring progress status
+ // kKeyTrackTimeStatus is used to track progress in elapsed time
+ kKeyTrackTimeStatus = 'tktm', // int64_t
+
+ kKeyRealTimeRecording = 'rtrc', // bool (int32_t)
+ kKeyNumBuffers = 'nbbf', // int32_t
+
+ // Ogg files can be tagged to be automatically looping...
+ kKeyAutoLoop = 'autL', // bool (int32_t)
+
+ kKeyValidSamples = 'valD', // int32_t
+
+ kKeyIsUnreadable = 'unre', // bool (int32_t)
+
+ // An indication that a video buffer has been rendered.
+ kKeyRendered = 'rend', // bool (int32_t)
+
+ // The language code for this media
+ kKeyMediaLanguage = 'lang', // cstring
+
+ // To store the timed text format data
+ kKeyTextFormatData = 'text', // raw data
+
+ kKeyRequiresSecureBuffers = 'secu', // bool (int32_t)
+
+ kKeyIsADTS = 'adts', // bool (int32_t)
+ kKeyAACAOT = 'aaot', // int32_t
+
+ // If a MediaBuffer's data represents (at least partially) encrypted
+ // data, the following fields aid in decryption.
+ // The data can be thought of as pairs of plain and encrypted data
+ // fragments, i.e. plain and encrypted data alternate.
+ // The first fragment is by convention plain data (if that's not the
+ // case, simply specify plain fragment size of 0).
+ // kKeyEncryptedSizes and kKeyPlainSizes each map to an array of
+ // size_t values. The sum total of all size_t values of both arrays
+ // must equal the amount of data (i.e. MediaBuffer's range_length()).
+ // If both arrays are present, they must be of the same size.
+ // If only encrypted sizes are present it is assumed that all
+ // plain sizes are 0, i.e. all fragments are encrypted.
+ // To programmatically set these array, use the MetaDataBase::setData API, i.e.
+ // const size_t encSizes[];
+ // meta->setData(
+ // kKeyEncryptedSizes, 0 /* type */, encSizes, sizeof(encSizes));
+ // A plain sizes array by itself makes no sense.
+ kKeyEncryptedSizes = 'encr', // size_t[]
+ kKeyPlainSizes = 'plai', // size_t[]
+ kKeyCryptoKey = 'cryK', // uint8_t[16]
+ kKeyCryptoIV = 'cryI', // uint8_t[16]
+ kKeyCryptoMode = 'cryM', // int32_t
+
+ kKeyCryptoDefaultIVSize = 'cryS', // int32_t
+
+ kKeyPssh = 'pssh', // raw data
+ kKeyCASystemID = 'caid', // int32_t
+ kKeyCASessionID = 'seid', // raw data
+
+ // Please see MediaFormat.KEY_IS_AUTOSELECT.
+ kKeyTrackIsAutoselect = 'auto', // bool (int32_t)
+ // Please see MediaFormat.KEY_IS_DEFAULT.
+ kKeyTrackIsDefault = 'dflt', // bool (int32_t)
+ // Similar to MediaFormat.KEY_IS_FORCED_SUBTITLE but pertains to av tracks as well.
+ kKeyTrackIsForced = 'frcd', // bool (int32_t)
+
+ // H264 supplemental enhancement information offsets/sizes
+ kKeySEI = 'sei ', // raw data
+
+ // MPEG user data offsets
+ kKeyMpegUserData = 'mpud', // size_t[]
+
+ // Size of NALU length in mkv/mp4
+ kKeyNalLengthSize = 'nals', // int32_t
+
+ // HDR related
+ kKeyHdrStaticInfo = 'hdrS', // HDRStaticInfo
+
+ // color aspects
+ kKeyColorRange = 'cRng', // int32_t, color range, value defined by ColorAspects.Range
+ kKeyColorPrimaries = 'cPrm', // int32_t,
+ // color Primaries, value defined by ColorAspects.Primaries
+ kKeyTransferFunction = 'tFun', // int32_t,
+ // transfer Function, value defined by ColorAspects.Transfer.
+ kKeyColorMatrix = 'cMtx', // int32_t,
+ // color Matrix, value defined by ColorAspects.MatrixCoeffs.
+ kKeyTemporalLayerId = 'iLyr', // int32_t, temporal layer-id. 0-based (0 => base layer)
+ kKeyTemporalLayerCount = 'cLyr', // int32_t, number of temporal layers encoded
+
+ kKeyGridWidth = 'grdW', // int32_t, HEIF grid width
+ kKeyGridHeight = 'grdH', // int32_t, HEIF grid height
+ kKeyGridRows = 'grdR', // int32_t, HEIF grid rows
+ kKeyGridCols = 'grdC', // int32_t, HEIF grid columns
+ kKeyIccProfile = 'prof', // raw data, ICC prifile data
+ kKeyIsPrimaryImage = 'prim', // bool (int32_t), image track is the primary image
+ kKeyFrameCount = 'nfrm', // int32_t, total number of frame in video track
+};
+
+enum {
+ kTypeESDS = 'esds',
+ kTypeAVCC = 'avcc',
+ kTypeHVCC = 'hvcc',
+ kTypeD263 = 'd263',
+};
+
+class Parcel;
+
+class MetaDataBase {
+public:
+ MetaDataBase();
+ MetaDataBase(const MetaDataBase &from);
+ MetaDataBase& operator = (const MetaDataBase &);
+
+ virtual ~MetaDataBase();
+
+ enum Type {
+ TYPE_NONE = 'none',
+ TYPE_C_STRING = 'cstr',
+ TYPE_INT32 = 'in32',
+ TYPE_INT64 = 'in64',
+ TYPE_FLOAT = 'floa',
+ TYPE_POINTER = 'ptr ',
+ TYPE_RECT = 'rect',
+ };
+
+ void clear();
+ bool remove(uint32_t key);
+
+ bool setCString(uint32_t key, const char *value);
+ bool setInt32(uint32_t key, int32_t value);
+ bool setInt64(uint32_t key, int64_t value);
+ bool setFloat(uint32_t key, float value);
+ bool setPointer(uint32_t key, void *value);
+
+ bool setRect(
+ uint32_t key,
+ int32_t left, int32_t top,
+ int32_t right, int32_t bottom);
+
+ bool findCString(uint32_t key, const char **value) const;
+ bool findInt32(uint32_t key, int32_t *value) const;
+ bool findInt64(uint32_t key, int64_t *value) const;
+ bool findFloat(uint32_t key, float *value) const;
+ bool findPointer(uint32_t key, void **value) const;
+
+ bool findRect(
+ uint32_t key,
+ int32_t *left, int32_t *top,
+ int32_t *right, int32_t *bottom) const;
+
+ bool setData(uint32_t key, uint32_t type, const void *data, size_t size);
+
+ bool findData(uint32_t key, uint32_t *type,
+ const void **data, size_t *size) const;
+
+ bool hasData(uint32_t key) const;
+
+ String8 toString() const;
+ void dumpToLog() const;
+
+private:
+ friend class BpMediaSource;
+ friend class BnMediaSource;
+ friend class BnMediaExtractor;
+ friend class MetaData;
+
+ struct typed_data;
+ struct Rect;
+ struct MetaDataInternal;
+ MetaDataInternal *mInternalData;
+ status_t writeToParcel(Parcel &parcel);
+ status_t updateFromParcel(const Parcel &parcel);
+};
+
+} // namespace android
+
+#endif // META_DATA_H_
diff --git a/media/libmediaplayer2/nuplayer2/GenericSource2.cpp b/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
index c34aabb..790581a 100644
--- a/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
+++ b/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
@@ -35,6 +35,7 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/DataSourceFactory.h>
+#include <media/stagefright/FileSource.h>
#include <media/stagefright/InterfaceUtils.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaClock.h>
@@ -161,30 +162,15 @@
status_t NuPlayer2::GenericSource2::initFromDataSource() {
sp<IMediaExtractor> extractor;
- CHECK(mDataSource != NULL || mFd != -1);
+ CHECK(mDataSource != NULL);
sp<DataSource> dataSource = mDataSource;
- const int fd = mFd;
- const int64_t offset = mOffset;
- const int64_t length = mLength;
mLock.unlock();
// This might take long time if data source is not reliable.
- if (dataSource != nullptr) {
- extractor = MediaExtractorFactory::Create(dataSource, NULL /* mime */);
- } else {
- extractor = MediaExtractorFactory::CreateFromFd(
- fd, offset, length, NULL /* mime */, &dataSource);
- }
-
- if (dataSource == nullptr) {
- ALOGE("initFromDataSource, failed to create data source!");
- mLock.lock();
- return UNKNOWN_ERROR;
- }
+ extractor = MediaExtractorFactory::Create(dataSource, NULL);
if (extractor == NULL) {
ALOGE("initFromDataSource, cannot create extractor!");
- mLock.lock();
return UNKNOWN_ERROR;
}
@@ -193,13 +179,10 @@
size_t numtracks = extractor->countTracks();
if (numtracks == 0) {
ALOGE("initFromDataSource, source has no track!");
- mLock.lock();
return UNKNOWN_ERROR;
}
mLock.lock();
- mFd = -1;
- mDataSource = dataSource;
mFileMeta = fileMeta;
if (mFileMeta != NULL) {
int64_t duration;
@@ -408,16 +391,51 @@
if (!mDisconnected) {
mDataSource = dataSource;
}
+ } else {
+ if (property_get_bool("media.stagefright.extractremote", true) &&
+ !FileSource::requiresDrm(mFd, mOffset, mLength, nullptr /* mime */)) {
+ sp<IBinder> binder =
+ defaultServiceManager()->getService(String16("media.extractor"));
+ if (binder != nullptr) {
+ ALOGD("FileSource remote");
+ sp<IMediaExtractorService> mediaExService(
+ interface_cast<IMediaExtractorService>(binder));
+ sp<IDataSource> source =
+ mediaExService->makeIDataSource(mFd, mOffset, mLength);
+ ALOGV("IDataSource(FileSource): %p %d %lld %lld",
+ source.get(), mFd, (long long)mOffset, (long long)mLength);
+ if (source.get() != nullptr) {
+ mDataSource = CreateDataSourceFromIDataSource(source);
+ if (mDataSource != nullptr) {
+ // Close the local file descriptor as it is not needed anymore.
+ close(mFd);
+ mFd = -1;
+ }
+ } else {
+ ALOGW("extractor service cannot make data source");
+ }
+ } else {
+ ALOGW("extractor service not running");
+ }
+ }
+ if (mDataSource == nullptr) {
+ ALOGD("FileSource local");
+ mDataSource = new FileSource(mFd, mOffset, mLength);
+ }
+ // TODO: close should always be done on mFd, see the lines following
+ // CreateDataSourceFromIDataSource above,
+ // and the FileSource constructor should dup the mFd argument as needed.
+ mFd = -1;
}
- if (mFd == -1 && mDataSource == NULL) {
+ if (mDataSource == NULL) {
ALOGE("Failed to create data source!");
notifyPreparedAndCleanup(UNKNOWN_ERROR);
return;
}
}
- if (mDataSource != nullptr && mDataSource->flags() & DataSource::kIsCachingDataSource) {
+ if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
}
@@ -1187,7 +1205,7 @@
if (audio && mAudioIsVorbis) {
int32_t numPageSamples;
- if (!mb->meta_data()->findInt32(kKeyValidSamples, &numPageSamples)) {
+ if (!mb->meta_data().findInt32(kKeyValidSamples, &numPageSamples)) {
numPageSamples = -1;
}
@@ -1198,12 +1216,12 @@
sp<AMessage> meta = ab->meta();
int64_t timeUs;
- CHECK(mb->meta_data()->findInt64(kKeyTime, &timeUs));
+ CHECK(mb->meta_data().findInt64(kKeyTime, &timeUs));
meta->setInt64("timeUs", timeUs);
if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
int32_t layerId;
- if (mb->meta_data()->findInt32(kKeyTemporalLayerId, &layerId)) {
+ if (mb->meta_data().findInt32(kKeyTemporalLayerId, &layerId)) {
meta->setInt32("temporal-layer-id", layerId);
}
}
@@ -1216,7 +1234,7 @@
}
int64_t durationUs;
- if (mb->meta_data()->findInt64(kKeyDuration, &durationUs)) {
+ if (mb->meta_data().findInt64(kKeyDuration, &durationUs)) {
meta->setInt64("durationUs", durationUs);
}
@@ -1227,14 +1245,14 @@
uint32_t dataType; // unused
const void *seiData;
size_t seiLength;
- if (mb->meta_data()->findData(kKeySEI, &dataType, &seiData, &seiLength)) {
+ if (mb->meta_data().findData(kKeySEI, &dataType, &seiData, &seiLength)) {
sp<ABuffer> sei = ABuffer::CreateAsCopy(seiData, seiLength);;
meta->setBuffer("sei", sei);
}
const void *mpegUserDataPointer;
size_t mpegUserDataLength;
- if (mb->meta_data()->findData(
+ if (mb->meta_data().findData(
kKeyMpegUserData, &dataType, &mpegUserDataPointer, &mpegUserDataLength)) {
sp<ABuffer> mpegUserData = ABuffer::CreateAsCopy(mpegUserDataPointer, mpegUserDataLength);
meta->setBuffer("mpegUserData", mpegUserData);
@@ -1366,8 +1384,8 @@
for (; id < count; ++id) {
int64_t timeUs;
MediaBufferBase *mbuf = mediaBuffers[id];
- if (!mbuf->meta_data()->findInt64(kKeyTime, &timeUs)) {
- mbuf->meta_data()->dumpToLog();
+ if (!mbuf->meta_data().findInt64(kKeyTime, &timeUs)) {
+ mbuf->meta_data().dumpToLog();
track->mPackets->signalEOS(ERROR_MALFORMED);
break;
}
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.cpp
index c49bccb..645138a 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Decoder.cpp
@@ -1091,7 +1091,7 @@
codecBuffer->setRange(0, mediaBuf->size());
memcpy(codecBuffer->data(), mediaBuf->data(), mediaBuf->size());
- sp<MetaData> meta_data = mediaBuf->meta_data();
+ MetaDataBase &meta_data = mediaBuf->meta_data();
cryptInfo = AMediaCodecCryptoInfoWrapper::Create(meta_data);
} else { // No mediaBuf
ALOGE("onInputBufferFetched: buffer->data()/mediaBuf are NULL for %p",
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index b0c82f2..e7c3deb 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -27,6 +27,7 @@
#include <media/MediaBufferHolder.h>
#include <media/MediaExtractor.h>
#include <media/MediaSource.h>
+#include <media/IMediaExtractorService.h>
#include <media/IMediaHTTPService.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -161,30 +162,15 @@
status_t NuPlayer::GenericSource::initFromDataSource() {
sp<IMediaExtractor> extractor;
- CHECK(mDataSource != NULL || mFd != -1);
+ CHECK(mDataSource != NULL);
sp<DataSource> dataSource = mDataSource;
- const int fd = mFd;
- const int64_t offset = mOffset;
- const int64_t length = mLength;
mLock.unlock();
// This might take long time if data source is not reliable.
- if (dataSource != nullptr) {
- extractor = MediaExtractorFactory::Create(dataSource, NULL /* mime */);
- } else {
- extractor = MediaExtractorFactory::CreateFromFd(
- fd, offset, length, NULL /* mime */, &dataSource);
- }
-
- if (dataSource == nullptr) {
- ALOGE("initFromDataSource, failed to create data source!");
- mLock.lock();
- return UNKNOWN_ERROR;
- }
+ extractor = MediaExtractorFactory::Create(dataSource, NULL);
if (extractor == NULL) {
ALOGE("initFromDataSource, cannot create extractor!");
- mLock.lock();
return UNKNOWN_ERROR;
}
@@ -193,13 +179,10 @@
size_t numtracks = extractor->countTracks();
if (numtracks == 0) {
ALOGE("initFromDataSource, source has no track!");
- mLock.lock();
return UNKNOWN_ERROR;
}
mLock.lock();
- mFd = -1;
- mDataSource = dataSource;
mFileMeta = fileMeta;
if (mFileMeta != NULL) {
int64_t duration;
@@ -403,15 +386,51 @@
if (!mDisconnected) {
mDataSource = dataSource;
}
+ } else {
+ if (property_get_bool("media.stagefright.extractremote", true) &&
+ !FileSource::requiresDrm(mFd, mOffset, mLength, nullptr /* mime */)) {
+ sp<IBinder> binder =
+ defaultServiceManager()->getService(String16("media.extractor"));
+ if (binder != nullptr) {
+ ALOGD("FileSource remote");
+ sp<IMediaExtractorService> mediaExService(
+ interface_cast<IMediaExtractorService>(binder));
+ sp<IDataSource> source =
+ mediaExService->makeIDataSource(mFd, mOffset, mLength);
+ ALOGV("IDataSource(FileSource): %p %d %lld %lld",
+ source.get(), mFd, (long long)mOffset, (long long)mLength);
+ if (source.get() != nullptr) {
+ mDataSource = CreateDataSourceFromIDataSource(source);
+ if (mDataSource != nullptr) {
+ // Close the local file descriptor as it is not needed anymore.
+ close(mFd);
+ mFd = -1;
+ }
+ } else {
+ ALOGW("extractor service cannot make data source");
+ }
+ } else {
+ ALOGW("extractor service not running");
+ }
+ }
+ if (mDataSource == nullptr) {
+ ALOGD("FileSource local");
+ mDataSource = new FileSource(mFd, mOffset, mLength);
+ }
+ // TODO: close should always be done on mFd, see the lines following
+ // CreateDataSourceFromIDataSource above,
+ // and the FileSource constructor should dup the mFd argument as needed.
+ mFd = -1;
}
- if (mFd == -1 && mDataSource == NULL) {
+
+ if (mDataSource == NULL) {
ALOGE("Failed to create data source!");
notifyPreparedAndCleanup(UNKNOWN_ERROR);
return;
}
}
- if (mDataSource != nullptr && mDataSource->flags() & DataSource::kIsCachingDataSource) {
+ if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
}
@@ -1180,7 +1199,7 @@
if (audio && mAudioIsVorbis) {
int32_t numPageSamples;
- if (!mb->meta_data()->findInt32(kKeyValidSamples, &numPageSamples)) {
+ if (!mb->meta_data().findInt32(kKeyValidSamples, &numPageSamples)) {
numPageSamples = -1;
}
@@ -1191,12 +1210,12 @@
sp<AMessage> meta = ab->meta();
int64_t timeUs;
- CHECK(mb->meta_data()->findInt64(kKeyTime, &timeUs));
+ CHECK(mb->meta_data().findInt64(kKeyTime, &timeUs));
meta->setInt64("timeUs", timeUs);
if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
int32_t layerId;
- if (mb->meta_data()->findInt32(kKeyTemporalLayerId, &layerId)) {
+ if (mb->meta_data().findInt32(kKeyTemporalLayerId, &layerId)) {
meta->setInt32("temporal-layer-id", layerId);
}
}
@@ -1209,7 +1228,7 @@
}
int64_t durationUs;
- if (mb->meta_data()->findInt64(kKeyDuration, &durationUs)) {
+ if (mb->meta_data().findInt64(kKeyDuration, &durationUs)) {
meta->setInt64("durationUs", durationUs);
}
@@ -1220,14 +1239,14 @@
uint32_t dataType; // unused
const void *seiData;
size_t seiLength;
- if (mb->meta_data()->findData(kKeySEI, &dataType, &seiData, &seiLength)) {
+ if (mb->meta_data().findData(kKeySEI, &dataType, &seiData, &seiLength)) {
sp<ABuffer> sei = ABuffer::CreateAsCopy(seiData, seiLength);;
meta->setBuffer("sei", sei);
}
const void *mpegUserDataPointer;
size_t mpegUserDataLength;
- if (mb->meta_data()->findData(
+ if (mb->meta_data().findData(
kKeyMpegUserData, &dataType, &mpegUserDataPointer, &mpegUserDataLength)) {
sp<ABuffer> mpegUserData = ABuffer::CreateAsCopy(mpegUserDataPointer, mpegUserDataLength);
meta->setBuffer("mpegUserData", mpegUserData);
@@ -1359,8 +1378,8 @@
for (; id < count; ++id) {
int64_t timeUs;
MediaBufferBase *mbuf = mediaBuffers[id];
- if (!mbuf->meta_data()->findInt64(kKeyTime, &timeUs)) {
- mbuf->meta_data()->dumpToLog();
+ if (!mbuf->meta_data().findInt64(kKeyTime, &timeUs)) {
+ mbuf->meta_data().dumpToLog();
track->mPackets->signalEOS(ERROR_MALFORMED);
break;
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 88594d2..2a08f62 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -1071,7 +1071,7 @@
codecBuffer->setRange(0, mediaBuf->size());
memcpy(codecBuffer->data(), mediaBuf->data(), mediaBuf->size());
- sp<MetaData> meta_data = mediaBuf->meta_data();
+ MetaDataBase &meta_data = mediaBuf->meta_data();
cryptInfo = NuPlayerDrm::getSampleCryptoInfo(meta_data);
} else { // No mediaBuf
ALOGE("onInputBufferFetched: buffer->data()/mediaBuf are NULL for %p",
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
index b7c9db7..165e483 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
@@ -265,18 +265,13 @@
return ret;
}
-NuPlayerDrm::CryptoInfo *NuPlayerDrm::getSampleCryptoInfo(sp<MetaData> meta)
+NuPlayerDrm::CryptoInfo *NuPlayerDrm::getSampleCryptoInfo(MetaDataBase &meta)
{
uint32_t type;
const void *crypteddata;
size_t cryptedsize;
- if (meta == NULL) {
- ALOGE("getSampleCryptoInfo: Unexpected. No meta data for sample.");
- return NULL;
- }
-
- if (!meta->findData(kKeyEncryptedSizes, &type, &crypteddata, &cryptedsize)) {
+ if (!meta.findData(kKeyEncryptedSizes, &type, &crypteddata, &cryptedsize)) {
return NULL;
}
size_t numSubSamples = cryptedsize / sizeof(size_t);
@@ -288,7 +283,7 @@
const void *cleardata;
size_t clearsize;
- if (meta->findData(kKeyPlainSizes, &type, &cleardata, &clearsize)) {
+ if (meta.findData(kKeyPlainSizes, &type, &cleardata, &clearsize)) {
if (clearsize != cryptedsize) {
// The two must be of the same length.
ALOGE("getSampleCryptoInfo mismatch cryptedsize: %zu != clearsize: %zu",
@@ -299,7 +294,7 @@
const void *key;
size_t keysize;
- if (meta->findData(kKeyCryptoKey, &type, &key, &keysize)) {
+ if (meta.findData(kKeyCryptoKey, &type, &key, &keysize)) {
if (keysize != kBlockSize) {
ALOGE("getSampleCryptoInfo Keys must be %d bytes in length: %zu",
kBlockSize, keysize);
@@ -310,7 +305,7 @@
const void *iv;
size_t ivsize;
- if (meta->findData(kKeyCryptoIV, &type, &iv, &ivsize)) {
+ if (meta.findData(kKeyCryptoIV, &type, &iv, &ivsize)) {
if (ivsize != kBlockSize) {
ALOGE("getSampleCryptoInfo IV must be %d bytes in length: %zu",
kBlockSize, ivsize);
@@ -320,7 +315,7 @@
}
int32_t mode;
- if (!meta->findInt32(kKeyCryptoMode, &mode)) {
+ if (!meta.findInt32(kKeyCryptoMode, &mode)) {
mode = CryptoPlugin::kMode_AES_CTR;
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.h b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.h
index 6b8a2d9..50f69ff 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.h
@@ -109,7 +109,7 @@
size_t *clearbytes,
size_t *encryptedbytes);
- static CryptoInfo *getSampleCryptoInfo(sp<MetaData> meta);
+ static CryptoInfo *getSampleCryptoInfo(MetaDataBase &meta);
}; // NuPlayerDrm
diff --git a/media/libstagefright/AACWriter.cpp b/media/libstagefright/AACWriter.cpp
index d64138e..2ea5fcd 100644
--- a/media/libstagefright/AACWriter.cpp
+++ b/media/libstagefright/AACWriter.cpp
@@ -316,7 +316,7 @@
}
int32_t isCodecSpecific = 0;
- if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecSpecific) && isCodecSpecific) {
+ if (buffer->meta_data().findInt32(kKeyIsCodecConfig, &isCodecSpecific) && isCodecSpecific) {
ALOGV("Drop codec specific info buffer");
buffer->release();
buffer = NULL;
@@ -324,7 +324,7 @@
}
int64_t timestampUs;
- CHECK(buffer->meta_data()->findInt64(kKeyTime, ×tampUs));
+ CHECK(buffer->meta_data().findInt64(kKeyTime, ×tampUs));
if (timestampUs > mEstimatedDurationUs) {
mEstimatedDurationUs = timestampUs;
}
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 6da6c13..b296622 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -6349,90 +6349,54 @@
Vector<AString> matchingCodecs;
Vector<AString> owners;
- AString mime;
-
AString componentName;
- int32_t encoder = false;
- if (msg->findString("componentName", &componentName)) {
- sp<IMediaCodecList> list = MediaCodecList::getInstance();
- if (list == nullptr) {
- ALOGE("Unable to obtain MediaCodecList while "
- "attempting to create codec \"%s\"",
- componentName.c_str());
- mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
- return false;
- }
- ssize_t index = list->findCodecByName(componentName.c_str());
- if (index < 0) {
- ALOGE("Unable to find codec \"%s\"",
- componentName.c_str());
- mCodec->signalError(OMX_ErrorInvalidComponent, NAME_NOT_FOUND);
- return false;
- }
- sp<MediaCodecInfo> info = list->getCodecInfo(index);
- if (info == nullptr) {
- ALOGE("Unexpected error (index out-of-bound) while "
- "retrieving information for codec \"%s\"",
- componentName.c_str());
- mCodec->signalError(OMX_ErrorUndefined, UNKNOWN_ERROR);
- return false;
- }
- matchingCodecs.add(info->getCodecName());
- owners.add(info->getOwnerName() == nullptr ?
- "default" : info->getOwnerName());
- } else {
- CHECK(msg->findString("mime", &mime));
+ CHECK(msg->findString("componentName", &componentName));
- if (!msg->findInt32("encoder", &encoder)) {
- encoder = false;
- }
-
- MediaCodecList::findMatchingCodecs(
- mime.c_str(),
- encoder, // createEncoder
- 0, // flags
- &matchingCodecs,
- &owners);
+ sp<IMediaCodecList> list = MediaCodecList::getInstance();
+ if (list == nullptr) {
+ ALOGE("Unable to obtain MediaCodecList while "
+ "attempting to create codec \"%s\"",
+ componentName.c_str());
+ mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
+ return false;
}
+ ssize_t index = list->findCodecByName(componentName.c_str());
+ if (index < 0) {
+ ALOGE("Unable to find codec \"%s\"",
+ componentName.c_str());
+ mCodec->signalError(OMX_ErrorInvalidComponent, NAME_NOT_FOUND);
+ return false;
+ }
+ sp<MediaCodecInfo> info = list->getCodecInfo(index);
+ if (info == nullptr) {
+ ALOGE("Unexpected error (index out-of-bound) while "
+ "retrieving information for codec \"%s\"",
+ componentName.c_str());
+ mCodec->signalError(OMX_ErrorUndefined, UNKNOWN_ERROR);
+ return false;
+ }
+ AString owner = (info->getOwnerName() == nullptr) ? "default" : info->getOwnerName();
sp<CodecObserver> observer = new CodecObserver;
sp<IOMX> omx;
sp<IOMXNode> omxNode;
status_t err = NAME_NOT_FOUND;
- for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
- ++matchIndex) {
- componentName = matchingCodecs[matchIndex];
-
- OMXClient client;
- if (client.connect(owners[matchIndex].c_str()) != OK) {
- mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
- return false;
- }
- omx = client.interface();
-
- pid_t tid = gettid();
- int prevPriority = androidGetThreadPriority(tid);
- androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
- err = omx->allocateNode(componentName.c_str(), observer, &omxNode);
- androidSetThreadPriority(tid, prevPriority);
-
- if (err == OK) {
- break;
- } else {
- ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
- }
-
- omxNode = NULL;
+ OMXClient client;
+ if (client.connect(owner.c_str()) != OK) {
+ mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
+ return false;
}
+ omx = client.interface();
- if (omxNode == NULL) {
- if (!mime.empty()) {
- ALOGE("Unable to instantiate a %scoder for type '%s' with err %#x.",
- encoder ? "en" : "de", mime.c_str(), err);
- } else {
- ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err);
- }
+ pid_t tid = gettid();
+ int prevPriority = androidGetThreadPriority(tid);
+ androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
+ err = omx->allocateNode(componentName.c_str(), observer, &omxNode);
+ androidSetThreadPriority(tid, prevPriority);
+
+ if (err != OK) {
+ ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err);
mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err));
return false;
diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp
index e33d3da..41106a1 100644
--- a/media/libstagefright/AMRWriter.cpp
+++ b/media/libstagefright/AMRWriter.cpp
@@ -215,7 +215,7 @@
}
int64_t timestampUs;
- CHECK(buffer->meta_data()->findInt64(kKeyTime, ×tampUs));
+ CHECK(buffer->meta_data().findInt64(kKeyTime, ×tampUs));
if (timestampUs > mEstimatedDurationUs) {
mEstimatedDurationUs = timestampUs;
}
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index e704c88..65348e5 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -63,6 +63,7 @@
"C2OMXNode.cpp",
"CCodec.cpp",
"CCodecBufferChannel.cpp",
+ "Codec2InfoBuilder.cpp",
"CodecBase.cpp",
"CallbackDataSource.cpp",
"CallbackMediaSource.cpp",
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index 16ea5b5..a6f0a0b 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -543,7 +543,7 @@
}
if(mInputBuffer->range_length() != 0) {
- CHECK(mInputBuffer->meta_data()->findInt64(
+ CHECK(mInputBuffer->meta_data().findInt64(
kKeyTime, &mPositionTimeMediaUs));
}
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index d854582..2ae3218 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -265,7 +265,7 @@
// Mute/suppress the recording sound
int64_t timeUs;
- CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
+ CHECK(buffer->meta_data().findInt64(kKeyTime, &timeUs));
int64_t elapsedTimeUs = timeUs - mStartTimeUs;
if (elapsedTimeUs < kAutoRampStartUs) {
memset((uint8_t *) buffer->data(), 0, buffer->range_length());
@@ -289,7 +289,7 @@
if (mSampleRate != mOutSampleRate) {
timeUs *= (int64_t)mSampleRate / (int64_t)mOutSampleRate;
- buffer->meta_data()->setInt64(kKeyTime, timeUs);
+ buffer->meta_data().setInt64(kKeyTime, timeUs);
}
*out = buffer;
@@ -433,11 +433,11 @@
(mSampleRate >> 1)) / mSampleRate;
if (mNumFramesReceived == 0) {
- buffer->meta_data()->setInt64(kKeyAnchorTime, mStartTimeUs);
+ buffer->meta_data().setInt64(kKeyAnchorTime, mStartTimeUs);
}
- buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs);
- buffer->meta_data()->setInt64(kKeyDriftTime, timeUs - mInitialReadTimeUs);
+ buffer->meta_data().setInt64(kKeyTime, mPrevSampleTimeUs);
+ buffer->meta_data().setInt64(kKeyDriftTime, timeUs - mInitialReadTimeUs);
mPrevSampleTimeUs = timestampUs;
mNumFramesReceived += bufferSize / frameSize;
mBuffersReceived.push_back(buffer);
diff --git a/media/libstagefright/CCodec.cpp b/media/libstagefright/CCodec.cpp
index bb70458..f62ee41 100644
--- a/media/libstagefright/CCodec.cpp
+++ b/media/libstagefright/CCodec.cpp
@@ -313,6 +313,19 @@
}
void CCodec::configure(const sp<AMessage> &msg) {
+ std::shared_ptr<C2ComponentInterface> intf;
+ {
+ Mutexed<State>::Locked state(mState);
+ if (state->get() != ALLOCATED) {
+ state->set(RELEASED);
+ state.unlock();
+ mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
+ state.lock();
+ return;
+ }
+ intf = state->comp->intf();
+ }
+
sp<AMessage> inputFormat(new AMessage);
sp<AMessage> outputFormat(new AMessage);
if (status_t err = [=] {
@@ -332,11 +345,34 @@
setSurface(surface);
}
+ std::vector<std::unique_ptr<C2Param>> params;
+ std::initializer_list<C2Param::Index> indices {
+ C2PortMimeConfig::input::PARAM_TYPE,
+ C2PortMimeConfig::output::PARAM_TYPE,
+ };
+ c2_status_t c2err = intf->query_vb(
+ {},
+ indices,
+ C2_DONT_BLOCK,
+ ¶ms);
+ if (c2err != C2_OK) {
+ ALOGE("Failed to query component interface: %d", c2err);
+ return UNKNOWN_ERROR;
+ }
+ if (params.size() != indices.size()) {
+ ALOGE("Component returns wrong number of params");
+ return UNKNOWN_ERROR;
+ }
+ if (!params[0] || !params[1]) {
+ ALOGE("Component returns null params");
+ return UNKNOWN_ERROR;
+ }
+ inputFormat->setString("mime", ((C2PortMimeConfig *)params[0].get())->m.value);
+ outputFormat->setString("mime", ((C2PortMimeConfig *)params[1].get())->m.value);
+
// XXX: hack
bool audio = mime.startsWithIgnoreCase("audio/");
if (encoder) {
- outputFormat->setString("mime", mime);
- inputFormat->setString("mime", AStringPrintf("%s/raw", audio ? "audio" : "video"));
if (audio) {
inputFormat->setInt32("channel-count", 1);
inputFormat->setInt32("sample-rate", 44100);
@@ -347,8 +383,6 @@
outputFormat->setInt32("height", 1920);
}
} else {
- inputFormat->setString("mime", mime);
- outputFormat->setString("mime", AStringPrintf("%s/raw", audio ? "audio" : "video"));
if (audio) {
outputFormat->setInt32("channel-count", 2);
outputFormat->setInt32("sample-rate", 44100);
@@ -712,7 +746,7 @@
switch (msg->what()) {
case kWhatAllocate: {
// C2ComponentStore::createComponent() should return within 100ms.
- setDeadline(now + 150ms);
+ setDeadline(now + 150ms, "allocate");
AString componentName;
CHECK(msg->findString("componentName", &componentName));
allocate(componentName);
@@ -720,7 +754,7 @@
}
case kWhatConfigure: {
// C2Component::commit_sm() should return within 5ms.
- setDeadline(now + 50ms);
+ setDeadline(now + 50ms, "configure");
sp<AMessage> format;
CHECK(msg->findMessage("format", &format));
configure(format);
@@ -728,31 +762,31 @@
}
case kWhatStart: {
// C2Component::start() should return within 500ms.
- setDeadline(now + 550ms);
+ setDeadline(now + 550ms, "start");
start();
break;
}
case kWhatStop: {
// C2Component::stop() should return within 500ms.
- setDeadline(now + 550ms);
+ setDeadline(now + 550ms, "stop");
stop();
break;
}
case kWhatFlush: {
// C2Component::flush_sm() should return within 5ms.
- setDeadline(now + 50ms);
+ setDeadline(now + 50ms, "flush");
flush();
break;
}
case kWhatCreateInputSurface: {
// Surface operations may be briefly blocking.
- setDeadline(now + 100ms);
+ setDeadline(now + 100ms, "createInputSurface");
createInputSurface();
break;
}
case kWhatSetInputSurface: {
// Surface operations may be briefly blocking.
- setDeadline(now + 100ms);
+ setDeadline(now + 100ms, "setInputSurface");
sp<RefBase> obj;
CHECK(msg->findObject("surface", &obj));
sp<PersistentSurface> surface(static_cast<PersistentSurface *>(obj.get()));
@@ -780,25 +814,28 @@
break;
}
}
- setDeadline(TimePoint::max());
+ setDeadline(TimePoint::max(), "none");
}
-void CCodec::setDeadline(const TimePoint &newDeadline) {
- Mutexed<TimePoint>::Locked deadline(mDeadline);
- *deadline = newDeadline;
+void CCodec::setDeadline(const TimePoint &newDeadline, const char *name) {
+ Mutexed<NamedTimePoint>::Locked deadline(mDeadline);
+ deadline->set(newDeadline, name);
}
void CCodec::initiateReleaseIfStuck() {
+ std::string name;
{
- Mutexed<TimePoint>::Locked deadline(mDeadline);
- if (*deadline >= std::chrono::steady_clock::now()) {
+ Mutexed<NamedTimePoint>::Locked deadline(mDeadline);
+ if (deadline->get() >= std::chrono::steady_clock::now()) {
// We're not stuck.
return;
}
+ name = deadline->getName();
}
+ ALOGW("previous call to %s exceeded timeout", name.c_str());
mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
- initiateRelease();
+ initiateRelease(false);
}
} // namespace android
diff --git a/media/libstagefright/CallbackDataSource.cpp b/media/libstagefright/CallbackDataSource.cpp
index 71b737b..92e6eb9 100644
--- a/media/libstagefright/CallbackDataSource.cpp
+++ b/media/libstagefright/CallbackDataSource.cpp
@@ -117,6 +117,10 @@
return mIDataSource->DrmInitialization(mime);
}
+sp<IDataSource> CallbackDataSource::getIDataSource() const {
+ return mIDataSource;
+}
+
TinyCacheSource::TinyCacheSource(const sp<DataSource>& source)
: mSource(source), mCachedOffset(0), mCachedSize(0) {
mName = String8::format("TinyCacheSource(%s)", mSource->toString().string());
@@ -194,4 +198,8 @@
return mSource->DrmInitialization(mime);
}
+sp<IDataSource> TinyCacheSource::getIDataSource() const {
+ return mSource->getIDataSource();
+}
+
} // namespace android
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 4960418..db37021 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -1100,7 +1100,7 @@
*buffer = new MediaBuffer(frame->pointer(), frame->size());
(*buffer)->setObserver(this);
(*buffer)->add_ref();
- (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
+ (*buffer)->meta_data().setInt64(kKeyTime, frameTime);
}
return OK;
}
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index f3f06d8..3ad82d9 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -191,13 +191,13 @@
(*newBuffer) = new MediaBuffer(sourceSize);
memcpy((*newBuffer)->data(), sourcePointer, sourceSize);
- (*newBuffer)->meta_data()->setInt64(kKeyTime, frameTime);
+ (*newBuffer)->meta_data().setInt64(kKeyTime, frameTime);
}
void CameraSourceTimeLapse::fillLastReadBufferCopy(MediaBufferBase& sourceBuffer) {
ALOGV("fillLastReadBufferCopy");
int64_t frameTime;
- CHECK(sourceBuffer.meta_data()->findInt64(kKeyTime, &frameTime));
+ CHECK(sourceBuffer.meta_data().findInt64(kKeyTime, &frameTime));
createMediaBufferCopy(sourceBuffer, frameTime, &mLastReadBufferCopy);
mLastReadBufferCopy->add_ref();
mLastReadBufferCopy->setObserver(this);
diff --git a/media/libstagefright/Codec2InfoBuilder.cpp b/media/libstagefright/Codec2InfoBuilder.cpp
new file mode 100644
index 0000000..7ce2ff1
--- /dev/null
+++ b/media/libstagefright/Codec2InfoBuilder.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2018 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 "Codec2InfoBuilder"
+#include <log/log.h>
+
+#include <C2Component.h>
+#include <C2PlatformSupport.h>
+#include <C2V4l2Support.h>
+
+#include <cutils/properties.h>
+#include <media/stagefright/foundation/MediaDefs.h>
+#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
+#include <media/stagefright/Codec2InfoBuilder.h>
+
+namespace android {
+
+using ConstTraitsPtr = std::shared_ptr<const C2Component::Traits>;
+
+status_t Codec2InfoBuilder::buildMediaCodecList(MediaCodecListWriter* writer) {
+ // Obtain C2ComponentStore
+ std::shared_ptr<C2ComponentStore> store = GetCodec2PlatformComponentStore();
+ if (store == nullptr) {
+ ALOGE("Cannot find a component store.");
+ return NO_INIT;
+ }
+
+ std::vector<ConstTraitsPtr> traits = store->listComponents();
+
+ if (property_get_bool("debug.stagefright.ccodec_v4l2", false)) {
+ std::shared_ptr<C2ComponentStore> v4l2Store = GetCodec2VDAComponentStore();
+ if (v4l2Store == nullptr) {
+ ALOGD("Cannot find a V4L2 component store.");
+ // non-fatal.
+ } else {
+ std::vector<ConstTraitsPtr> v4l2Traits = v4l2Store->listComponents();
+ traits.insert(traits.end(), v4l2Traits.begin(), v4l2Traits.end());
+ }
+ }
+
+ MediaCodecsXmlParser parser(
+ MediaCodecsXmlParser::defaultSearchDirs,
+ "media_codecs_c2.xml");
+ if (parser.getParsingStatus() != OK) {
+ ALOGD("XML parser no good");
+ return OK;
+ }
+ for (const ConstTraitsPtr &trait : traits) {
+ if (parser.getCodecMap().count(trait->name.c_str()) == 0) {
+ ALOGD("%s not found in xml", trait->name.c_str());
+ continue;
+ }
+ const MediaCodecsXmlParser::CodecProperties &codec = parser.getCodecMap().at(trait->name);
+ std::unique_ptr<MediaCodecInfoWriter> codecInfo = writer->addMediaCodecInfo();
+ codecInfo->setName(trait->name.c_str());
+ codecInfo->setOwner("dummy");
+ // TODO: get this from trait->kind
+ bool encoder = (trait->name.find("encoder") != std::string::npos);
+ codecInfo->setEncoder(encoder);
+ codecInfo->setRank(trait->rank);
+ for (auto typeIt = codec.typeMap.begin(); typeIt != codec.typeMap.end(); ++typeIt) {
+ const std::string &mediaType = typeIt->first;
+ const MediaCodecsXmlParser::AttributeMap &attrMap = typeIt->second;
+ std::unique_ptr<MediaCodecInfo::CapabilitiesWriter> caps =
+ codecInfo->addMime(mediaType.c_str());
+ for (auto attrIt = attrMap.begin(); attrIt != attrMap.end(); ++attrIt) {
+ std::string key, value;
+ std::tie(key, value) = *attrIt;
+ if (key.find("feature-") == 0 && key.find("feature-bitrate-modes") != 0) {
+ caps->addDetail(key.c_str(), std::stoi(value));
+ } else {
+ caps->addDetail(key.c_str(), value.c_str());
+ }
+ }
+ // TODO: get this from intf().
+ if (mediaType.find("video") != std::string::npos && !encoder) {
+ caps->addColorFormat(0x7F420888); // COLOR_FormatYUV420Flexible
+ }
+ }
+ }
+ return OK;
+}
+
+} // namespace android
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index 6f88c0e..9748a8b 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -251,7 +251,7 @@
} else {
codecBuffer->setRange(0, mediaBuffer->range_length());
- CHECK(mediaBuffer->meta_data()->findInt64(kKeyTime, &ptsUs));
+ CHECK(mediaBuffer->meta_data().findInt64(kKeyTime, &ptsUs));
memcpy(codecBuffer->data(),
(const uint8_t*)mediaBuffer->data() + mediaBuffer->range_offset(),
mediaBuffer->range_length());
@@ -387,12 +387,12 @@
status_t VideoFrameDecoder::onInputReceived(
const sp<MediaCodecBuffer> &codecBuffer,
- const sp<MetaData> &sampleMeta, bool firstSample, uint32_t *flags) {
+ MetaDataBase &sampleMeta, bool firstSample, uint32_t *flags) {
bool isSeekingClosest = (mSeekMode == MediaSource::ReadOptions::SEEK_CLOSEST)
|| (mSeekMode == MediaSource::ReadOptions::SEEK_FRAME_INDEX);
if (firstSample && isSeekingClosest) {
- sampleMeta->findInt64(kKeyTargetTime, &mTargetTimeUs);
+ sampleMeta.findInt64(kKeyTargetTime, &mTargetTimeUs);
ALOGV("Seeking closest: targetTimeUs=%lld", (long long)mTargetTimeUs);
}
diff --git a/media/libstagefright/InterfaceUtils.cpp b/media/libstagefright/InterfaceUtils.cpp
index 70fbbd7..56c5908 100644
--- a/media/libstagefright/InterfaceUtils.cpp
+++ b/media/libstagefright/InterfaceUtils.cpp
@@ -56,7 +56,7 @@
sp<IMediaSource> CreateIMediaSourceFromMediaSourceBase(
const sp<RemoteMediaExtractor> &extractor,
- MediaSourceBase *source, const sp<RefBase> &plugin) {
+ MediaTrack *source, const sp<RefBase> &plugin) {
if (source == nullptr) {
return nullptr;
}
diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp
index cdcd657..770535c 100644
--- a/media/libstagefright/MPEG2TSWriter.cpp
+++ b/media/libstagefright/MPEG2TSWriter.cpp
@@ -264,11 +264,11 @@
buffer->range_length());
int64_t timeUs;
- CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
+ CHECK(buffer->meta_data().findInt64(kKeyTime, &timeUs));
mBuffer->meta()->setInt64("timeUs", timeUs);
int32_t isSync;
- if (buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)
+ if (buffer->meta_data().findInt32(kKeyIsSyncFrame, &isSync)
&& isSync != 0) {
mBuffer->meta()->setInt32("isSync", true);
}
@@ -288,7 +288,7 @@
}
int64_t timeUs;
- CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
+ CHECK(buffer->meta_data().findInt64(kKeyTime, &timeUs));
mBuffer->meta()->setInt64("timeUs", timeUs);
mBuffer->meta()->setInt32("isSync", true);
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 387cb13..cfbbcb2 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -2831,7 +2831,7 @@
++count;
int32_t isCodecConfig;
- if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
+ if (buffer->meta_data().findInt32(kKeyIsCodecConfig, &isCodecConfig)
&& isCodecConfig) {
// if config format (at track addition) already had CSD, keep that
// UNLESS we have not received any frames yet.
@@ -2890,7 +2890,7 @@
memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
buffer->range_length());
copy->set_range(0, buffer->range_length());
- meta_data = new MetaData(*buffer->meta_data().get());
+ meta_data = new MetaData(buffer->meta_data());
buffer->release();
buffer = NULL;
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 2b33708..7d5c63a 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -421,13 +421,33 @@
sp<MediaCodec> MediaCodec::CreateByType(
const sp<ALooper> &looper, const AString &mime, bool encoder, status_t *err, pid_t pid,
uid_t uid) {
- sp<MediaCodec> codec = new MediaCodec(looper, pid, uid);
+ Vector<AString> matchingCodecs;
+ Vector<AString> owners;
- const status_t ret = codec->init(mime, true /* nameIsType */, encoder);
+ MediaCodecList::findMatchingCodecs(
+ mime.c_str(),
+ encoder,
+ 0,
+ &matchingCodecs,
+ &owners);
+
if (err != NULL) {
- *err = ret;
+ *err = NAME_NOT_FOUND;
}
- return ret == OK ? codec : NULL; // NULL deallocates codec.
+ for (size_t i = 0; i < matchingCodecs.size(); ++i) {
+ sp<MediaCodec> codec = new MediaCodec(looper, pid, uid);
+ AString componentName = matchingCodecs[i];
+ status_t ret = codec->init(componentName);
+ if (err != NULL) {
+ *err = ret;
+ }
+ if (ret == OK) {
+ return codec;
+ }
+ ALOGD("Allocating component '%s' failed (%d), try next one.",
+ componentName.c_str(), ret);
+ }
+ return NULL;
}
// static
@@ -435,7 +455,7 @@
const sp<ALooper> &looper, const AString &name, status_t *err, pid_t pid, uid_t uid) {
sp<MediaCodec> codec = new MediaCodec(looper, pid, uid);
- const status_t ret = codec->init(name, false /* nameIsType */, false /* encoder */);
+ const status_t ret = codec->init(name);
if (err != NULL) {
*err = ret;
}
@@ -553,11 +573,11 @@
}
//static
-sp<CodecBase> MediaCodec::GetCodecBase(const AString &name, bool nameIsType) {
+sp<CodecBase> MediaCodec::GetCodecBase(const AString &name) {
static bool ccodecEnabled = property_get_bool("debug.stagefright.ccodec", false);
- if (ccodecEnabled && !nameIsType && name.startsWithIgnoreCase("c2.")) {
+ if (ccodecEnabled && name.startsWithIgnoreCase("c2.")) {
return new CCodec;
- } else if (nameIsType || name.startsWithIgnoreCase("omx.")) {
+ } else if (name.startsWithIgnoreCase("omx.")) {
// at this time only ACodec specifies a mime type.
return new ACodec;
} else if (name.startsWithIgnoreCase("android.filter.")) {
@@ -567,48 +587,42 @@
}
}
-status_t MediaCodec::init(const AString &name, bool nameIsType, bool encoder) {
+status_t MediaCodec::init(const AString &name) {
mResourceManagerService->init();
// save init parameters for reset
mInitName = name;
- mInitNameIsType = nameIsType;
- mInitIsEncoder = encoder;
// Current video decoders do not return from OMX_FillThisBuffer
// quickly, violating the OpenMAX specs, until that is remedied
// we need to invest in an extra looper to free the main event
// queue.
- mCodec = GetCodecBase(name, nameIsType);
+ mCodec = GetCodecBase(name);
if (mCodec == NULL) {
return NAME_NOT_FOUND;
}
bool secureCodec = false;
- if (nameIsType && !strncasecmp(name.c_str(), "video/", 6)) {
- mIsVideo = true;
- } else {
- AString tmp = name;
- if (tmp.endsWith(".secure")) {
- secureCodec = true;
- tmp.erase(tmp.size() - 7, 7);
- }
- const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
- if (mcl == NULL) {
- mCodec = NULL; // remove the codec.
- return NO_INIT; // if called from Java should raise IOException
- }
- ssize_t codecIdx = mcl->findCodecByName(tmp.c_str());
- if (codecIdx >= 0) {
- const sp<MediaCodecInfo> info = mcl->getCodecInfo(codecIdx);
- Vector<AString> mimes;
- info->getSupportedMimes(&mimes);
- for (size_t i = 0; i < mimes.size(); i++) {
- if (mimes[i].startsWith("video/")) {
- mIsVideo = true;
- break;
- }
+ AString tmp = name;
+ if (tmp.endsWith(".secure")) {
+ secureCodec = true;
+ tmp.erase(tmp.size() - 7, 7);
+ }
+ const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
+ if (mcl == NULL) {
+ mCodec = NULL; // remove the codec.
+ return NO_INIT; // if called from Java should raise IOException
+ }
+ ssize_t codecIdx = mcl->findCodecByName(tmp.c_str());
+ if (codecIdx >= 0) {
+ const sp<MediaCodecInfo> info = mcl->getCodecInfo(codecIdx);
+ Vector<AString> mimes;
+ info->getSupportedMimes(&mimes);
+ for (size_t i = 0; i < mimes.size(); i++) {
+ if (mimes[i].startsWith("video/")) {
+ mIsVideo = true;
+ break;
}
}
}
@@ -638,22 +652,10 @@
sp<AMessage> msg = new AMessage(kWhatInit, this);
msg->setString("name", name);
- msg->setInt32("nameIsType", nameIsType);
-
- if (nameIsType) {
- msg->setInt32("encoder", encoder);
- }
if (mAnalyticsItem != NULL) {
- if (nameIsType) {
- // name is the mime type
- mAnalyticsItem->setCString(kCodecMime, name.c_str());
- } else {
- mAnalyticsItem->setCString(kCodecCodec, name.c_str());
- }
+ mAnalyticsItem->setCString(kCodecCodec, name.c_str());
mAnalyticsItem->setCString(kCodecMode, mIsVideo ? kCodecModeVideo : kCodecModeAudio);
- if (nameIsType)
- mAnalyticsItem->setInt32(kCodecEncoder, encoder);
}
status_t err;
@@ -719,6 +721,7 @@
if (format->findInt32("level", &level)) {
mAnalyticsItem->setInt32(kCodecLevel, level);
}
+ mAnalyticsItem->setInt32(kCodecEncoder, (flags & CONFIGURE_FLAG_ENCODE) ? 1 : 0);
}
if (mIsVideo) {
@@ -743,8 +746,7 @@
}
// Prevent possible integer overflow in downstream code.
- if (mInitIsEncoder
- && (uint64_t)mVideoWidth * mVideoHeight > (uint64_t)INT32_MAX / 4) {
+ if ((uint64_t)mVideoWidth * mVideoHeight > (uint64_t)INT32_MAX / 4) {
ALOGE("buffer size is too big, width=%d, height=%d", mVideoWidth, mVideoHeight);
return BAD_VALUE;
}
@@ -1023,7 +1025,7 @@
mHaveInputSurface = false;
if (err == OK) {
- err = init(mInitName, mInitNameIsType, mInitIsEncoder);
+ err = init(mInitName);
}
return err;
}
@@ -1973,21 +1975,8 @@
AString name;
CHECK(msg->findString("name", &name));
- int32_t nameIsType;
- int32_t encoder = false;
- CHECK(msg->findInt32("nameIsType", &nameIsType));
- if (nameIsType) {
- CHECK(msg->findInt32("encoder", &encoder));
- }
-
sp<AMessage> format = new AMessage;
-
- if (nameIsType) {
- format->setString("mime", name.c_str());
- format->setInt32("encoder", encoder);
- } else {
- format->setString("componentName", name.c_str());
- }
+ format->setString("componentName", name.c_str());
mCodec->initiateAllocateComponent(format);
break;
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 54265a4..f595646 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -29,6 +29,7 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/MediaDefs.h>
+#include <media/stagefright/Codec2InfoBuilder.h>
#include <media/stagefright/MediaCodecList.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/OmxInfoBuilder.h>
@@ -77,6 +78,15 @@
}
OmxInfoBuilder sOmxInfoBuilder;
+Codec2InfoBuilder sCodec2InfoBuilder;
+
+std::initializer_list<MediaCodecListBuilderBase *> GetBuilders() {
+ if (property_get_bool("debug.stagefright.ccodec", false)) {
+ return {&sOmxInfoBuilder, &sCodec2InfoBuilder};
+ } else {
+ return {&sOmxInfoBuilder};
+ }
+}
} // unnamed namespace
@@ -88,7 +98,7 @@
ALOGV("Enter profilerThreadWrapper.");
remove(kProfilingResults); // remove previous result so that it won't be loaded to
// the new MediaCodecList
- sp<MediaCodecList> codecList(new MediaCodecList(&sOmxInfoBuilder));
+ sp<MediaCodecList> codecList(new MediaCodecList(GetBuilders()));
if (codecList->initCheck() != OK) {
ALOGW("Failed to create a new MediaCodecList, skipping codec profiling.");
return nullptr;
@@ -98,7 +108,7 @@
ALOGV("Codec profiling started.");
profileCodecs(infos, kProfilingResults);
ALOGV("Codec profiling completed.");
- codecList = new MediaCodecList(&sOmxInfoBuilder);
+ codecList = new MediaCodecList(GetBuilders());
if (codecList->initCheck() != OK) {
ALOGW("Failed to parse profiling results.");
return nullptr;
@@ -116,7 +126,7 @@
Mutex::Autolock autoLock(sInitMutex);
if (sCodecList == nullptr) {
- MediaCodecList *codecList = new MediaCodecList(&sOmxInfoBuilder);
+ MediaCodecList *codecList = new MediaCodecList(GetBuilders());
if (codecList->initCheck() == OK) {
sCodecList = codecList;
@@ -169,11 +179,28 @@
return sRemoteList;
}
-MediaCodecList::MediaCodecList(MediaCodecListBuilderBase* builder) {
+MediaCodecList::MediaCodecList(std::initializer_list<MediaCodecListBuilderBase*> builders) {
mGlobalSettings = new AMessage();
mCodecInfos.clear();
MediaCodecListWriter writer(this);
- mInitCheck = builder->buildMediaCodecList(&writer);
+ for (MediaCodecListBuilderBase *builder : builders) {
+ mInitCheck = builder->buildMediaCodecList(&writer);
+ if (mInitCheck != OK) {
+ break;
+ }
+ }
+ std::stable_sort(
+ mCodecInfos.begin(),
+ mCodecInfos.end(),
+ [](const sp<MediaCodecInfo> &info1, const sp<MediaCodecInfo> &info2) {
+ if (info2 == nullptr) {
+ return false;
+ } else if (info1 == nullptr) {
+ return true;
+ } else {
+ return info1->rank() < info2->rank();
+ }
+ });
}
MediaCodecList::~MediaCodecList() {
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 08331ad..20881a4 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -692,7 +692,7 @@
size_t size = 0;
if (mbuf != NULL) {
- CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
+ CHECK(mbuf->meta_data().findInt64(kKeyTime, &timeUs));
if (mFirstSampleSystemTimeUs < 0ll) {
mFirstSampleSystemTimeUs = systemTime() / 1000;
if (mPausePending) {
@@ -715,7 +715,7 @@
mFirstSampleTimeUs = timeUs;
}
int64_t driftTimeUs = 0;
- if (mbuf->meta_data()->findInt64(kKeyDriftTime, &driftTimeUs)
+ if (mbuf->meta_data().findInt64(kKeyDriftTime, &driftTimeUs)
&& driftTimeUs) {
driftTimeUs = timeUs - mFirstSampleTimeUs - driftTimeUs;
}
@@ -937,7 +937,7 @@
decodingTimeUs = *(mDecodingTimeQueue.begin());
mDecodingTimeQueue.erase(mDecodingTimeQueue.begin());
}
- mbuf->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs);
+ mbuf->meta_data().setInt64(kKeyDecodingTime, decodingTimeUs);
ALOGV("[video] time %" PRId64 " us (%.2f secs), dts/pts diff %" PRId64,
timeUs, timeUs / 1E6, decodingTimeUs - timeUs);
@@ -947,18 +947,18 @@
CHECK(!mDriftTimeQueue.empty());
driftTimeUs = *(mDriftTimeQueue.begin());
mDriftTimeQueue.erase(mDriftTimeQueue.begin());
- mbuf->meta_data()->setInt64(kKeyDriftTime, driftTimeUs);
+ mbuf->meta_data().setInt64(kKeyDriftTime, driftTimeUs);
#endif // DEBUG_DRIFT_TIME
ALOGV("[audio] time %" PRId64 " us (%.2f secs), drift %" PRId64,
timeUs, timeUs / 1E6, driftTimeUs);
}
- mbuf->meta_data()->setInt64(kKeyTime, timeUs);
+ mbuf->meta_data().setInt64(kKeyTime, timeUs);
} else {
- mbuf->meta_data()->setInt64(kKeyTime, 0ll);
- mbuf->meta_data()->setInt32(kKeyIsCodecConfig, true);
+ mbuf->meta_data().setInt64(kKeyTime, 0ll);
+ mbuf->meta_data().setInt32(kKeyIsCodecConfig, true);
}
if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) {
- mbuf->meta_data()->setInt32(kKeyIsSyncFrame, true);
+ mbuf->meta_data().setInt32(kKeyIsSyncFrame, true);
}
memcpy(mbuf->data(), outbuf->data(), outbuf->size());
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index 543c274..f6c61a0 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -23,7 +23,6 @@
#include <media/MediaAnalyticsItem.h>
#include <media/MediaExtractor.h>
#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/FileSource.h>
#include <media/stagefright/InterfaceUtils.h>
#include <media/stagefright/MediaExtractorFactory.h>
#include <media/IMediaExtractor.h>
@@ -40,7 +39,7 @@
// static
sp<IMediaExtractor> MediaExtractorFactory::Create(
const sp<DataSource> &source, const char *mime) {
- ALOGV("MediaExtractorFactory::%s %s", __func__, mime);
+ ALOGV("MediaExtractorFactory::Create %s", mime);
if (!property_get_bool("media.stagefright.extractremote", true)) {
// local extractor
@@ -64,44 +63,6 @@
return NULL;
}
-// static
-sp<IMediaExtractor> MediaExtractorFactory::CreateFromFd(
- int fd, int64_t offset, int64_t length, const char *mime, sp<DataSource> *out) {
- ALOGV("MediaExtractorFactory::%s %s", __func__, mime);
-
- if (property_get_bool("media.stagefright.extractremote", true)) {
- // remote extractor
- ALOGV("get service manager");
- sp<IBinder> binder = defaultServiceManager()->getService(String16("media.extractor"));
-
- if (binder != 0) {
- sp<IMediaExtractorService> mediaExService(
- interface_cast<IMediaExtractorService>(binder));
- if (!FileSource::requiresDrm(fd, offset, length, nullptr /* mime */)) {
- ALOGD("FileSource remote");
- sp<IDataSource> remoteSource =
- mediaExService->makeIDataSource(fd, offset, length);
- ALOGV("IDataSource(FileSource): %p %d %lld %lld",
- remoteSource.get(), fd, (long long)offset, (long long)length);
- if (remoteSource.get() != nullptr) {
- // replace the caller's local source with remote source.
- *out = CreateDataSourceFromIDataSource(remoteSource);
- return mediaExService->makeExtractor(remoteSource, mime);
- } else {
- ALOGW("extractor service cannot make file source."
- " falling back to local file source.");
- }
- }
- // Falls back.
- } else {
- ALOGE("extractor service not running");
- return nullptr;
- }
- }
- *out = new FileSource(fd, offset, length);
- return Create(*out, mime);
-}
-
sp<IMediaExtractor> MediaExtractorFactory::CreateFromService(
const sp<DataSource> &source, const char *mime) {
diff --git a/media/libstagefright/MediaMuxer.cpp b/media/libstagefright/MediaMuxer.cpp
index 62daac8..23e543d 100644
--- a/media/libstagefright/MediaMuxer.cpp
+++ b/media/libstagefright/MediaMuxer.cpp
@@ -181,13 +181,13 @@
mediaBuffer->add_ref(); // Released in MediaAdapter::signalBufferReturned().
mediaBuffer->set_range(buffer->offset(), buffer->size());
- sp<MetaData> sampleMetaData = mediaBuffer->meta_data();
- sampleMetaData->setInt64(kKeyTime, timeUs);
+ MetaDataBase &sampleMetaData = mediaBuffer->meta_data();
+ sampleMetaData.setInt64(kKeyTime, timeUs);
// Just set the kKeyDecodingTime as the presentation time for now.
- sampleMetaData->setInt64(kKeyDecodingTime, timeUs);
+ sampleMetaData.setInt64(kKeyDecodingTime, timeUs);
if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) {
- sampleMetaData->setInt32(kKeyIsSyncFrame, true);
+ sampleMetaData.setInt32(kKeyIsSyncFrame, true);
}
sp<MediaAdapter> currentTrack = mTrackList[trackIndex];
diff --git a/media/libstagefright/MetaDataUtils.cpp b/media/libstagefright/MetaDataUtils.cpp
index ac1f33f..af8f539 100644
--- a/media/libstagefright/MetaDataUtils.cpp
+++ b/media/libstagefright/MetaDataUtils.cpp
@@ -24,33 +24,33 @@
namespace android {
-sp<MetaData> MakeAVCCodecSpecificData(const sp<ABuffer> &accessUnit) {
+bool MakeAVCCodecSpecificData(MetaDataBase &meta, const sp<ABuffer> &accessUnit) {
int32_t width;
int32_t height;
int32_t sarWidth;
int32_t sarHeight;
sp<ABuffer> csd = MakeAVCCodecSpecificData(accessUnit, &width, &height, &sarWidth, &sarHeight);
if (csd == nullptr) {
- return nullptr;
+ return false;
}
- sp<MetaData> meta = new MetaData;
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+ meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
- meta->setData(kKeyAVCC, kTypeAVCC, csd->data(), csd->size());
- meta->setInt32(kKeyWidth, width);
- meta->setInt32(kKeyHeight, height);
+ meta.setData(kKeyAVCC, kTypeAVCC, csd->data(), csd->size());
+ meta.setInt32(kKeyWidth, width);
+ meta.setInt32(kKeyHeight, height);
if (sarWidth > 0 && sarHeight > 0) {
- meta->setInt32(kKeySARWidth, sarWidth);
- meta->setInt32(kKeySARHeight, sarHeight);
+ meta.setInt32(kKeySARWidth, sarWidth);
+ meta.setInt32(kKeySARHeight, sarHeight);
}
- return meta;
+ return true;
}
-sp<MetaData> MakeAACCodecSpecificData(
+bool MakeAACCodecSpecificData(
+ MetaDataBase &meta,
unsigned profile, unsigned sampling_freq_index,
unsigned channel_configuration) {
if(sampling_freq_index > 11u) {
- return nullptr;
+ return false;
}
int32_t sampleRate;
int32_t channelCount;
@@ -91,15 +91,14 @@
csd[sizeof(kStaticESDS) + 1] =
((sampling_freq_index << 7) & 0x80) | (channel_configuration << 3);
- sp<MetaData> meta = new MetaData;
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
+ meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
- meta->setInt32(kKeySampleRate, sampleRate);
- meta->setInt32(kKeyChannelCount, channelCount);
+ meta.setInt32(kKeySampleRate, sampleRate);
+ meta.setInt32(kKeyChannelCount, channelCount);
- meta->setData(kKeyESDS, 0, csd, csdSize);
+ meta.setData(kKeyESDS, 0, csd, csdSize);
delete [] csd;
- return meta;
+ return true;
}
} // namespace android
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index c6cbb2f..540cf8c 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -525,10 +525,10 @@
mbuf->release();
continue;
}
- if (mbuf->meta_data()->findInt64(kKeyTime, &timeUs)) {
+ if (mbuf->meta_data().findInt64(kKeyTime, &timeUs)) {
info->mSamples.emplace_back(mbuf, timeUs);
} else {
- mbuf->meta_data()->dumpToLog();
+ mbuf->meta_data().dumpToLog();
info->mFinalResult = ERROR_MALFORMED;
mbuf->release();
releaseRemaining = true;
@@ -568,7 +568,7 @@
status_t NuMediaExtractor::appendVorbisNumPageSamples(
MediaBufferBase *mbuf, const sp<ABuffer> &buffer) {
int32_t numPageSamples;
- if (!mbuf->meta_data()->findInt32(
+ if (!mbuf->meta_data().findInt32(
kKeyValidSamples, &numPageSamples)) {
numPageSamples = -1;
}
@@ -580,7 +580,7 @@
uint32_t type;
const void *data;
size_t size, size2;
- if (mbuf->meta_data()->findData(kKeyEncryptedSizes, &type, &data, &size)) {
+ if (mbuf->meta_data().findData(kKeyEncryptedSizes, &type, &data, &size)) {
// Signal numPageSamples (a plain int32_t) is appended at the end,
// i.e. sizeof(numPageSamples) plain bytes + 0 encrypted bytes
if (SIZE_MAX - size < sizeof(int32_t)) {
@@ -598,9 +598,9 @@
int32_t zero = 0;
memcpy(adata, data, size);
memcpy(adata + size, &zero, sizeof(zero));
- mbuf->meta_data()->setData(kKeyEncryptedSizes, type, adata, newSize);
+ mbuf->meta_data().setData(kKeyEncryptedSizes, type, adata, newSize);
- if (mbuf->meta_data()->findData(kKeyPlainSizes, &type, &data, &size2)) {
+ if (mbuf->meta_data().findData(kKeyPlainSizes, &type, &data, &size2)) {
if (size2 != size) {
return ERROR_MALFORMED;
}
@@ -613,7 +613,7 @@
// append sizeof(numPageSamples) to plain sizes.
int32_t int32Size = sizeof(numPageSamples);
memcpy(adata + size, &int32Size, sizeof(int32Size));
- mbuf->meta_data()->setData(kKeyPlainSizes, type, adata, newSize);
+ mbuf->meta_data().setData(kKeyPlainSizes, type, adata, newSize);
}
return OK;
@@ -725,7 +725,7 @@
}
TrackInfo *info = &mSelectedTracks.editItemAt(minIndex);
- *sampleMeta = info->mSamples.begin()->mBuffer->meta_data();
+ *sampleMeta = new MetaData(info->mSamples.begin()->mBuffer->meta_data());
return OK;
}
diff --git a/media/libstagefright/OmxInfoBuilder.cpp b/media/libstagefright/OmxInfoBuilder.cpp
index a6ebadd..fe141ab 100644
--- a/media/libstagefright/OmxInfoBuilder.cpp
+++ b/media/libstagefright/OmxInfoBuilder.cpp
@@ -154,22 +154,22 @@
// codec name -> index into swCodecs/hwCodecs
std::map<hidl_string, std::unique_ptr<MediaCodecInfoWriter>>
swCodecName2Info, hwCodecName2Info;
- // owner name -> MediaCodecInfo
- // This map will be used to obtain the correct IOmx service(s) needed for
- // creating IOmxNode instances and querying capabilities.
- std::map<std::string, std::vector<sp<MediaCodecInfo> > >
- owner2CodecInfo;
- for (const auto& role : roles) {
- const auto& typeName = role.type;
+ char rank[PROPERTY_VALUE_MAX];
+ uint32_t defaultRank = 0x100;
+ if (property_get("debug.stagefright.omx_default_rank", rank, nullptr)) {
+ defaultRank = std::strtoul(rank, nullptr, 10);
+ }
+ for (const IOmxStore::RoleInfo& role : roles) {
+ const hidl_string& typeName = role.type;
bool isEncoder = role.isEncoder;
bool preferPlatformNodes = role.preferPlatformNodes;
// If preferPlatformNodes is true, hardware nodes must be added after
// platform (software) nodes. hwCodecs is used to hold hardware nodes
// that need to be added after software nodes for the same role.
std::vector<const IOmxStore::NodeInfo*> hwCodecs;
- for (const auto& node : role.nodes) {
- const auto& nodeName = node.name;
+ for (const IOmxStore::NodeInfo& node : role.nodes) {
+ const hidl_string& nodeName = node.name;
bool isSoftware = hasPrefix(nodeName, "OMX.google");
MediaCodecInfoWriter* info;
if (isSoftware) {
@@ -182,6 +182,7 @@
info->setName(nodeName.c_str());
info->setOwner(node.owner.c_str());
info->setEncoder(isEncoder);
+ info->setRank(defaultRank);
} else {
// The node has been seen before. Simply retrieve the
// existing MediaCodecInfoWriter.
@@ -198,6 +199,7 @@
info->setName(nodeName.c_str());
info->setOwner(node.owner.c_str());
info->setEncoder(isEncoder);
+ info->setRank(defaultRank);
} else {
// If preferPlatformNodes is true, this node must be
// added after all software nodes.
@@ -224,9 +226,9 @@
// added in the loop above, but rather saved in hwCodecs. They are
// going to be added here.
if (preferPlatformNodes) {
- for (const auto& node : hwCodecs) {
+ for (const IOmxStore::NodeInfo *node : hwCodecs) {
MediaCodecInfoWriter* info;
- const auto& nodeName = node->name;
+ const hidl_string& nodeName = node->name;
auto c2i = hwCodecName2Info.find(nodeName);
if (c2i == hwCodecName2Info.end()) {
// Create a new MediaCodecInfo for a new node.
@@ -236,6 +238,7 @@
info->setName(nodeName.c_str());
info->setOwner(node->owner.c_str());
info->setEncoder(isEncoder);
+ info->setRank(defaultRank);
} else {
// The node has been seen before. Simply retrieve the
// existing MediaCodecInfoWriter.
diff --git a/media/libstagefright/RemoteMediaExtractor.cpp b/media/libstagefright/RemoteMediaExtractor.cpp
index 7efb91c..9d2c42b 100644
--- a/media/libstagefright/RemoteMediaExtractor.cpp
+++ b/media/libstagefright/RemoteMediaExtractor.cpp
@@ -57,13 +57,13 @@
// tracks (size_t)
mAnalyticsItem->setInt32(kExtractorTracks, ntracks);
// metadata
- sp<MetaData> pMetaData = extractor->getMetaData();
- if (pMetaData != nullptr) {
- String8 xx = pMetaData->toString();
+ MetaDataBase pMetaData;
+ if (extractor->getMetaData(pMetaData) == OK) {
+ String8 xx = pMetaData.toString();
// 'titl' -- but this verges into PII
// 'mime'
const char *mime = nullptr;
- if (pMetaData->findCString(kKeyMIMEType, &mime)) {
+ if (pMetaData.findCString(kKeyMIMEType, &mime)) {
mAnalyticsItem->setCString(kExtractorMime, mime);
}
// what else is interesting and not already available?
@@ -95,17 +95,25 @@
}
sp<IMediaSource> RemoteMediaExtractor::getTrack(size_t index) {
- MediaSourceBase *source = mExtractor->getTrack(index);
+ MediaTrack *source = mExtractor->getTrack(index);
return (source == nullptr)
? nullptr : CreateIMediaSourceFromMediaSourceBase(this, source, mExtractorPlugin);
}
sp<MetaData> RemoteMediaExtractor::getTrackMetaData(size_t index, uint32_t flags) {
- return mExtractor->getTrackMetaData(index, flags);
+ sp<MetaData> meta = new MetaData();
+ if (mExtractor->getTrackMetaData(*meta.get(), index, flags) == OK) {
+ return meta;
+ }
+ return nullptr;
}
sp<MetaData> RemoteMediaExtractor::getMetaData() {
- return mExtractor->getMetaData();
+ sp<MetaData> meta = new MetaData();
+ if (mExtractor->getMetaData(*meta.get()) == OK) {
+ return meta;
+ }
+ return nullptr;
}
status_t RemoteMediaExtractor::getMetrics(Parcel *reply) {
diff --git a/media/libstagefright/RemoteMediaSource.cpp b/media/libstagefright/RemoteMediaSource.cpp
index d038454..d07afec 100644
--- a/media/libstagefright/RemoteMediaSource.cpp
+++ b/media/libstagefright/RemoteMediaSource.cpp
@@ -22,7 +22,7 @@
RemoteMediaSource::RemoteMediaSource(
const sp<RemoteMediaExtractor> &extractor,
- MediaSourceBase *source,
+ MediaTrack *source,
const sp<RefBase> &plugin)
: mExtractor(extractor),
mSource(source),
@@ -42,7 +42,11 @@
}
sp<MetaData> RemoteMediaSource::getFormat() {
- return mSource->getFormat();
+ sp<MetaData> meta = new MetaData();
+ if (mSource->getFormat(*meta.get()) == OK) {
+ return meta;
+ }
+ return nullptr;
}
status_t RemoteMediaSource::read(
@@ -51,11 +55,11 @@
}
status_t RemoteMediaSource::pause() {
- return mSource->pause();
+ return ERROR_UNSUPPORTED;
}
-status_t RemoteMediaSource::setStopTimeUs(int64_t stopTimeUs) {
- return mSource->setStopTimeUs(stopTimeUs);
+status_t RemoteMediaSource::setStopTimeUs(int64_t /* stopTimeUs */) {
+ return ERROR_UNSUPPORTED;
}
////////////////////////////////////////////////////////////////////////////////
@@ -63,7 +67,7 @@
// static
sp<IMediaSource> RemoteMediaSource::wrap(
const sp<RemoteMediaExtractor> &extractor,
- MediaSourceBase *source, const sp<RefBase> &plugin) {
+ MediaTrack *source, const sp<RefBase> &plugin) {
if (source == nullptr) {
return nullptr;
}
diff --git a/media/libstagefright/SimpleDecodingSource.cpp b/media/libstagefright/SimpleDecodingSource.cpp
index f93a0b7..404c537 100644
--- a/media/libstagefright/SimpleDecodingSource.cpp
+++ b/media/libstagefright/SimpleDecodingSource.cpp
@@ -309,7 +309,7 @@
if (in_buf != NULL) {
int64_t timestampUs = 0;
- CHECK(in_buf->meta_data()->findInt64(kKeyTime, ×tampUs));
+ CHECK(in_buf->meta_data().findInt64(kKeyTime, ×tampUs));
if (in_buf->range_length() + (mIsVorbis ? 4 : 0) > in_buffer->capacity()) {
ALOGW("'%s' received %zu input bytes for buffer of size %zu",
mComponentName.c_str(),
@@ -321,7 +321,7 @@
if (mIsVorbis) {
int32_t numPageSamples;
- if (!in_buf->meta_data()->findInt32(kKeyValidSamples, &numPageSamples)) {
+ if (!in_buf->meta_data().findInt32(kKeyValidSamples, &numPageSamples)) {
numPageSamples = -1;
}
memcpy(in_buffer->base() + cpLen, &numPageSamples, sizeof(numPageSamples));
@@ -393,7 +393,7 @@
*buffer = new MediaBuffer(out_size);
CHECK_LE(out_buffer->size(), (*buffer)->size());
memcpy((*buffer)->data(), out_buffer->data(), out_buffer->size());
- (*buffer)->meta_data()->setInt64(kKeyTime, out_pts);
+ (*buffer)->meta_data().setInt64(kKeyTime, out_pts);
mCodec->releaseOutputBuffer(out_ix);
}
return OK;
diff --git a/media/libstagefright/codec2/SimpleC2Component.cpp b/media/libstagefright/codec2/SimpleC2Component.cpp
index c345783..333cfeb 100644
--- a/media/libstagefright/codec2/SimpleC2Component.cpp
+++ b/media/libstagefright/codec2/SimpleC2Component.cpp
@@ -226,7 +226,9 @@
releasing = std::move(state->mThread);
}
mExitRequested = true;
- releasing.join();
+ if (releasing.joinable()) {
+ releasing.join();
+ }
onRelease();
return C2_OK;
}
diff --git a/media/libstagefright/codec2/SimpleC2Interface.cpp b/media/libstagefright/codec2/SimpleC2Interface.cpp
index f082243..d159426 100644
--- a/media/libstagefright/codec2/SimpleC2Interface.cpp
+++ b/media/libstagefright/codec2/SimpleC2Interface.cpp
@@ -45,15 +45,38 @@
if (heapParams) {
heapParams->clear();
for (const auto &index : heapParamIndices) {
- if (index.coreIndex() != C2StreamFormatConfig::CORE_INDEX
- || !index.forStream()
- || index.stream() != 0u) {
- heapParams->push_back(nullptr);
- }
- if (index.forInput()) {
- heapParams->push_back(C2Param::Copy(mInputFormat));
- } else {
- heapParams->push_back(C2Param::Copy(mOutputFormat));
+ switch (index.type()) {
+ case C2StreamFormatConfig::input::PARAM_TYPE:
+ if (index.stream() == 0u) {
+ heapParams->push_back(C2Param::Copy(mInputFormat));
+ } else {
+ heapParams->push_back(nullptr);
+ }
+ break;
+ case C2StreamFormatConfig::output::PARAM_TYPE:
+ if (index.stream() == 0u) {
+ heapParams->push_back(C2Param::Copy(mOutputFormat));
+ } else {
+ heapParams->push_back(nullptr);
+ }
+ break;
+ case C2PortMimeConfig::input::PARAM_TYPE:
+ if (mInputMediaType) {
+ heapParams->push_back(C2Param::Copy(*mInputMediaType));
+ } else {
+ heapParams->push_back(nullptr);
+ }
+ break;
+ case C2PortMimeConfig::output::PARAM_TYPE:
+ if (mOutputMediaType) {
+ heapParams->push_back(C2Param::Copy(*mOutputMediaType));
+ } else {
+ heapParams->push_back(nullptr);
+ }
+ break;
+ default:
+ heapParams->push_back(nullptr);
+ break;
}
}
}
diff --git a/media/libstagefright/codec2/hidl/interfaces/1.0/Android.bp b/media/libstagefright/codec2/hidl/interfaces/1.0/Android.bp
new file mode 100644
index 0000000..e75ef24
--- /dev/null
+++ b/media/libstagefright/codec2/hidl/interfaces/1.0/Android.bp
@@ -0,0 +1,56 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_package_root {
+ name: "vendor.google.media.c2",
+ path: "frameworks/av/media/libstagefright/codec2/hidl/interfaces",
+}
+
+hidl_interface {
+ name: "vendor.google.media.c2@1.0",
+ root: "vendor.google.media.c2",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ "IComponent.hal",
+ "IComponentInterface.hal",
+ "IComponentListener.hal",
+ "IComponentStore.hal",
+ "IConfigurable.hal",
+ "IInputSurface.hal",
+ "IInputSurfaceConnection.hal",
+ ],
+ interfaces: [
+ "android.hardware.graphics.bufferqueue@1.0",
+ "android.hardware.graphics.common@1.0",
+ "android.hardware.media.bufferpool@1.0",
+ "android.hardware.media.omx@1.0",
+ "android.hardware.media@1.0",
+ "android.hidl.base@1.0",
+ ],
+ types: [
+ "Block",
+ "BlockId",
+ "Buffer",
+ "FieldDescriptor",
+ "FieldId",
+ "FieldSupportedValues",
+ "FieldSupportedValuesQuery",
+ "FieldSupportedValuesQueryResult",
+ "FieldType",
+ "FrameData",
+ "InfoBuffer",
+ "ParamDescriptor",
+ "ParamField",
+ "ParamFieldValues",
+ "SettingResult",
+ "Status",
+ "StructDescriptor",
+ "Work",
+ "WorkOrdinal",
+ "Worklet",
+ ],
+ gen_java: false,
+}
+
diff --git a/media/libstagefright/codec2/hidl/interfaces/1.0/IComponent.hal b/media/libstagefright/codec2/hidl/interfaces/1.0/IComponent.hal
new file mode 100644
index 0000000..b1b4fc2
--- /dev/null
+++ b/media/libstagefright/codec2/hidl/interfaces/1.0/IComponent.hal
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package vendor.google.media.c2@1.0;
+
+import android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer;
+import android.hardware.media.omx@1.0::IGraphicBufferSource;
+
+import IConfigurable;
+import IComponentInterface;
+import IComponentListener;
+import IInputSurface;
+
+/**
+ * Interface for a Codec 2.0 component corresponding to API level 1.0 or
+ * below. Components have two states: stopped and running. The running
+ * state has three sub-states: executing, tripped and error.
+ */
+interface IComponent extends IComponentInterface {
+
+ // METHODS AVAILABLE WHEN RUNNING
+ // =========================================================================
+
+ /**
+ * Queues up work for the component.
+ *
+ * This method must be supported in running (including tripped) states.
+ *
+ * This method must return within 1ms
+ *
+ * It is acceptable for this method to return OK and return an error value
+ * using the onWorkDone() callback.
+ *
+ * @param workBundle WorkBundle object containing Works to queue to the
+ * component.
+ * @return status Status of the call, which may be
+ * - OK - Works in \p workBundle were successfully queued.
+ * - BAD_INDEX - Some component(s) in some Work do(es) not exist.
+ * - CANNOT_DO - The components are not tunneled.
+ * - NO_MEMORY - Not enough memory to queue \p workBundle.
+ * - CORRUPTED - Some unknown error prevented queuing the Works.
+ * (unexpected).
+ */
+ queue(WorkBundle workBundle) generates (Status status);
+
+ /**
+ * Discards and abandons any pending work for the component.
+ *
+ * This method must be supported in running (including tripped) states.
+ *
+ * This method must return within 5ms.
+ *
+ * Work that could be immediately abandoned/discarded must be returned in
+ * \p flushedWorks; this can be done in an arbitrary order.
+ *
+ * Work that could not be abandoned or discarded immediately must be marked
+ * to be discarded at the earliest opportunity, and must be returned via
+ * the onWorkDone() callback. This must be completed within 500ms.
+ *
+ * @return status Status of the call, which may be
+ * - OK - The component has been successfully flushed.
+ * - TIMED_OUT - The flush could not be completed within the time limit.
+ * (unexpected)
+ * - CORRUPTED - Some unknown error prevented flushing from
+ * completion. (unexpected)
+ * @return flushedWorkBundle WorkBundle object containing flushed Works.
+ */
+ flush(
+ ) generates (
+ Status status,
+ WorkBundle flushedWorkBundle
+ );
+
+ /**
+ * Drains the component, and optionally downstream components. This is a
+ * signalling method; as such it does not wait for any work completion.
+ *
+ * Marks last work item as "drain-till-here", so component is notified not
+ * to wait for further work before it processes work already queued. This
+ * method can also be used to set the end-of-stream flag after work has been
+ * queued. Client can continue to queue further work immediately after this
+ * method returns.
+ *
+ * This method must be supported in running (including tripped) states.
+ *
+ * This method must return within 1ms.
+ *
+ * Work that is completed must be returned via the onWorkDone() callback.
+ *
+ * @param withEos Whether to drain the component with marking end-of-stream.
+ * @return status Status of the call, which may be
+ * - OK - The drain request has been successfully recorded.
+ * - TIMED_OUT - The flush could not be completed within the time limit.
+ * (unexpected)
+ * - CORRUPTED - Some unknown error prevented flushing from completion.
+ * (unexpected)
+ */
+ drain(bool withEos) generates (Status status);
+
+ /**
+ * Starts using a persistent input surface for a component.
+ *
+ * The component must be in running state.
+ *
+ * @param surface A persistent input surface to use for codec input.
+ * @return status Status of the call, which may be
+ * - OK - The operation completed successfully.
+ * - CANNOT_DO - The component does not support an input surface.
+ * - BAD_STATE - Component is not in running state.
+ * - DUPLICATE - The component is already connected to an input surface.
+ * - REFUSED - The input surface is already in use.
+ * - NO_MEMORY - Not enough memory to start the component.
+ * - TIMED_OUT - The component could not be connected within the time
+ * limit. (unexpected)
+ * - CORRUPTED - Some unknown error prevented connecting the component.
+ * (unexpected)
+ */
+ connectToInputSurface(IInputSurface surface) generates (Status status);
+
+ /**
+ * Starts using a persistent OMX input surface for a component.
+ *
+ * The component must be in running state.
+ *
+ * @param producer Producer component of an OMX persistent input surface.
+ * @param source Source component of an OMX persistent input surface.
+ * @return status Status of the call, which may be
+ * - OK - The operation completed successfully.
+ * - CANNOT_DO - The component does not support an input surface.
+ * - BAD_STATE - Component is not in running state.
+ * - DUPLICATE - The component is already connected to an input surface.
+ * - REFUSED - The input surface is already in use.
+ * - NO_MEMORY - Not enough memory to start the component.
+ * - TIMED_OUT - The component could not be connected within the time
+ * limit. (unexpected)
+ * - CORRUPTED - Some unknown error prevented connecting the component.
+ * (unexpected)
+ */
+ connectToOmxInputSurface(
+ IGraphicBufferProducer producer,
+ IGraphicBufferSource source
+ ) generates (Status status);
+
+ /**
+ * Stops using an input surface.
+ *
+ * This call is used for both Codec 2.0 and OMX input surfaces.
+ *
+ * The component must be in running state.
+ *
+ * @return status Status of the call, which may be
+ * - OK - The operation completed successfully.
+ * - CANNOT_DO - The component does not support an input surface.
+ * - BAD_STATE - Component is not in running state.
+ * - NOT_FOUND - The component is not connected to an input surface.
+ * - TIMED_OUT - The component could not be connected within the time
+ * limit. (unexpected)
+ * - CORRUPTED - Some unknown error prevented connecting the component.
+ * (unexpected)
+ */
+ disconnectFromInputSurface() generates (Status Status);
+
+ /**
+ * Creates a local block pool backed by the given allocator and returns its
+ * identifier.
+ *
+ * This call must return within 100 msec.
+ *
+ * @param allocatorId The Codec 2.0 allocator ID
+ * @return status Status of the call, which may be
+ * - OK - The operation completed successfully.
+ * - NO_MEMORY - Not enough memory to create the pool.
+ * - BAD_VALUE - Invalid allocator.
+ * - TIMED_OUT - The pool could not be created within the time
+ * limit. (unexpected)
+ * - CORRUPTED - Some unknown error prevented creating the pool.
+ * (unexpected)
+ * @return blockPoolId The Codec 2.0 blockpool ID for the created pool.
+ * @return configurable Configuration interface for the created pool.
+ */
+ createBlockPool(uint32_t allocatorId) generates (
+ Status status,
+ uint64_t blockPoolId,
+ IConfigurable configurable
+ );
+
+ // STATE CHANGE METHODS
+ // =========================================================================
+
+ /**
+ * Starts the component.
+ *
+ * This method must be supported in stopped state as well as tripped state.
+ *
+ * If the return value is OK, the component must be in the running state.
+ * If the return value is BAD_STATE or DUPLICATE, no state change is
+ * expected as a response to this call.
+ * Otherwise, the component must be in the stopped state.
+ *
+ * If a component is in the tripped state and start() is called while the
+ * component configuration still results in a trip, start must succeed and
+ * a new onTripped callback must be used to communicate the configuration
+ * conflict that results in the new trip.
+ *
+ * This method must return within 500ms.
+ *
+ * @return status Status of the call, which may be
+ * - OK - The component has started successfully.
+ * - BAD_STATE - Component is not in stopped or tripped state.
+ * - DUPLICATE - When called during another start call from another
+ * thread.
+ * - NO_MEMORY - Not enough memory to start the component.
+ * - TIMED_OUT - The component could not be started within the time limit.
+ * (unexpected)
+ * - CORRUPTED - Some unknown error prevented starting the component.
+ * (unexpected)
+ */
+ start() generates (Status status);
+
+ /**
+ * Stops the component.
+ *
+ * This method must be supported in running (including tripped) state.
+ *
+ * This method must return withing 500ms.
+ *
+ * Upon this call, all pending work must be abandoned.
+ * If the return value is BAD_STATE or DUPLICATE, no state change is
+ * expected as a response to this call.
+ * For all other return values, the component must be in the stopped state.
+ *
+ * This does not alter any settings and tunings that may have resulted in a
+ * tripped state.
+ *
+ * @return status Status of the call, which may be
+ * - OK - The component has stopped successfully.
+ * - BAD_STATE - Component is not in running state.
+ * - DUPLICATE - When called during another stop call from another thread.
+ * - TIMED_OUT - The component could not be stopped within the time limit.
+ * (unexpected)
+ * - CORRUPTED - Some unknown error prevented starting the component.
+ * (unexpected)
+ */
+ stop() generates (Status status);
+
+ /**
+ * Resets the component.
+ *
+ * This method must be supported in all (including tripped) states other
+ * than released.
+ *
+ * This method must be supported during any other blocking call.
+ *
+ * This method must return withing 500ms.
+ *
+ * After this call returns all work must have been abandoned, all references
+ * must have been released.
+ *
+ * If the return value is BAD_STATE or DUPLICATE, no state change is
+ * expected as a response to this call.
+ * For all other return values, the component shall be in the stopped state.
+ *
+ * This brings settings back to their default - "guaranteeing" no tripped
+ * state.
+ *
+ * @return status Status of the call, which may be
+ * - OK - The component has been reset.
+ * - BAD_STATE - Component is in released state.
+ * - DUPLICATE - When called during another reset call from another
+ * thread.
+ * - TIMED_OUT - The component could not be reset within the time limit.
+ * (unexpected)
+ * - CORRUPTED - Some unknown error prevented resetting the component.
+ * (unexpected)
+ */
+ reset() generates (Status status);
+
+ /**
+ * Releases the component.
+ *
+ * This method must be supported in stopped state.
+ *
+ * This method must return withing 500ms. Upon return all references must
+ * be abandoned.
+ *
+ * @return status Status of the call, which may be
+ * - OK - The component has been released.
+ * - BAD_STATE - The component is running.
+ * - DUPLICATE - The component is already released.
+ * - TIMED_OUT - The component could not be released within the time
+ * limit. (unexpected)
+ * - CORRUPTED - Some unknown error prevented releasing the component.
+ * (unexpected)
+ */
+ release() generates (Status status);
+
+};
+
diff --git a/media/libstagefright/codec2/hidl/interfaces/1.0/IComponentInterface.hal b/media/libstagefright/codec2/hidl/interfaces/1.0/IComponentInterface.hal
new file mode 100644
index 0000000..7014998
--- /dev/null
+++ b/media/libstagefright/codec2/hidl/interfaces/1.0/IComponentInterface.hal
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package vendor.google.media.c2@1.0;
+
+import IConfigurable;
+
+/**
+ * Component interface object. This object contains all of the configuration of
+ * a potential or actual component. It can be created and used independently of
+ * an actual Codec 2.0 component instance to query support and parameters for
+ * various component settings and configurations for a potential component.
+ * Actual components also expose this interface.
+ */
+interface IComponentInterface extends IConfigurable {
+ /*
+ * There are no additional methods to IConfigurable interface.
+ *
+ * Component interfaces have no states.
+ *
+ * The name of the component or component interface object is a unique name
+ * for that component or component interface 'class'; however, multiple
+ * instances of that component must have the same name.
+ */
+};
+
diff --git a/media/libstagefright/codec2/hidl/interfaces/1.0/IComponentListener.hal b/media/libstagefright/codec2/hidl/interfaces/1.0/IComponentListener.hal
new file mode 100644
index 0000000..d1a681a
--- /dev/null
+++ b/media/libstagefright/codec2/hidl/interfaces/1.0/IComponentListener.hal
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package vendor.google.media.c2@1.0;
+
+/**
+ * This callback interface is used for handling notifications from IComponent.
+ */
+interface IComponentListener {
+
+ /**
+ * Notify the listener that some works have been completed.
+ */
+ oneway onWorkDone(WorkBundle workBundle);
+
+ /**
+ * Notify the listener that the component is tripped.
+ */
+ oneway onTripped(vec<SettingResult> settingResults);
+
+ /**
+ * Notify the listener of an error.
+ *
+ * @param status The error type. \p status may be `OK`, which means that an
+ * error has occurred, but the error type is unknown.
+ * @param errorCode Additional error code. The framework may not recognize
+ * this.
+ */
+ oneway onError(Status status, uint32_t errorCode);
+
+};
+
diff --git a/media/libstagefright/codec2/hidl/interfaces/1.0/IComponentStore.hal b/media/libstagefright/codec2/hidl/interfaces/1.0/IComponentStore.hal
new file mode 100644
index 0000000..eae5b72
--- /dev/null
+++ b/media/libstagefright/codec2/hidl/interfaces/1.0/IComponentStore.hal
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package vendor.google.media.c2@1.0;
+
+import android.hardware.media.bufferpool@1.0::IClientManager;
+import IComponentInterface;
+import IComponentListener;
+import IComponent;
+import IConfigurable;
+import IInputSurface;
+
+interface IComponentStore extends IConfigurable {
+
+ /**
+ * Creates a component by name.
+ *
+ * This method must return within 100ms.
+ *
+ * @param name Name of the component to create. This should match one of the
+ * names returned by listComponents().
+ * @param listener The component listener to use for the component.
+ * @param pool The buffer pool client manager of the component listener.
+ * This must be null if the listener process does not own a buffer pool.
+ * @return status Status of the call, which may be
+ * - OK - The component was created successfully.
+ * - NOT_FOUND - There is no component with the given name.
+ * - NO_MEMORY - Not enough memory to create the component.
+ * - TIMED_OUT - The component could not be created within the time limit.
+ * (unexpected)
+ * - CORRUPTED - Some unknown error prevented the creation of the
+ * component. (unexpected)
+ * @return comp The created component if `Status = OK`.
+ */
+ createComponent(
+ string name,
+ IComponentListener listener,
+ IClientManager pool
+ ) generates (
+ Status status,
+ IComponent comp
+ );
+
+ /**
+ * Creates a component interface by name.
+ *
+ * This method must return within 100ms.
+ *
+ * @param name Name of the component interface to create. This should match
+ * one of the names returned by listComponents().
+ * @return status Status of the call, which may be
+ * - OK - The component interface was created successfully.
+ * - NOT_FOUND - There is no component interface with the given name.
+ * - NO_MEMORY - Not enough memory to create the component interface.
+ * - TIMED_OUT - The component interface could not be created within the
+ * time limit. (unexpected)
+ * - CORRUPTED - Some unknown error prevented the creation of the
+ * component interface. (unexpected)
+ * @return compIntf The created component interface if `Status = OK`.
+ */
+ createInterface(
+ string name
+ ) generates (
+ Status status,
+ IComponentInterface compIntf
+ );
+
+ /**
+ * Component traits.
+ */
+ struct ComponentTraits {
+ /**
+ * Name of the component.
+ */
+ string name;
+
+ enum Domain : uint32_t {
+ AUDIO,
+ VIDEO,
+ OTHER = 0xffffffff,
+ };
+ /**
+ * Component domain. The framework may not recognize `OTHER`.
+ */
+ Domain domain;
+ /**
+ * If #domain is `OTHER`, #domainOther can be used to provide additional
+ * information. Otherwise, #domainOther is ignored. The framework may
+ * not inspect this value.
+ */
+ uint32_t domainOther;
+
+ enum Kind : uint32_t {
+ DECODER,
+ ENCODER,
+ OTHER = 0xffffffff,
+ };
+ /**
+ * Component kind. The framework may not recognize `OTHER`.
+ */
+ Kind kind;
+ /**
+ * If #kind is `OTHER`, #kindOther can be used to provide additional
+ * information. Otherwise, #kindOther is ignored. The framework may not
+ * inspect this value.
+ */
+ uint32_t kindOther;
+
+ /**
+ * Rank used by MediaCodecList to determine component ordering. Lower
+ * value means higher priority.
+ */
+ uint32_t rank;
+
+ /**
+ * Media type.
+ */
+ string mediaType;
+
+ /**
+ * Aliases for component name for backward compatibility.
+ *
+ * \note Multiple components can have the same alias (but not the same
+ * component name) as long as their media types differ.
+ */
+ vec<string> aliases;
+ };
+
+ /**
+ * Returns the list of components supported by this component store.
+ *
+ * This method must return within 500ms.
+ *
+ * @return traits List of component traits for all components supported by this store in no
+ * particular order.
+ */
+ listComponents() generates (vec<ComponentTraits> traits);
+
+ /**
+ * Creates a persistent input surface that can be used as an input surface
+ * for any IComponent instance
+ *
+ * This method must return within 100ms.
+ *
+ * @return surface A persistent input surface
+ */
+ createInputSurface() generates (IInputSurface surface);
+
+ /**
+ * Returns a list of StructDescriptor object for a set of requested
+ * structures that this store is aware of.
+ *
+ * This operation must be performed at best effort, e.g. the component
+ * store must simply ignore all struct indices that it is not aware of.
+ *
+ * @param indices struct indices to return des
+ * @return status Status of the call, which may be
+ * - OK - The operation completed successfully.
+ * - NOT_FOUND - Some indices were not known.
+ * - NO_MEMORY - Not enough memory to complete this method.
+ * @return structs List of StructDescriptor objects.
+ */
+ getStructDescriptors(
+ vec<ParamIndex> indices
+ ) generates (
+ Status status,
+ vec<StructDescriptor> structs
+ );
+
+ /**
+ * Returns information required for using BufferPool API in buffer passing.
+ * If the returned pool is not null, the client can call registerSender() to
+ * register its IAccessor instance, hence allowing the client to send
+ * buffers to components hosted by this process.
+ *
+ * @return pool If the component store supports receiving buffers via
+ * BufferPool API, \p pool must be a valid `IClientManager` instance.
+ * Otherwise, \p pool must be null.
+ */
+ getPoolClientManager(
+ ) generates (
+ IClientManager pool
+ );
+
+ /**
+ * The store must copy the contents of \p src into \p dst without changing
+ * the format of \p dst.
+ *
+ * @param src Source buffer.
+ * @param dst Destination buffer.
+ * @return status Status of the call, which may be
+ * - OK - The copy is successful.
+ * - CANNOT_DO - \p src and \p dst are not compatible.
+ * - REFUSED - No permission to copy.
+ * - CORRUPTED - The copy cannot be done. (unexpected)
+ */
+ copyBuffer(Buffer src, Buffer dst) generates (Status status);
+
+};
+
diff --git a/media/libstagefright/codec2/hidl/interfaces/1.0/IConfigurable.hal b/media/libstagefright/codec2/hidl/interfaces/1.0/IConfigurable.hal
new file mode 100644
index 0000000..83447ad
--- /dev/null
+++ b/media/libstagefright/codec2/hidl/interfaces/1.0/IConfigurable.hal
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package vendor.google.media.c2@1.0;
+
+/**
+ * Generic configuration interface used by all configurable Codec 2.0
+ * components.
+ *
+ * This interface must be supported in all states of the inheriting
+ * object, and must not change the state of the inheriting object.
+ */
+interface IConfigurable {
+ /**
+ * Returns the name of this object. This must match the name that was
+ * supplied during the creation of the object.
+ *
+ * @return name Name of this object.
+ */
+ getName() generates (string name);
+
+ /**
+ * Queries a set of parameters from the object. Querying is performed at
+ * best effort: the object must query all supported parameters and skip
+ * unsupported ones, or parameters that could not be allocated. Any errors
+ * are communicated in the return value.
+ *
+ * \note Parameter values do not depend on the order of query.
+ *
+ * This method must return within 1ms if \p mayBlock is DONT_BLOCK, and
+ * within 5ms otherwise.
+ *
+ * @param indices List of param indices for params to be queried.
+ * @param mayBlock Whether this call may block or not.
+ * @return status Status of the call, which may be
+ * - OK - All parameters could be queried.
+ * - BAD_INDEX - All supported parameters could be queried, but some
+ * parameters were not supported.
+ * - NO_MEMORY - Could not allocate memory for a supported parameter.
+ * - BLOCKING - Querying some parameters requires blocking.
+ * - CORRUPTED - Some unknown error prevented the querying of the
+ * parameters. (unexpected)
+ * @return params List of params queried corresponding to \p indices.
+ */
+ query(
+ vec<ParamIndex> indices,
+ bool mayBlock
+ ) generates (
+ Status status,
+ Params params
+ );
+
+ /**
+ * Sets a set of parameters for the object. Tuning is performed at best
+ * effort: the object must update all supported configuration at best
+ * effort and skip unsupported parameters. Any errors are communicated in
+ * the return value and in \p failures.
+ *
+ * \note Parameter tuning DOES depend on the order of the tuning parameters.
+ * E.g. some parameter update may allow some subsequent parameter update.
+ *
+ * This method must return within 1ms if \p mayBlock is false, and within
+ * 5ms otherwise.
+ *
+ * @param inParams Requested parameter updates.
+ * @param mayBlock Whether this call may block or not.
+ * @return status Status of the call, which may be
+ * - OK - All parameters could be updated successfully.
+ * - BAD_INDEX - All supported parameters could be updated successfully,
+ * but some parameters were not supported.
+ * - NO_MEMORY - Some supported parameters could not be updated
+ * successfully because they contained unsupported values.
+ * These are returned in \p failures.
+ * - BLOCKING - Setting some parameters requires blocking.
+ * - CORRUPTED - Some unknown error prevented the update of the
+ * parameters. (unexpected)
+ * @return failures List of parameter failures.
+ * @return outParams Resulting values for the configured parameters.
+ */
+ config(
+ Params inParams,
+ bool mayBlock
+ ) generates (
+ Status status,
+ vec<SettingResult> failures,
+ Params outParams
+ );
+
+ // REFLECTION MECHANISM
+ // =========================================================================
+
+ /**
+ * Returns a selected range of the set of supported parameters.
+ *
+ * The set of supported parameters are represented in a vector with a
+ * start index of 0, and the selected range are indices into this vector.
+ * Fewer than \p count parameters are returned if the selected range is
+ * not fully/not at all part of the available vector indices.
+ *
+ * This method must return within 1ms.
+ *
+ * @param start start index of selected range
+ * @param count size of the selected
+ * @return status Status of the call, which may be
+ * - OK - The operation completed successfully.
+ * - NO_MEMORY - Not enough memory to complete this method.
+ * @return params Vector containing the selected range of supported
+ * parameters.
+ */
+ querySupportedParams(
+ uint32_t start,
+ uint32_t count
+ ) generates (
+ Status status,
+ vec<ParamDescriptor> params
+ );
+
+ /**
+ * Retrieves the supported values for the queried fields.
+ *
+ * Upon return the object must fill in the supported
+ * values for the fields listed as well as a status for each field.
+ * Object shall process all fields queried even if some queries fail.
+ *
+ * This method must return within 1ms if \p mayBlock is false, and within
+ * 5ms otherwise.
+ *
+ * @param inFields Vector of field queries.
+ * @param mayBlock Whether this call may block or not.
+ * @return status Status of the call, which may be
+ * - OK - The operation completed successfully.
+ * - BLOCKING - Querying some parameters requires blocking.
+ * - NO_MEMORY - Not enough memory to complete this method.
+ * - BAD_INDEX - At least one field was not recognized as a component
+ * field.
+ * @return outFields Vector containing supported values and query result
+ * for the selected fields.
+ */
+ querySupportedValues(
+ vec<FieldSupportedValuesQuery> inFields,
+ bool mayBlock
+ ) generates (
+ Status status,
+ vec<FieldSupportedValuesQueryResult> outFields
+ );
+
+};
+
diff --git a/media/libstagefright/codec2/hidl/interfaces/1.0/IInputSurface.hal b/media/libstagefright/codec2/hidl/interfaces/1.0/IInputSurface.hal
new file mode 100644
index 0000000..79dd65f
--- /dev/null
+++ b/media/libstagefright/codec2/hidl/interfaces/1.0/IInputSurface.hal
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package vendor.google.media.c2@1.0;
+
+import android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer;
+
+import IConfigurable;
+import IInputSurfaceConnection;
+
+/**
+ * Input surface that can be configured for the IComponent.
+ */
+interface IInputSurface extends IGraphicBufferProducer {
+
+ /**
+ * Connects this input surface to a component.
+ *
+ * This call must return within 100 ms.
+ *
+ * @param component The component to connect to. This must have type
+ * IComponent.
+ * @return status Status of the call, which may be
+ * - OK - The operation succeeded.
+ * - BAD_STATE - The component is in running state.
+ * - DUPLICATE - The surface is already connected to a component.
+ * - NO_MEMORY - Could not allocate memory to connect to the component.
+ * - CORRUPTED - Some unknown error prevented the connection. (unexpected)
+ * @return connection Connection object that is used to disconnect
+ * from the component.
+ */
+ connectToComponent(
+ interface component
+ ) generates (
+ Status status,
+ IInputSurfaceConnection connection
+ );
+
+ /**
+ * Returns the Codec 2.0 configuration object for this surface.
+ *
+ * @return configurable The configuration object for this surface.
+ */
+ getConfigurable() generates (IConfigurable configurable);
+
+};
+
diff --git a/media/libstagefright/codec2/hidl/interfaces/1.0/IInputSurfaceConnection.hal b/media/libstagefright/codec2/hidl/interfaces/1.0/IInputSurfaceConnection.hal
new file mode 100644
index 0000000..4deabb9
--- /dev/null
+++ b/media/libstagefright/codec2/hidl/interfaces/1.0/IInputSurfaceConnection.hal
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package vendor.google.media.c2@1.0;
+
+interface IInputSurfaceConnection {
+
+ /**
+ * Disconnects this input surface from the component.
+ *
+ * This call must return within 100 ms.
+ *
+ * @return status Status of the call, which may be
+ * - OK - The operation succeeded.
+ * - BAD_STATE - The component is not in running state.
+ * - NOT_FOUND - The surface is not connected to a component.
+ * - CORRUPTED - Some unknown error prevented the connection. (unexpected)
+ */
+ disconnect() generates (Status status);
+
+};
+
diff --git a/media/libstagefright/codec2/hidl/interfaces/1.0/types.hal b/media/libstagefright/codec2/hidl/interfaces/1.0/types.hal
new file mode 100644
index 0000000..65b7fec
--- /dev/null
+++ b/media/libstagefright/codec2/hidl/interfaces/1.0/types.hal
@@ -0,0 +1,581 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package vendor.google.media.c2@1.0;
+
+import android.hardware.media.bufferpool@1.0::BufferStatusMessage;
+
+enum Status : int32_t {
+ /** operation completed successfully */
+ OK = 0,
+
+ // bad input
+
+ /** argument has invalid value (user error) */
+ BAD_VALUE = -22,
+ /** argument uses invalid index (user error) */
+ BAD_INDEX = -75,
+ /** argument/index is valid but not possible */
+ CANNOT_DO = -2147483646,
+
+ // bad sequencing of events
+
+ /** object already exists */
+ DUPLICATE = -17,
+ /** object not found */
+ NOT_FOUND = -2,
+ /** operation is not permitted in the current state */
+ BAD_STATE = -38,
+ /** operation would block but blocking is not permitted */
+ BLOCKING = -9930,
+
+ // bad environment
+
+ /** not enough memory to complete operation */
+ NO_MEMORY = -12,
+ /** missing permission to complete operation */
+ REFUSED = -1,
+
+ /** operation did not complete within timeout */
+ TIMED_OUT = -110,
+
+ // missing functionality
+
+ /** operation is not implemented/supported (optional only) */
+ OMITTED = -74,
+
+ // unknown fatal
+
+ /** some unexpected error prevented the operation */
+ CORRUPTED = -2147483648,
+
+ // uninitialized
+
+ /** status has not been initialized */
+ NO_INIT = -19,
+};
+
+/**
+ * Codec 2.0 parameter index
+ */
+typedef uint32_t ParamIndex;
+
+/**
+ * Codec 2.0 parameter structure
+ *
+ * The description of a Params is provided by supplying a ParamIndex to
+ * IComponentStore::getStructDescriptors().
+ */
+typedef vec<uint8_t> Params;
+
+/**
+ * Struct uniquely specifying a field in an arbitrary parameter structure.
+ */
+struct FieldId {
+ /** Offset of the field in bytes */
+ uint32_t offset;
+ /** Size of the field in bytes */
+ uint32_t size;
+};
+
+/**
+ * Struct representing a location of a field in a parameter with a given index.
+ */
+struct ParamField {
+ /** Index of the parameter */
+ ParamIndex index;
+ /** Field identifier */
+ FieldId fieldId;
+};
+
+/**
+ * Struct describing basic properties of a parameter with a given index.
+ */
+struct ParamDescriptor {
+ /** Parameter index */
+ ParamIndex index;
+
+ enum Attrib : uint32_t {
+ IS_REQUIRED = 1u << 0,
+ IS_PERSISTENT = 1u << 1,
+ };
+ /** Parameter attributes */
+ bitfield<Attrib> attrib;
+
+ /** Parameter name */
+ string name;
+
+ /** index of other parameters that this parameter depends on */
+ vec<ParamIndex> dependencies;
+};
+
+// Generic way to describe supported numeric values for Codec 2.0 interfaces.
+
+/**
+ * An untyped value that can fit on 64 bits - the type of which is communicated
+ * via a separate channel (FieldType).
+ */
+typedef uint64_t PrimitiveValue;
+
+/*
+ * Generic supported values for a field.
+ *
+ * This can be either a range or a set of values. The range can be linear or
+ * geometric with clear minimum and maximum values, and can have an optional
+ * step size or geometric ratio. Values can optionally represent flags.
+ */
+struct FieldSupportedValues {
+ struct Range {
+ PrimitiveValue min;
+ PrimitiveValue max;
+ PrimitiveValue step;
+ PrimitiveValue num;
+ PrimitiveValue denom;
+ };
+
+ enum Type : int32_t {
+ /** No supported values */
+ EMPTY,
+ /** Numeric range that can be continuous or discrete */
+ RANGE,
+ /** List of values */
+ VALUES,
+ /** List of flags that can be OR-ed */
+ FLAGS,
+ /** Other representations */
+ OTHER = 0xffffffff,
+ };
+ /**
+ * Type of the supported values. The framework may not recognize `OTHER`.
+ */
+ Type type;
+ /**
+ * Codec2.0 type code of the supported values.
+ * * If #type is `OTHER`, #typeOther can be used to give more information.
+ * In this case, the interpretation of this structure is
+ * implementation-defined.
+ * * For all other values of #type, #typeOther is not used.
+ * The framework may not inspect this value.
+ */
+ int32_t typeOther;
+
+ /*
+ * If #type = EMPTY, #range and #value are unused.
+ */
+
+ /**
+ * If #type = RANGE, #range will specify the range of possible values.
+ *
+ * The intended type of members of #range will be clear in the context where
+ * FieldSupportedValues is used.
+ */
+ Range range;
+
+ /**
+ * If #type is `VALUES` or `FLAGS`, #value will list supported values.
+ *
+ * The intended type of components of #value will be clear in the context
+ * where FieldSupportedValues is used.
+ */
+ vec<PrimitiveValue> values;
+};
+
+/**
+ * Supported values for a specific field.
+ *
+ * This is a pair of the field specifier together with an optional supported
+ * values object. This structure is used when reporting parameter configuration
+ * failures and conflicts.
+ */
+struct ParamFieldValues {
+ /** the field or parameter */
+ ParamField paramOrField;
+
+ /**
+ * optional supported values for the field if paramOrField specifies an
+ * actual field that is numeric (non struct, blob or string). Supported
+ * values for arrays (including string and blobs) describe the supported
+ * values for each element (character for string, and bytes for blobs). It
+ * is optional for read-only strings and blobs.
+ */
+ vec<FieldSupportedValues> values;
+};
+
+/**
+ * Field descriptor.
+ */
+struct FieldDescriptor {
+
+ /** Field id */
+ FieldId fieldId;
+
+ /**
+ * Possible types of a field.
+ */
+ enum Type : uint32_t {
+ NO_INIT,
+ INT32,
+ UINT32,
+ CNTR32,
+ INT64,
+ UINT64,
+ CNTR64,
+ FLOAT,
+ /**
+ * Fixed-size string (POD)
+ */
+ STRING = 0x100,
+ /**
+ * blobs have no sub-elements and can be thought of as byte arrays.
+ * However, bytes cannot be individually addressed by clients.
+ */
+ BLOB,
+ /**
+ * Structs. Marked with this flag in addition to their coreIndex.
+ */
+ STRUCT_FLAG = 0x20000,
+ };
+ /**
+ * Type of the field.
+ */
+ bitfield<Type> type;
+
+ /** Extent of the field */
+ uint32_t length;
+ /*
+ * Note: the last member of a param struct can be of arbitrary length (e.g.
+ * if it is T[] array, which extends to the last byte of the parameter.)
+ * This is marked with extent 0.
+ */
+
+ /** Name of the field */
+ string name;
+ /** Named value type */
+ struct NamedValue {
+ string name;
+ PrimitiveValue value;
+ };
+ /** Named values for the field */
+ vec<NamedValue> namedValues;
+};
+
+/**
+ * Struct descriptor.
+ */
+struct StructDescriptor {
+ /** Struct type */
+ ParamIndex type;
+ /** Field descriptors for each field */
+ vec<FieldDescriptor> fields;
+};
+
+/**
+ * Information describing the reason a parameter settings may fail, or
+ * may be overriden.
+ */
+struct SettingResult {
+ /** Failure code (of Codec 2.0 SettingResult failure type) */
+ enum Failure : uint32_t {
+ /** Parameter is read-only and cannot be set. */
+ READ_ONLY,
+ /** Parameter mismatches input data. */
+ MISMATCH,
+ /** Parameter does not accept value. */
+ BAD_VALUE,
+ /** Parameter is not supported. */
+ BAD_TYPE,
+ /** Parameter is not supported on the specific port. */
+ BAD_PORT,
+ /** Parameter is not supported on the specific stream. */
+ BAD_INDEX,
+ /** Parameter is in conflict with an/other setting(s). */
+ CONFLICT,
+ /**
+ * Parameter is out of range due to other settings. (This failure mode
+ * can only be used for strict parameters.)
+ */
+ UNSUPPORTED,
+ /**
+ * Requested parameter value is in conflict with an/other setting(s)
+ * and has been corrected to the closest supported value. This failure
+ * mode is given to provide suggestion to the client as to how to enable
+ * the requested parameter value. */
+ INFO_CONFLICT,
+ /**
+ * This failure mode is reported when all the above failure modes do not
+ * apply.
+ */
+ OTHER = 0xffffffff,
+ };
+ /**
+ * The failure type. The framework might not recognize `OTHER`.
+ */
+ Failure failure;
+ /**
+ * The failure code.
+ * * If #failure is `OTHER`, #failureOther can be used to give more
+ * information.
+ * * For all other values of #failure, #failureOther is not used.
+ * The framework may not inspect this value.
+ */
+ uint32_t failureOther;
+
+ /**
+ * Failing (or corrected) field. Currently supported values for the field.
+ * This is set if different from the globally supported values (e.g. due to
+ * restrictions by another param or input data)
+ */
+ ParamFieldValues field;
+
+ /**
+ * Conflicting parameters or fields with
+ * (optional) suggested values for any conflicting fields to avoid the conflict.
+ */
+ vec<ParamFieldValues> conflicts;
+};
+
+/**
+ * Data structure for ordering Work objects. Each member is used for comparing
+ * urgency in the same fashion: a smaller value indicates that the associated
+ * Work object is more urgent.
+ */
+struct WorkOrdinal {
+ /**
+ * Timestamp in microseconds - can wrap around.
+ */
+ uint64_t timestampUs;
+ /**
+ * Frame index - can wrap around.
+ */
+ uint64_t frameIndex;
+ /**
+ * Component specific frame ordinal - can wrap around.
+ */
+ uint64_t customOrdinal;
+};
+
+/**
+ * A structure that holds information of a Block. There are two types of Blocks:
+ * NATIVE and POOLED. Each type has its own way of identifying blocks.
+ */
+struct BaseBlock {
+ enum Type : int32_t {
+ NATIVE,
+ POOLED,
+ };
+ /**
+ * There are two types of blocks: NATIVE and POOLED.
+ */
+ Type type;
+
+ /**
+ * A "NATIVE" block is represented by a native handle.
+ */
+ handle nativeBlock;
+
+ /*
+ * A "POOLED" block is represented by `BufferStatusMessage`.
+ */
+ BufferStatusMessage pooledBlock;
+};
+
+/**
+ * A Block in transfer consists of an index into an array of BaseBlock plus some
+ * extra information. One BaseBlock may occur in multiple blocks in one
+ * `WorkBundle`.
+ */
+struct Block {
+ /**
+ * Identity of the BaseBlock within a WorkBundle. This is an index into the
+ * `baseBlocks` array of a `WorkBundle` object.
+ */
+ uint32_t index;
+ /**
+ * Metadata associated with the block.
+ */
+ Params meta;
+ /**
+ * Fence for synchronizing block access.
+ */
+ handle fence;
+};
+
+/**
+ * Type of buffers processed by a component.
+ */
+struct Buffer {
+ /**
+ * Metadata associated with the buffer.
+ */
+ Params info;
+ /**
+ * Blocks contained in the buffer.
+ */
+ vec<Block> blocks;
+};
+
+/**
+ * An extension of Buffer that also contains an index.
+ */
+struct InfoBuffer {
+ ParamIndex index;
+ Buffer buffer;
+};
+
+/**
+ * This structure represents a frame with its metadata. A frame consists of an
+ * ordered set of buffers, configuration changes, and info buffers along with
+ * some non-configuration metadata.
+ */
+struct FrameData {
+ enum Flags : uint32_t {
+ /**
+ * For input frames: no output frame will be generated when processing
+ * this frame, but metadata must still be processed.
+ * For output frames: this frame must be discarded but metadata is still
+ * valid.
+ */
+ DROP_FRAME = (1 << 0),
+ /**
+ * This frame is the last frame of the current stream. Further frames
+ * are part of a new stream.
+ */
+ END_OF_STREAM = (1 << 1),
+ /**
+ * This frame must be discarded with its metadata.
+ * This flag is only set by components - e.g. as a response to the flush
+ * command.
+ */
+ DISCARD_FRAME = (1 << 2),
+ /**
+ * This frame contains only codec-specific configuration data, and no
+ * actual access unit.
+ *
+ * \deprecated Pass codec configuration with the codec-specific
+ * configuration info together with the access unit.
+ */
+ CODEC_CONFIG = (1u << 31),
+ };
+
+ /**
+ * Frame flags.
+ */
+ bitfield<Flags> flags;
+
+ /**
+ * Ordinal of the frame.
+ */
+ WorkOrdinal ordinal;
+
+ /**
+ * Frame buffers.
+ */
+ vec<Buffer> buffers;
+
+ /**
+ * Params determining a configuration update.
+ */
+ Params configUpdate;
+
+ /**
+ * Info buffers.
+ */
+ vec<InfoBuffer> infoBuffers;
+};
+
+/**
+ * Struct for
+ */
+struct Worklet {
+ /**
+ * List of Params describing tunings.
+ */
+ vec<Params> tunings;
+
+ /**
+ * List of failures.
+ */
+ vec<SettingResult> failures;
+
+ /**
+ * Output frame data.
+ */
+ FrameData output;
+
+ /* Note: Component id is not necessary as tunneling is not supported. */
+};
+
+/**
+ * This structure holds information about a single work item. It must be passed
+ * by the client to the component.
+ */
+struct Work {
+ /**
+ * FrameData for the input. Indices of Blocks inside #input refer to
+ * BaseBlocks in the member `blocks` of the containing `WorkBundle`.
+ */
+ FrameData input;
+ /**
+ * Worklet. Indices of Blocks inside `worklet.output` refer to
+ * BaseBlocks in the member `blocks` of the containing `WorkBundle`.
+ */
+ Worklet worklet;
+ /**
+ * Whether the worklet was processed or not.
+ */
+ bool workletProcessed;
+ Status result;
+};
+
+/**
+ * This structure holds a list of Work objects and a list of BaseBlocks.
+ */
+struct WorkBundle {
+ /**
+ * A list of Work items.
+ */
+ vec<Work> works;
+ /**
+ * A list of blocks indexed by elements of #works.
+ */
+ vec<BaseBlock> baseBlocks;
+};
+
+/**
+ * This structure describes a query for supported values of a field. This is
+ * used as input to IConfigurable::queryFieldSupportedValues().
+ */
+struct FieldSupportedValuesQuery {
+ enum Type : uint32_t {
+ /** Query all possible values regardless of other settings */
+ POSSIBLE,
+ /** Query currently possible values given dependent settings */
+ CURRENT,
+ };
+
+ ParamField field;
+ Type type;
+};
+
+/**
+ * This structure is used to hold the result from
+ * IConfigurable::queryFieldSupportedValues().
+ */
+struct FieldSupportedValuesQueryResult {
+ Status status;
+ FieldSupportedValues values;
+};
+
diff --git a/media/libstagefright/codec2/include/C2Component.h b/media/libstagefright/codec2/include/C2Component.h
index 61fcfc0..dbcd82d 100644
--- a/media/libstagefright/codec2/include/C2Component.h
+++ b/media/libstagefright/codec2/include/C2Component.h
@@ -398,7 +398,7 @@
domain_t domain; ///< component domain (e.g. audio or video)
kind_t kind; ///< component kind (e.g. encoder, decoder or filter)
rank_t rank; ///< rank used to determine component ordering (the lower the sooner)
- C2StringLiteral mediaType; ///< media type supported by the component
+ C2String mediaType; ///< media type supported by the component
/**
* name alias(es) for backward compatibility.
diff --git a/media/libstagefright/codec2/include/SimpleC2Interface.h b/media/libstagefright/codec2/include/SimpleC2Interface.h
index b934f12..310096f 100644
--- a/media/libstagefright/codec2/include/SimpleC2Interface.h
+++ b/media/libstagefright/codec2/include/SimpleC2Interface.h
@@ -27,13 +27,9 @@
public:
inline Builder(
const char *name,
- c2_node_id_t id)
- : mIntf(new SimpleC2Interface(name, id)) {}
-
- inline Builder(
- const char *name,
c2_node_id_t id,
- std::function<void(::android::SimpleC2Interface*)> deleter)
+ std::function<void(C2ComponentInterface*)> deleter =
+ std::default_delete<C2ComponentInterface>())
: mIntf(new SimpleC2Interface(name, id), deleter) {}
inline Builder &inputFormat(C2FormatKind input) {
@@ -46,6 +42,28 @@
return *this;
}
+ inline Builder &inputMediaType(const char *mediaType, size_t maxLen = 128) {
+ mIntf->mInputMediaType = C2PortMimeConfig::input::AllocShared(maxLen);
+ std::strncpy(mIntf->mInputMediaType->m.value, mediaType, maxLen);
+ return *this;
+ }
+
+ inline Builder &outputMediaType(const char *mediaType, size_t maxLen = 128) {
+ mIntf->mOutputMediaType = C2PortMimeConfig::output::AllocShared(maxLen);
+ std::strncpy(mIntf->mOutputMediaType->m.value, mediaType, maxLen);
+ return *this;
+ }
+
+ template<size_t N>
+ inline Builder &inputMediaType(const char mediaType[N]) {
+ return inputMediaType(mediaType, N);
+ }
+
+ template<size_t N>
+ inline Builder &outputMediaType(const char mediaType[N]) {
+ return outputMediaType(mediaType, N);
+ }
+
inline std::shared_ptr<SimpleC2Interface> build() {
return mIntf;
}
@@ -89,6 +107,8 @@
const c2_node_id_t mId;
C2StreamFormatConfig::input mInputFormat;
C2StreamFormatConfig::output mOutputFormat;
+ std::shared_ptr<C2PortMimeConfig::input> mInputMediaType;
+ std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType;
SimpleC2Interface() = delete;
};
diff --git a/media/libstagefright/codec2/vndk/C2Store.cpp b/media/libstagefright/codec2/vndk/C2Store.cpp
index c4ed2f4..f612b4f 100644
--- a/media/libstagefright/codec2/vndk/C2Store.cpp
+++ b/media/libstagefright/codec2/vndk/C2Store.cpp
@@ -203,9 +203,17 @@
/**
* Creates an uninitialized component module.
*
+ * \param name[in] component name.
+ *
* \note Only used by ComponentLoader.
*/
- ComponentModule() : mInit(C2_NO_INIT) {}
+ ComponentModule()
+ : mInit(C2_NO_INIT),
+ mLibHandle(nullptr),
+ createFactory(nullptr),
+ destroyFactory(nullptr),
+ mComponentFactory(nullptr) {
+ }
/**
* Initializes a component module with a given library path. Must be called exactly once.
@@ -383,12 +391,35 @@
std::shared_ptr<C2ComponentInterface> intf;
c2_status_t res = createInterface(0, &intf);
if (res != C2_OK) {
+ ALOGD("failed to create interface: %d", res);
return nullptr;
}
std::shared_ptr<C2Component::Traits> traits(new (std::nothrow) C2Component::Traits);
if (traits) {
- // traits->name = intf->getName();
+ traits->name = intf->getName();
+ // TODO: get this from interface properly.
+ bool encoder = (traits->name.find("encoder") != std::string::npos);
+ uint32_t mediaTypeIndex = encoder ? C2PortMimeConfig::output::PARAM_TYPE
+ : C2PortMimeConfig::input::PARAM_TYPE;
+ std::vector<std::unique_ptr<C2Param>> params;
+ res = intf->query_vb({}, { mediaTypeIndex }, C2_MAY_BLOCK, ¶ms);
+ if (res != C2_OK) {
+ ALOGD("failed to query interface: %d", res);
+ return nullptr;
+ }
+ if (params.size() != 1u) {
+ ALOGD("failed to query interface: unexpected vector size: %zu", params.size());
+ return nullptr;
+ }
+ C2PortMimeConfig *mediaTypeConfig = (C2PortMimeConfig *)(params[0].get());
+ if (mediaTypeConfig == nullptr) {
+ ALOGD("failed to query media type");
+ return nullptr;
+ }
+ traits->mediaType = mediaTypeConfig->m.value;
+ // TODO: get this properly.
+ traits->rank = 0x200;
}
mTraits = traits;
diff --git a/media/libstagefright/codecs/aacdec/C2SoftAac.cpp b/media/libstagefright/codecs/aacdec/C2SoftAac.cpp
index 3f09e0a..c82ea45 100644
--- a/media/libstagefright/codecs/aacdec/C2SoftAac.cpp
+++ b/media/libstagefright/codecs/aacdec/C2SoftAac.cpp
@@ -25,6 +25,7 @@
#include <cutils/properties.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/MediaDefs.h>
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/MediaErrors.h>
#include <utils/misc.h>
@@ -50,12 +51,22 @@
namespace android {
-C2SoftAac::C2SoftAac(const char *name, c2_node_id_t id)
- : SimpleC2Component(
- SimpleC2Interface::Builder(name, id)
+constexpr char kComponentName[] = "c2.google.aac.decoder";
+
+static std::shared_ptr<C2ComponentInterface> BuildIntf(
+ const char *name, c2_node_id_t id,
+ std::function<void(C2ComponentInterface*)> deleter =
+ std::default_delete<C2ComponentInterface>()) {
+ return SimpleC2Interface::Builder(name, id, deleter)
.inputFormat(C2FormatCompressed)
.outputFormat(C2FormatAudio)
- .build()),
+ .inputMediaType(MEDIA_MIMETYPE_AUDIO_AAC)
+ .outputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
+ .build();
+}
+
+C2SoftAac::C2SoftAac(const char *name, c2_node_id_t id)
+ : SimpleC2Component(BuildIntf(name, id)),
mAACDecoder(NULL),
mStreamInfo(NULL),
mIsADTS(false),
@@ -333,6 +344,7 @@
const std::unique_ptr<C2Work> &work,
const std::shared_ptr<C2BlockPool> &pool) {
work->workletsProcessed = 0u;
+ work->result = C2_OK;
if (mSignalledError) {
return;
}
@@ -675,20 +687,18 @@
class C2SoftAacDecFactory : public C2ComponentFactory {
public:
virtual c2_status_t createComponent(
- c2_node_id_t id, std::shared_ptr<C2Component>* const component,
- std::function<void(::C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftAac("aac", id), deleter);
+ c2_node_id_t id,
+ std::shared_ptr<C2Component>* const component,
+ std::function<void(C2Component*)> deleter) override {
+ *component = std::shared_ptr<C2Component>(new C2SoftAac(kComponentName, id), deleter);
return C2_OK;
}
virtual c2_status_t createInterface(
- c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(::C2ComponentInterface*)> deleter) override {
- *interface =
- SimpleC2Interface::Builder("aac", id, deleter)
- .inputFormat(C2FormatCompressed)
- .outputFormat(C2FormatVideo)
- .build();
+ c2_node_id_t id,
+ std::shared_ptr<C2ComponentInterface>* const interface,
+ std::function<void(C2ComponentInterface*)> deleter) override {
+ *interface = BuildIntf(kComponentName, id, deleter);
return C2_OK;
}
diff --git a/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp b/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp
index 74f5a7a..70f6817 100644
--- a/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp
+++ b/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp
@@ -22,20 +22,31 @@
#include <C2PlatformSupport.h>
#include <SimpleC2Interface.h>
+#include <media/stagefright/foundation/MediaDefs.h>
#include <media/stagefright/foundation/hexdump.h>
#include "C2SoftAacEnc.h"
namespace android {
+constexpr char kComponentName[] = "c2.google.aac.encoder";
+
+static std::shared_ptr<C2ComponentInterface> BuildIntf(
+ const char *name, c2_node_id_t id,
+ std::function<void(C2ComponentInterface*)> deleter =
+ std::default_delete<C2ComponentInterface>()) {
+ return SimpleC2Interface::Builder(name, id, deleter)
+ .inputFormat(C2FormatAudio)
+ .outputFormat(C2FormatCompressed)
+ .inputMediaType(MEDIA_MIMETYPE_AUDIO_AAC)
+ .outputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
+ .build();
+}
+
C2SoftAacEnc::C2SoftAacEnc(
const char *name,
c2_node_id_t id)
- : SimpleC2Component(
- SimpleC2Interface::Builder(name, id)
- .inputFormat(C2FormatAudio)
- .outputFormat(C2FormatCompressed)
- .build()),
+ : SimpleC2Component(BuildIntf(name, id)),
mAACEncoder(NULL),
mNumChannels(1),
mSampleRate(44100),
@@ -176,6 +187,7 @@
void C2SoftAacEnc::process(
const std::unique_ptr<C2Work> &work,
const std::shared_ptr<C2BlockPool> &pool) {
+ work->result = C2_OK;
work->workletsProcessed = 0u;
if (mSignalledError) {
@@ -381,20 +393,17 @@
class C2SoftAacEncFactory : public C2ComponentFactory {
public:
virtual c2_status_t createComponent(
- c2_node_id_t id, std::shared_ptr<C2Component>* const component,
- std::function<void(::C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftAacEnc("aacenc", id), deleter);
+ c2_node_id_t id,
+ std::shared_ptr<C2Component>* const component,
+ std::function<void(C2Component*)> deleter) override {
+ *component = std::shared_ptr<C2Component>(new C2SoftAacEnc(kComponentName, id), deleter);
return C2_OK;
}
virtual c2_status_t createInterface(
c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(::C2ComponentInterface*)> deleter) override {
- *interface =
- SimpleC2Interface::Builder("aacenc", id, deleter)
- .inputFormat(C2FormatAudio)
- .outputFormat(C2FormatCompressed)
- .build();
+ std::function<void(C2ComponentInterface*)> deleter) override {
+ *interface = BuildIntf(kComponentName, id, deleter);
return C2_OK;
}
diff --git a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
index 3c09e37..b9ba251 100644
--- a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
+++ b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
@@ -54,7 +54,7 @@
#define PRINT_TIME ALOGV
-#define componentName "video_decoder.avc"
+constexpr char kComponentName[] = "c2.google.avc.decoder";
// #define codingType OMX_VIDEO_CodingAVC
#define CODEC_MIME_TYPE MEDIA_MIMETYPE_VIDEO_AVC
@@ -71,6 +71,18 @@
(IVD_CONTROL_API_COMMAND_TYPE_T)IH264D_CMD_CTL_SET_NUM_CORES
namespace {
+std::shared_ptr<C2ComponentInterface> BuildIntf(
+ const char *name, c2_node_id_t id,
+ std::function<void(C2ComponentInterface*)> deleter =
+ std::default_delete<C2ComponentInterface>()) {
+ return SimpleC2Interface::Builder(name, id, deleter)
+ .inputFormat(C2FormatCompressed)
+ .outputFormat(C2FormatVideo)
+ .inputMediaType(MEDIA_MIMETYPE_VIDEO_AVC)
+ .outputMediaType(MEDIA_MIMETYPE_VIDEO_RAW)
+ .build();
+}
+
#if 0
using SupportedValuesWithFields = C2SoftAvcDecIntf::SupportedValuesWithFields;
@@ -614,11 +626,7 @@
C2SoftAvcDec::C2SoftAvcDec(
const char *name,
c2_node_id_t id)
- : SimpleC2Component(
- SimpleC2Interface::Builder(name, id)
- .inputFormat(C2FormatCompressed)
- .outputFormat(C2FormatVideo)
- .build()),
+ : SimpleC2Component(BuildIntf(name, id)),
mCodecCtx(NULL),
mFlushOutBuffer(NULL),
mIvColorFormat(IV_YUV_420P),
@@ -1327,21 +1335,18 @@
class C2SoftAvcDecFactory : public C2ComponentFactory {
public:
virtual c2_status_t createComponent(
- c2_node_id_t id, std::shared_ptr<C2Component>* const component,
- std::function<void(::C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftAvcDec("avc", id), deleter);
+ c2_node_id_t id,
+ std::shared_ptr<C2Component>* const component,
+ std::function<void(C2Component*)> deleter) override {
+ *component = std::shared_ptr<C2Component>(new C2SoftAvcDec(kComponentName, id), deleter);
return C2_OK;
}
virtual c2_status_t createInterface(
- c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(::C2ComponentInterface*)> deleter) override {
- *interface =
- SimpleC2Interface::Builder("avc", id, deleter)
- .inputFormat(C2FormatCompressed)
- .outputFormat(C2FormatVideo)
- .build();
-// std::shared_ptr<C2ComponentInterface>(new C2SoftAvcDecIntf("avc", id), deleter);
+ c2_node_id_t id,
+ std::shared_ptr<C2ComponentInterface>* const interface,
+ std::function<void(C2ComponentInterface*)> deleter) override {
+ *interface = BuildIntf(kComponentName, id, deleter);
return C2_OK;
}
diff --git a/media/libstagefright/codecs/avcenc/C2SoftAvcEnc.cpp b/media/libstagefright/codecs/avcenc/C2SoftAvcEnc.cpp
index e105460..8fb8122 100644
--- a/media/libstagefright/codecs/avcenc/C2SoftAvcEnc.cpp
+++ b/media/libstagefright/codecs/avcenc/C2SoftAvcEnc.cpp
@@ -35,7 +35,9 @@
namespace android {
-#define ive_api_function ih264e_api_function
+#define ive_api_function ih264e_api_function
+
+constexpr char kComponentName[] = "c2.google.avc.encoder";
namespace {
@@ -55,6 +57,18 @@
return (size_t)cpuCoreCount;
}
+std::shared_ptr<C2ComponentInterface> BuildIntf(
+ const char *name, c2_node_id_t id,
+ std::function<void(C2ComponentInterface*)> deleter =
+ std::default_delete<C2ComponentInterface>()) {
+ return SimpleC2Interface::Builder(name, id, deleter)
+ .inputFormat(C2FormatVideo)
+ .outputFormat(C2FormatCompressed)
+ .inputMediaType(MEDIA_MIMETYPE_VIDEO_RAW)
+ .outputMediaType(MEDIA_MIMETYPE_VIDEO_AVC)
+ .build();
+}
+
void ConvertRGBToPlanarYUV(
uint8_t *dstY, size_t dstStride, size_t dstVStride,
const C2GraphicView &src) {
@@ -115,11 +129,7 @@
} // namespace
C2SoftAvcEnc::C2SoftAvcEnc(const char *name, c2_node_id_t id)
- : SimpleC2Component(
- SimpleC2Interface::Builder(name, id)
- .inputFormat(C2FormatVideo)
- .outputFormat(C2FormatCompressed)
- .build()),
+ : SimpleC2Component(BuildIntf(name, id)),
mUpdateFlag(0),
mIvVideoColorFormat(IV_YUV_420P),
mAVCEncProfile(IV_PROFILE_BASE),
@@ -1209,20 +1219,18 @@
class C2SoftAvcEncFactory : public C2ComponentFactory {
public:
virtual c2_status_t createComponent(
- c2_node_id_t id, std::shared_ptr<C2Component>* const component,
- std::function<void(::C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftAvcEnc("avcenc", id), deleter);
+ c2_node_id_t id,
+ std::shared_ptr<C2Component>* const component,
+ std::function<void(C2Component*)> deleter) override {
+ *component = std::shared_ptr<C2Component>(new C2SoftAvcEnc(kComponentName, id), deleter);
return C2_OK;
}
virtual c2_status_t createInterface(
- c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(::C2ComponentInterface*)> deleter) override {
- *interface =
- SimpleC2Interface::Builder("avcenc", id, deleter)
- .inputFormat(C2FormatVideo)
- .outputFormat(C2FormatCompressed)
- .build();
+ c2_node_id_t id,
+ std::shared_ptr<C2ComponentInterface>* const interface,
+ std::function<void(C2ComponentInterface*)> deleter) override {
+ *interface = BuildIntf(kComponentName, id, deleter);
return C2_OK;
}
diff --git a/media/libstagefright/codecs/cmds/codec2.cpp b/media/libstagefright/codecs/cmds/codec2.cpp
index 26f96c3..0ec1a77 100644
--- a/media/libstagefright/codecs/cmds/codec2.cpp
+++ b/media/libstagefright/codecs/cmds/codec2.cpp
@@ -309,8 +309,8 @@
break;
}
- sp<MetaData> meta = buffer->meta_data();
- CHECK(meta->findInt64(kKeyTime, ×tamp));
+ MetaDataBase &meta = buffer->meta_data();
+ CHECK(meta.findInt64(kKeyTime, ×tamp));
size = buffer->size();
data = buffer->data();
diff --git a/media/libstagefright/codecs/g711/dec/C2SoftG711.cpp b/media/libstagefright/codecs/g711/dec/C2SoftG711.cpp
index e830324..d296a3d 100644
--- a/media/libstagefright/codecs/g711/dec/C2SoftG711.cpp
+++ b/media/libstagefright/codecs/g711/dec/C2SoftG711.cpp
@@ -24,21 +24,37 @@
#include <SimpleC2Interface.h>
#include <media/stagefright/foundation/ADebug.h>
-
-#ifdef ALAW
-#define COMPONENT_NAME "g711a"
-#else
-#define COMPONENT_NAME "g711m"
-#endif
+#include <media/stagefright/foundation/MediaDefs.h>
namespace android {
-C2SoftG711::C2SoftG711(const char *name, c2_node_id_t id)
- : SimpleC2Component(
- SimpleC2Interface::Builder(name, id)
+#ifdef ALAW
+constexpr char kComponentName[] = "c2.google.g711.alaw.decoder";
+#else
+constexpr char kComponentName[] = "c2.google.g711.mlaw.decoder";
+#endif
+
+static std::shared_ptr<C2ComponentInterface> BuildIntf(
+ const char *name, c2_node_id_t id,
+ std::function<void(C2ComponentInterface*)> deleter =
+ std::default_delete<C2ComponentInterface>()) {
+ return SimpleC2Interface::Builder(name, id, deleter)
.inputFormat(C2FormatCompressed)
.outputFormat(C2FormatAudio)
- .build()) {
+ .inputMediaType(
+#ifdef ALAW
+ MEDIA_MIMETYPE_AUDIO_G711_ALAW
+#else
+ MEDIA_MIMETYPE_AUDIO_G711_MLAW
+#endif
+ )
+ .outputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
+ .build();
+}
+
+
+C2SoftG711::C2SoftG711(const char *name, c2_node_id_t id)
+ : SimpleC2Component(BuildIntf(name, id)) {
}
C2SoftG711::~C2SoftG711() {
@@ -206,20 +222,17 @@
class C2SoftG711DecFactory : public C2ComponentFactory {
public:
virtual c2_status_t createComponent(
- c2_node_id_t id, std::shared_ptr<C2Component>* const component,
- std::function<void(::C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftG711(COMPONENT_NAME, id), deleter);
+ c2_node_id_t id,
+ std::shared_ptr<C2Component>* const component,
+ std::function<void(C2Component*)> deleter) override {
+ *component = std::shared_ptr<C2Component>(new C2SoftG711(kComponentName, id), deleter);
return C2_OK;
}
virtual c2_status_t createInterface(
c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(::C2ComponentInterface*)> deleter) override {
- *interface =
- SimpleC2Interface::Builder(COMPONENT_NAME, id, deleter)
- .inputFormat(C2FormatCompressed)
- .outputFormat(C2FormatAudio)
- .build();
+ std::function<void(C2ComponentInterface*)> deleter) override {
+ *interface = BuildIntf(kComponentName, id, deleter);
return C2_OK;
}
diff --git a/media/libstagefright/codecs/mp3dec/C2SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/C2SoftMP3.cpp
index 9e8b527..9cac87e 100644
--- a/media/libstagefright/codecs/mp3dec/C2SoftMP3.cpp
+++ b/media/libstagefright/codecs/mp3dec/C2SoftMP3.cpp
@@ -26,17 +26,28 @@
#include <SimpleC2Interface.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/MediaDefs.h>
#include <numeric>
namespace android {
-C2SoftMP3::C2SoftMP3(const char *name, c2_node_id_t id)
- : SimpleC2Component(
- SimpleC2Interface::Builder(name, id)
+constexpr char kComponentName[] = "c2.google.aac.encoder";
+
+static std::shared_ptr<C2ComponentInterface> BuildIntf(
+ const char *name, c2_node_id_t id,
+ std::function<void(C2ComponentInterface*)> deleter =
+ std::default_delete<C2ComponentInterface>()) {
+ return SimpleC2Interface::Builder(name, id, deleter)
.inputFormat(C2FormatCompressed)
.outputFormat(C2FormatAudio)
- .build()),
+ .inputMediaType(MEDIA_MIMETYPE_AUDIO_MPEG)
+ .outputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
+ .build();
+}
+
+C2SoftMP3::C2SoftMP3(const char *name, c2_node_id_t id)
+ : SimpleC2Component(BuildIntf(name, id)),
mConfig(nullptr),
mDecoderBuf(nullptr) {
}
@@ -397,20 +408,18 @@
class C2SoftMp3DecFactory : public C2ComponentFactory {
public:
virtual c2_status_t createComponent(
- c2_node_id_t id, std::shared_ptr<C2Component>* const component,
- std::function<void(::C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftMP3("mp3", id), deleter);
+ c2_node_id_t id,
+ std::shared_ptr<C2Component>* const component,
+ std::function<void(C2Component*)> deleter) override {
+ *component = std::shared_ptr<C2Component>(new C2SoftMP3(kComponentName, id), deleter);
return C2_OK;
}
virtual c2_status_t createInterface(
- c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(::C2ComponentInterface*)> deleter) override {
- *interface =
- SimpleC2Interface::Builder("mp3", id, deleter)
- .inputFormat(C2FormatCompressed)
- .outputFormat(C2FormatAudio)
- .build();
+ c2_node_id_t id,
+ std::shared_ptr<C2ComponentInterface>* const interface,
+ std::function<void(C2ComponentInterface*)> deleter) override {
+ *interface = BuildIntf(kComponentName, id, deleter);
return C2_OK;
}
diff --git a/media/libstagefright/data/media_codecs_google_c2.xml b/media/libstagefright/data/media_codecs_google_c2.xml
new file mode 100644
index 0000000..bb78013
--- /dev/null
+++ b/media/libstagefright/data/media_codecs_google_c2.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!-- Copyright 2018 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.
+-->
+<MediaCodecs>
+ <Include href="media_codecs_google_c2_audio.xml" />
+ <Include href="media_codecs_google_c2_video.xml" />
+</MediaCodecs>
diff --git a/media/libstagefright/data/media_codecs_google_c2_audio.xml b/media/libstagefright/data/media_codecs_google_c2_audio.xml
new file mode 100644
index 0000000..b86f4ad
--- /dev/null
+++ b/media/libstagefright/data/media_codecs_google_c2_audio.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<Included>
+ <Decoders>
+ <MediaCodec name="c2.google.mp3.decoder" type="audio/mpeg">
+ <Limit name="channel-count" max="2" />
+ <Limit name="sample-rate" ranges="8000,11025,12000,16000,22050,24000,32000,44100,48000" />
+ <Limit name="bitrate" range="8000-320000" />
+ </MediaCodec>
+ <MediaCodec name="c2.google.amrnb.decoder" type="audio/3gpp">
+ <Limit name="channel-count" max="1" />
+ <Limit name="sample-rate" ranges="8000" />
+ <Limit name="bitrate" range="4750-12200" />
+ </MediaCodec>
+ <MediaCodec name="c2.google.amrwb.decoder" type="audio/amr-wb">
+ <Limit name="channel-count" max="1" />
+ <Limit name="sample-rate" ranges="16000" />
+ <Limit name="bitrate" range="6600-23850" />
+ </MediaCodec>
+ <MediaCodec name="c2.google.aac.decoder" type="audio/mp4a-latm">
+ <Limit name="channel-count" max="8" />
+ <Limit name="sample-rate" ranges="7350,8000,11025,12000,16000,22050,24000,32000,44100,48000" />
+ <Limit name="bitrate" range="8000-960000" />
+ </MediaCodec>
+ <MediaCodec name="c2.google.g711.alaw.decoder" type="audio/g711-alaw">
+ <Limit name="channel-count" max="1" />
+ <Limit name="sample-rate" ranges="8000-48000" />
+ <Limit name="bitrate" range="64000" />
+ </MediaCodec>
+ <MediaCodec name="c2.google.g711.mlaw.decoder" type="audio/g711-mlaw">
+ <Limit name="channel-count" max="1" />
+ <Limit name="sample-rate" ranges="8000-48000" />
+ <Limit name="bitrate" range="64000" />
+ </MediaCodec>
+ <MediaCodec name="c2.google.vorbis.decoder" type="audio/vorbis">
+ <Limit name="channel-count" max="8" />
+ <Limit name="sample-rate" ranges="8000-96000" />
+ <Limit name="bitrate" range="32000-500000" />
+ </MediaCodec>
+ <MediaCodec name="c2.google.opus.decoder" type="audio/opus">
+ <Limit name="channel-count" max="8" />
+ <Limit name="sample-rate" ranges="48000" />
+ <Limit name="bitrate" range="6000-510000" />
+ </MediaCodec>
+ <MediaCodec name="c2.google.raw.decoder" type="audio/raw">
+ <Limit name="channel-count" max="8" />
+ <Limit name="sample-rate" ranges="8000-96000" />
+ <Limit name="bitrate" range="1-10000000" />
+ </MediaCodec>
+ <MediaCodec name="c2.google.flac.decoder" type="audio/flac">
+ <Limit name="channel-count" max="8" />
+ <Limit name="sample-rate" ranges="1-655350" />
+ <Limit name="bitrate" range="1-21000000" />
+ </MediaCodec>
+ </Decoders>
+ <Encoders>
+ <MediaCodec name="c2.google.aac.encoder" type="audio/mp4a-latm">
+ <Limit name="channel-count" max="6" />
+ <Limit name="sample-rate" ranges="8000,11025,12000,16000,22050,24000,32000,44100,48000" />
+ <!-- also may support 64000, 88200 and 96000 Hz -->
+ <Limit name="bitrate" range="8000-960000" />
+ </MediaCodec>
+ <MediaCodec name="c2.google.amrnb.encoder" type="audio/3gpp">
+ <Limit name="channel-count" max="1" />
+ <Limit name="sample-rate" ranges="8000" />
+ <Limit name="bitrate" range="4750-12200" />
+ <Feature name="bitrate-modes" value="CBR" />
+ </MediaCodec>
+ <MediaCodec name="c2.google.amrwb.encoder" type="audio/amr-wb">
+ <Limit name="channel-count" max="1" />
+ <Limit name="sample-rate" ranges="16000" />
+ <Limit name="bitrate" range="6600-23850" />
+ <Feature name="bitrate-modes" value="CBR" />
+ </MediaCodec>
+ <MediaCodec name="c2.google.flac.encoder" type="audio/flac">
+ <Limit name="channel-count" max="2" />
+ <Limit name="sample-rate" ranges="1-655350" />
+ <Limit name="bitrate" range="1-21000000" />
+ <Limit name="complexity" range="0-8" default="5" />
+ <Feature name="bitrate-modes" value="CQ" />
+ </MediaCodec>
+ </Encoders>
+</Included>
diff --git a/media/libstagefright/data/media_codecs_google_c2_video.xml b/media/libstagefright/data/media_codecs_google_c2_video.xml
new file mode 100644
index 0000000..593463b
--- /dev/null
+++ b/media/libstagefright/data/media_codecs_google_c2_video.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<Included>
+ <Decoders>
+ <MediaCodec name="c2.google.mpeg4.decoder" type="video/mp4v-es">
+ <!-- profiles and levels: ProfileSimple : Level3 -->
+ <Limit name="size" min="2x2" max="352x288" />
+ <Limit name="alignment" value="2x2" />
+ <Limit name="block-size" value="16x16" />
+ <Limit name="blocks-per-second" range="12-11880" />
+ <Limit name="bitrate" range="1-384000" />
+ <Feature name="adaptive-playback" />
+ </MediaCodec>
+ <MediaCodec name="c2.google.h263.decoder" type="video/3gpp">
+ <!-- profiles and levels: ProfileBaseline : Level30, ProfileBaseline : Level45
+ ProfileISWV2 : Level30, ProfileISWV2 : Level45 -->
+ <Limit name="size" min="2x2" max="352x288" />
+ <Limit name="alignment" value="2x2" />
+ <Limit name="bitrate" range="1-384000" />
+ <Feature name="adaptive-playback" />
+ </MediaCodec>
+ <MediaCodec name="c2.google.avc.decoder" type="video/avc">
+ <!-- profiles and levels: ProfileHigh : Level52 -->
+ <Limit name="size" min="2x2" max="4080x4080" />
+ <Limit name="alignment" value="2x2" />
+ <Limit name="block-size" value="16x16" />
+ <Limit name="block-count" range="1-32768" /> <!-- max 4096x2048 equivalent -->
+ <Limit name="blocks-per-second" range="1-1966080" />
+ <Limit name="bitrate" range="1-48000000" />
+ <Feature name="adaptive-playback" />
+ </MediaCodec>
+ <MediaCodec name="c2.google.hevc.decoder" type="video/hevc">
+ <!-- profiles and levels: ProfileMain : MainTierLevel51 -->
+ <Limit name="size" min="2x2" max="4096x4096" />
+ <Limit name="alignment" value="2x2" />
+ <Limit name="block-size" value="8x8" />
+ <Limit name="block-count" range="1-196608" /> <!-- max 4096x3072 -->
+ <Limit name="blocks-per-second" range="1-2000000" />
+ <Limit name="bitrate" range="1-10000000" />
+ <Feature name="adaptive-playback" />
+ </MediaCodec>
+ <MediaCodec name="c2.google.vp8.decoder" type="video/x-vnd.on2.vp8">
+ <Limit name="size" min="2x2" max="2048x2048" />
+ <Limit name="alignment" value="2x2" />
+ <Limit name="block-size" value="16x16" />
+ <Limit name="block-count" range="1-16384" />
+ <Limit name="blocks-per-second" range="1-1000000" />
+ <Limit name="bitrate" range="1-40000000" />
+ <Feature name="adaptive-playback" />
+ </MediaCodec>
+ <MediaCodec name="c2.google.vp9.decoder" type="video/x-vnd.on2.vp9">
+ <Limit name="size" min="2x2" max="2048x2048" />
+ <Limit name="alignment" value="2x2" />
+ <Limit name="block-size" value="16x16" />
+ <Limit name="block-count" range="1-16384" />
+ <Limit name="blocks-per-second" range="1-500000" />
+ <Limit name="bitrate" range="1-40000000" />
+ <Feature name="adaptive-playback" />
+ </MediaCodec>
+ </Decoders>
+
+ <Encoders>
+ <MediaCodec name="c2.google.h263.encoder" type="video/3gpp">
+ <!-- profiles and levels: ProfileBaseline : Level45 -->
+ <Limit name="size" min="176x144" max="176x144" />
+ <Limit name="alignment" value="16x16" />
+ <Limit name="bitrate" range="1-128000" />
+ </MediaCodec>
+ <MediaCodec name="c2.google.avc.encoder" type="video/avc">
+ <!-- profiles and levels: ProfileBaseline : Level41 -->
+ <Limit name="size" min="16x16" max="2048x2048" />
+ <Limit name="alignment" value="2x2" />
+ <Limit name="block-size" value="16x16" />
+ <Limit name="block-count" range="1-8192" /> <!-- max 2048x1024 -->
+ <Limit name="blocks-per-second" range="1-245760" />
+ <Limit name="bitrate" range="1-12000000" />
+ <Feature name="intra-refresh" />
+ </MediaCodec>
+ <MediaCodec name="c2.google.mpeg4.encoder" type="video/mp4v-es">
+ <!-- profiles and levels: ProfileCore : Level2 -->
+ <Limit name="size" min="16x16" max="176x144" />
+ <Limit name="alignment" value="16x16" />
+ <Limit name="block-size" value="16x16" />
+ <Limit name="blocks-per-second" range="12-1485" />
+ <Limit name="bitrate" range="1-64000" />
+ </MediaCodec>
+ <MediaCodec name="c2.google.vp8.encoder" type="video/x-vnd.on2.vp8">
+ <!-- profiles and levels: ProfileMain : Level_Version0-3 -->
+ <Limit name="size" min="2x2" max="2048x2048" />
+ <Limit name="alignment" value="2x2" />
+ <Limit name="block-size" value="16x16" />
+ <!-- 2016 devices can encode at about 10fps at this block count -->
+ <Limit name="block-count" range="1-16384" />
+ <Limit name="bitrate" range="1-40000000" />
+ <Feature name="bitrate-modes" value="VBR,CBR" />
+ </MediaCodec>
+ <MediaCodec name="c2.google.vp9.encoder" type="video/x-vnd.on2.vp9">
+ <!-- profiles and levels: ProfileMain : Level_Version0-3 -->
+ <Limit name="size" min="2x2" max="2048x2048" />
+ <Limit name="alignment" value="2x2" />
+ <Limit name="block-size" value="16x16" />
+ <!-- 2016 devices can encode at about 8fps at this block count -->
+ <Limit name="block-count" range="1-3600" /> <!-- max 1280x720 -->
+ <Limit name="bitrate" range="1-40000000" />
+ <Feature name="bitrate-modes" value="VBR,CBR" />
+ </MediaCodec>
+ </Encoders>
+</Included>
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index 55fc680..5624f4a 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -2066,7 +2066,8 @@
CHECK_NE(channel_configuration, 0u);
bits.skipBits(2); // original_copy, home
- sp<MetaData> meta = MakeAACCodecSpecificData(
+ sp<MetaData> meta = new MetaData();
+ MakeAACCodecSpecificData(*meta,
profile, sampling_freq_index, channel_configuration);
meta->setInt32(kKeyIsADTS, true);
diff --git a/media/libstagefright/include/CallbackDataSource.h b/media/libstagefright/include/CallbackDataSource.h
index 32556d6..9f413cd 100644
--- a/media/libstagefright/include/CallbackDataSource.h
+++ b/media/libstagefright/include/CallbackDataSource.h
@@ -42,6 +42,7 @@
return mName;
}
virtual sp<DecryptHandle> DrmInitialization(const char *mime = NULL);
+ virtual sp<IDataSource> getIDataSource() const;
private:
sp<IDataSource> mIDataSource;
@@ -70,6 +71,7 @@
return mName;
}
virtual sp<DecryptHandle> DrmInitialization(const char *mime = NULL);
+ virtual sp<IDataSource> getIDataSource() const;
private:
// 2kb comes from experimenting with the time-to-first-frame from a MediaPlayer
diff --git a/media/libstagefright/include/FrameDecoder.h b/media/libstagefright/include/FrameDecoder.h
index c40324b..dfbe2cd 100644
--- a/media/libstagefright/include/FrameDecoder.h
+++ b/media/libstagefright/include/FrameDecoder.h
@@ -68,7 +68,7 @@
virtual status_t onInputReceived(
const sp<MediaCodecBuffer> &codecBuffer,
- const sp<MetaData> &sampleMeta,
+ MetaDataBase &sampleMeta,
bool firstSample,
uint32_t *flags) = 0;
@@ -123,7 +123,7 @@
virtual status_t onInputReceived(
const sp<MediaCodecBuffer> &codecBuffer,
- const sp<MetaData> &sampleMeta,
+ MetaDataBase &sampleMeta,
bool firstSample,
uint32_t *flags) override;
@@ -158,7 +158,7 @@
virtual status_t onInputReceived(
const sp<MediaCodecBuffer> &codecBuffer __unused,
- const sp<MetaData> &sampleMeta __unused,
+ MetaDataBase &sampleMeta __unused,
bool firstSample __unused,
uint32_t *flags __unused) override { return OK; }
diff --git a/media/libstagefright/include/media/stagefright/CCodec.h b/media/libstagefright/include/media/stagefright/CCodec.h
index 24ee0a3..3a2670d 100644
--- a/media/libstagefright/include/media/stagefright/CCodec.h
+++ b/media/libstagefright/include/media/stagefright/CCodec.h
@@ -83,7 +83,7 @@
void setInputSurface(const sp<PersistentSurface> &surface);
status_t setupInputSurface(const std::shared_ptr<InputSurfaceWrapper> &surface);
- void setDeadline(const TimePoint &deadline);
+ void setDeadline(const TimePoint &deadline, const char *name);
enum {
kWhatAllocate,
@@ -126,10 +126,25 @@
sp<AMessage> outputFormat;
};
+ struct NamedTimePoint {
+ inline void set(
+ const TimePoint &timePoint,
+ const char *name) {
+ mTimePoint = timePoint;
+ mName = name;
+ }
+
+ inline TimePoint get() const { return mTimePoint; }
+ inline const char *getName() const { return mName; }
+ private:
+ TimePoint mTimePoint;
+ const char *mName;
+ };
+
Mutexed<State> mState;
std::shared_ptr<CCodecBufferChannel> mChannel;
std::shared_ptr<C2Component::Listener> mListener;
- Mutexed<TimePoint> mDeadline;
+ Mutexed<NamedTimePoint> mDeadline;
Mutexed<Formats> mFormats;
Mutexed<std::list<std::unique_ptr<C2Work>>> mWorkDoneQueue;
diff --git a/media/libstagefright/include/media/stagefright/Codec2InfoBuilder.h b/media/libstagefright/include/media/stagefright/Codec2InfoBuilder.h
new file mode 100644
index 0000000..ea0b5c4
--- /dev/null
+++ b/media/libstagefright/include/media/stagefright/Codec2InfoBuilder.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_INFO_BUILDER_H_
+#define CODEC2_INFO_BUILDER_H_
+
+#include <media/stagefright/MediaCodecList.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+class Codec2InfoBuilder : public MediaCodecListBuilderBase {
+public:
+ Codec2InfoBuilder() = default;
+ status_t buildMediaCodecList(MediaCodecListWriter* writer) override;
+};
+
+} // namespace android
+
+#endif // CODEC2_INFO_BUILDER_H_
diff --git a/media/libstagefright/include/media/stagefright/InterfaceUtils.h b/media/libstagefright/include/media/stagefright/InterfaceUtils.h
index 568c735..f0ebd48 100644
--- a/media/libstagefright/include/media/stagefright/InterfaceUtils.h
+++ b/media/libstagefright/include/media/stagefright/InterfaceUtils.h
@@ -51,7 +51,7 @@
// Creates an IMediaSource wrapper to the given MediaSource.
sp<IMediaSource> CreateIMediaSourceFromMediaSourceBase(
const sp<RemoteMediaExtractor> &extractor,
- MediaSourceBase *source, const sp<RefBase> &plugin);
+ MediaTrack *source, const sp<RefBase> &plugin);
} // namespace android
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 0bc02af..e7faea5 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -334,8 +334,6 @@
// initial create parameters
AString mInitName;
- bool mInitNameIsType;
- bool mInitIsEncoder;
// configure parameter
sp<AMessage> mConfigureMsg;
@@ -370,14 +368,14 @@
MediaCodec(const sp<ALooper> &looper, pid_t pid, uid_t uid);
- static sp<CodecBase> GetCodecBase(const AString &name, bool nameIsType = false);
+ static sp<CodecBase> GetCodecBase(const AString &name);
static status_t PostAndAwaitResponse(
const sp<AMessage> &msg, sp<AMessage> *response);
void PostReplyWithError(const sp<AReplyToken> &replyID, int32_t err);
- status_t init(const AString &name, bool nameIsType, bool encoder);
+ status_t init(const AString &name);
void setState(State newState);
void returnBuffersToCodec(bool isReclaim = false);
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecList.h b/media/libstagefright/include/media/stagefright/MediaCodecList.h
index f2bd496..d46fe85 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecList.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecList.h
@@ -18,6 +18,8 @@
#define MEDIA_CODEC_LIST_H_
+#include <initializer_list>
+
#include <media/stagefright/foundation/ABase.h>
#include <media/stagefright/foundation/AString.h>
#include <media/IMediaCodecList.h>
@@ -94,9 +96,9 @@
/**
* This constructor will call `buildMediaCodecList()` from the given
- * `MediaCodecListBuilderBase` object.
+ * `MediaCodecListBuilderBase` objects.
*/
- MediaCodecList(MediaCodecListBuilderBase* builder);
+ MediaCodecList(std::initializer_list<MediaCodecListBuilderBase*> builders);
~MediaCodecList();
diff --git a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
index 90c66eb..fb9f5bd 100644
--- a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
+++ b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
@@ -33,12 +33,6 @@
public:
static sp<IMediaExtractor> Create(
const sp<DataSource> &source, const char *mime = NULL);
- // Creates media extractor from the given file descriptor. To avoid binder calls for
- // reading file data, this tries to create remote file source in extractor service.
- // If that fails, this falls back to local file source. The data source used for extractor
- // will be alsp returned with |out|.
- static sp<IMediaExtractor> CreateFromFd(
- int fd, int64_t offset, int64_t length, const char *mime, sp<DataSource> *out);
static sp<IMediaExtractor> CreateFromService(
const sp<DataSource> &source, const char *mime = NULL);
static void LoadPlugins(const ::std::string& apkPath);
diff --git a/media/libstagefright/include/media/stagefright/MetaDataBase.h b/media/libstagefright/include/media/stagefright/MetaDataBase.h
new file mode 120000
index 0000000..1e12193
--- /dev/null
+++ b/media/libstagefright/include/media/stagefright/MetaDataBase.h
@@ -0,0 +1 @@
+../../../../libmediaextractor/include/media/stagefright/MetaDataBase.h
\ No newline at end of file
diff --git a/media/libstagefright/include/media/stagefright/MetaDataUtils.h b/media/libstagefright/include/media/stagefright/MetaDataUtils.h
index 7c18bc2..3af2218 100644
--- a/media/libstagefright/include/media/stagefright/MetaDataUtils.h
+++ b/media/libstagefright/include/media/stagefright/MetaDataUtils.h
@@ -23,8 +23,8 @@
namespace android {
struct ABuffer;
-sp<MetaData> MakeAVCCodecSpecificData(const sp<ABuffer> &accessUnit);
-sp<MetaData> MakeAACCodecSpecificData(unsigned profile, unsigned sampling_freq_index,
+bool MakeAVCCodecSpecificData(MetaDataBase &meta, const sp<ABuffer> &accessUnit);
+bool MakeAACCodecSpecificData(MetaDataBase &meta, unsigned profile, unsigned sampling_freq_index,
unsigned channel_configuration);
} // namespace android
diff --git a/media/libstagefright/include/media/stagefright/RemoteDataSource.h b/media/libstagefright/include/media/stagefright/RemoteDataSource.h
index 4ddc5e3..e191e6a 100644
--- a/media/libstagefright/include/media/stagefright/RemoteDataSource.h
+++ b/media/libstagefright/include/media/stagefright/RemoteDataSource.h
@@ -31,6 +31,9 @@
if (source.get() == nullptr) {
return nullptr;
}
+ if (source->getIDataSource().get() != nullptr) {
+ return source->getIDataSource();
+ }
return new RemoteDataSource(source);
}
diff --git a/media/libstagefright/include/media/stagefright/RemoteMediaSource.h b/media/libstagefright/include/media/stagefright/RemoteMediaSource.h
index a9bf820..1d720af 100644
--- a/media/libstagefright/include/media/stagefright/RemoteMediaSource.h
+++ b/media/libstagefright/include/media/stagefright/RemoteMediaSource.h
@@ -28,7 +28,7 @@
public:
static sp<IMediaSource> wrap(
const sp<RemoteMediaExtractor> &extractor,
- MediaSourceBase *source,
+ MediaTrack *source,
const sp<RefBase> &plugin);
virtual ~RemoteMediaSource();
virtual status_t start(MetaData *params = NULL);
@@ -42,12 +42,12 @@
private:
sp<RemoteMediaExtractor> mExtractor;
- MediaSourceBase *mSource;
+ MediaTrack *mSource;
sp<RefBase> mExtractorPlugin;
explicit RemoteMediaSource(
const sp<RemoteMediaExtractor> &extractor,
- MediaSourceBase *source,
+ MediaTrack *source,
const sp<RefBase> &plugin);
DISALLOW_EVIL_CONSTRUCTORS(RemoteMediaSource);
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index d0b17e0..8488d10 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -203,23 +203,23 @@
}
MediaBufferBase *mediaBuffer = new MediaBuffer(buffer);
- sp<MetaData> bufmeta = mediaBuffer->meta_data();
+ MetaDataBase &bufmeta = mediaBuffer->meta_data();
- bufmeta->setInt64(kKeyTime, timeUs);
+ bufmeta.setInt64(kKeyTime, timeUs);
int32_t isSync;
if (buffer->meta()->findInt32("isSync", &isSync)) {
- bufmeta->setInt32(kKeyIsSyncFrame, isSync);
+ bufmeta.setInt32(kKeyIsSyncFrame, isSync);
}
sp<ABuffer> sei;
if (buffer->meta()->findBuffer("sei", &sei) && sei != NULL) {
- bufmeta->setData(kKeySEI, 0, sei->data(), sei->size());
+ bufmeta.setData(kKeySEI, 0, sei->data(), sei->size());
}
sp<ABuffer> mpegUserData;
if (buffer->meta()->findBuffer("mpegUserData", &mpegUserData) && mpegUserData != NULL) {
- bufmeta->setData(
+ bufmeta.setData(
kKeyMpegUserData, 0, mpegUserData->data(), mpegUserData->size());
}
@@ -234,18 +234,18 @@
CHECK(buffer->meta()->findBuffer("encBytes", &encBytesBuffer)
&& encBytesBuffer != NULL);
- bufmeta->setInt32(kKeyCryptoMode, cryptoMode);
+ bufmeta.setInt32(kKeyCryptoMode, cryptoMode);
uint8_t array[16] = {0};
- bufmeta->setData(kKeyCryptoIV, 0, array, 16);
+ bufmeta.setData(kKeyCryptoIV, 0, array, 16);
array[0] = (uint8_t) (cryptoKey & 0xff);
- bufmeta->setData(kKeyCryptoKey, 0, array, 16);
+ bufmeta.setData(kKeyCryptoKey, 0, array, 16);
- bufmeta->setData(kKeyPlainSizes, 0,
+ bufmeta.setData(kKeyPlainSizes, 0,
clearBytesBuffer->data(), clearBytesBuffer->size());
- bufmeta->setData(kKeyEncryptedSizes, 0,
+ bufmeta.setData(kKeyEncryptedSizes, 0,
encBytesBuffer->data(), encBytesBuffer->size());
}
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index 850face..59fba1a 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -633,7 +633,10 @@
mBuffer->setRange(0, mBuffer->size() - info.mLength);
if (mFormat == NULL) {
- mFormat = MakeAVCCodecSpecificData(accessUnit);
+ mFormat = new MetaData;
+ if (!MakeAVCCodecSpecificData(*mFormat, accessUnit)) {
+ mFormat.clear();
+ }
}
return accessUnit;
@@ -862,7 +865,7 @@
}
bits.skipBits(2); // original_copy, home
- mFormat = MakeAACCodecSpecificData(
+ MakeAACCodecSpecificData(*mFormat,
profile, sampling_freq_index, channel_configuration);
mFormat->setInt32(kKeyIsADTS, true);
@@ -1005,9 +1008,9 @@
return NULL;
}
if (mFormat == NULL) {
- mFormat = MakeAVCCodecSpecificData(mBuffer);
- if (mFormat == NULL) {
- ALOGI("Creating dummy AVC format for scrambled content");
+ mFormat = new MetaData;
+ if (!MakeAVCCodecSpecificData(*mFormat, mBuffer)) {
+ ALOGW("Creating dummy AVC format for scrambled content");
mFormat = new MetaData;
mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
mFormat->setInt32(kKeyWidth, 1280);
@@ -1167,7 +1170,10 @@
}
if (mFormat == NULL) {
- mFormat = MakeAVCCodecSpecificData(accessUnit);
+ mFormat = new MetaData;
+ if (!MakeAVCCodecSpecificData(*mFormat, accessUnit)) {
+ mFormat.clear();
+ }
}
if (mSampleDecryptor != NULL && shrunkBytes > 0) {
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index 3d9c791..895a4ce 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -667,7 +667,7 @@
actualSeekTimeUs = -1;
} else {
CHECK(buffer != NULL);
- CHECK(buffer->meta_data()->findInt64(kKeyTime, &actualSeekTimeUs));
+ CHECK(buffer->meta_data().findInt64(kKeyTime, &actualSeekTimeUs));
CHECK(actualSeekTimeUs >= 0);
buffer->release();
@@ -728,7 +728,7 @@
CHECK(buffer != NULL);
int64_t bufferTimeUs;
- CHECK(buffer->meta_data()->findInt64(kKeyTime, &bufferTimeUs));
+ CHECK(buffer->meta_data().findInt64(kKeyTime, &bufferTimeUs));
if (!CloseEnough(bufferTimeUs, actualSeekTimeUs)) {
printf("\n * Attempted seeking to %" PRId64 " us (%.2f secs)",
requestedSeekTimeUs, requestedSeekTimeUs / 1E6);
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index 4ce8a0c..0667df1 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -572,7 +572,7 @@
CHECK_GE(kMaxPacketSize, 12u + 2u);
int64_t timeUs;
- CHECK(mediaBuf->meta_data()->findInt64(kKeyTime, &timeUs));
+ CHECK(mediaBuf->meta_data().findInt64(kKeyTime, &timeUs));
uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100ll);
@@ -667,7 +667,7 @@
CHECK_GE(kMaxPacketSize, 12u + 2u);
int64_t timeUs;
- CHECK(mediaBuf->meta_data()->findInt64(kKeyTime, &timeUs));
+ CHECK(mediaBuf->meta_data().findInt64(kKeyTime, &timeUs));
uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100ll);
@@ -752,7 +752,7 @@
const bool isWide = (mMode == AMR_WB);
int64_t timeUs;
- CHECK(mediaBuf->meta_data()->findInt64(kKeyTime, &timeUs));
+ CHECK(mediaBuf->meta_data().findInt64(kKeyTime, &timeUs));
uint32_t rtpTime = mRTPTimeBase + (timeUs / (isWide ? 250 : 125));
// hexdump(mediaData, mediaLength);
diff --git a/media/libstagefright/webm/WebmFrameThread.cpp b/media/libstagefright/webm/WebmFrameThread.cpp
index 0d4c699..23269af 100644
--- a/media/libstagefright/webm/WebmFrameThread.cpp
+++ b/media/libstagefright/webm/WebmFrameThread.cpp
@@ -345,8 +345,8 @@
continue;
}
- sp<MetaData> md = buffer->meta_data();
- CHECK(md->findInt64(kKeyTime, ×tampUs));
+ MetaDataBase &md = buffer->meta_data();
+ CHECK(md.findInt64(kKeyTime, ×tampUs));
if (mStartTimeUs == kUninitialized) {
mStartTimeUs = timestampUs;
}
@@ -374,7 +374,7 @@
CHECK_GE(timestampUs, 0ll);
int32_t isSync = false;
- md->findInt32(kKeyIsSyncFrame, &isSync);
+ md.findInt32(kKeyIsSyncFrame, &isSync);
const sp<WebmFrame> f = new WebmFrame(
mType,
isSync,
diff --git a/packages/MediaComponents/res/drawable/ic_audiotrack.xml b/packages/MediaComponents/res/drawable/ic_audiotrack.xml
new file mode 100644
index 0000000..27c12b5
--- /dev/null
+++ b/packages/MediaComponents/res/drawable/ic_audiotrack.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M12,3v9.28c-0.47,-0.17 -0.97,-0.28 -1.5,-0.28C8.01,12 6,14.01 6,16.5S8.01,21 10.5,21c2.31,0 4.2,-1.75 4.45,-4H15V6h4V3h-7z"/>
+</vector>
diff --git a/packages/MediaComponents/res/drawable/ic_check.xml b/packages/MediaComponents/res/drawable/ic_check.xml
new file mode 100644
index 0000000..32f720b
--- /dev/null
+++ b/packages/MediaComponents/res/drawable/ic_check.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:pathData="M0 0h24v24H0z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z" />
+</vector>
\ No newline at end of file
diff --git a/packages/MediaComponents/res/drawable/ic_closed_caption_off.xml b/packages/MediaComponents/res/drawable/ic_closed_caption_off.xml
new file mode 100644
index 0000000..a79cd11
--- /dev/null
+++ b/packages/MediaComponents/res/drawable/ic_closed_caption_off.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:pathData="M0,0h24v24H0V0z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M19,5.5c0.27,0,0.5,0.23,0.5,0.5v12c0,0.27-0.23,0.5-0.5,0.5H5c-0.28,0-0.5-0.22-0.5-0.5V6c0-0.28,0.22-0.5,0.5-0.5H19
+M19,4H5C3.89,4,3,4.9,3,6v12c0,1.1,0.89,2,2,2h14c1.1,0,2-0.9,2-2V6C21,4.9,20.1,4,19,4L19,4z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M11,11H9.5v-0.5h-2v3h2V13H11v1c0,0.55-0.45,1-1,1H7c-0.55,0-1-0.45-1-1v-4c0-0.55,0.45-1,1-1h3c0.55,0,1,0.45,1,1V11z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M18,11h-1.5v-0.5h-2v3h2V13H18v1c0,0.55-0.45,1-1,1h-3c-0.55,0-1-0.45-1-1v-4c0-0.55,0.45-1,1-1h3c0.55,0,1,0.45,1,1V11z" />
+</vector>
\ No newline at end of file
diff --git a/packages/MediaComponents/res/drawable/ic_help.xml b/packages/MediaComponents/res/drawable/ic_help.xml
new file mode 100644
index 0000000..4d1d75d
--- /dev/null
+++ b/packages/MediaComponents/res/drawable/ic_help.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:pathData="M0 0h24v24H0z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1
+17h-2v-2h2v2zm2.07-7.75l-.9 .92 C13.45 12.9 13 13.5 13 15h-2v-.5c0-1.1 .45 -2.1
+1.17-2.83l1.24-1.26c.37-.36 .59 -.86 .59 -1.41 0-1.1-.9-2-2-2s-2 .9-2 2H8c0-2.21
+1.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25z" />
+</vector>
\ No newline at end of file
diff --git a/packages/MediaComponents/res/drawable/ic_high_quality.xml b/packages/MediaComponents/res/drawable/ic_high_quality.xml
new file mode 100644
index 0000000..e27d3e2
--- /dev/null
+++ b/packages/MediaComponents/res/drawable/ic_high_quality.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M19,4L5,4c-1.11,0 -2,0.9 -2,2v12c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,6c0,-1.1 -0.9,-2 -2,-2zM11,15L9.5,15v-2h-2v2L6,15L6,9h1.5v2.5h2L9.5,9L11,9v6zM18,14c0,0.55 -0.45,1 -1,1h-0.75v1.5h-1.5L14.75,15L14,15c-0.55,0 -1,-0.45 -1,-1v-4c0,-0.55 0.45,-1 1,-1h3c0.55,0 1,0.45 1,1v4zM14.5,13.5h2v-3h-2v3z"/>
+</vector>
\ No newline at end of file
diff --git a/packages/MediaComponents/res/drawable/ic_replay.xml b/packages/MediaComponents/res/drawable/ic_replay.xml
deleted file mode 100644
index 2bde120..0000000
--- a/packages/MediaComponents/res/drawable/ic_replay.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<vector android:height="40dp" android:viewportHeight="48.0"
- android:viewportWidth="48.0" android:width="40dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="#FFFFFF" android:pathData="M24,10V2L14,12l10,10v-8c6.63,0 12,5.37 12,12s-5.37,12 -12,12 -12,-5.37 -12,-12H8c0,8.84 7.16,16 16,16s16,-7.16 16,-16 -7.16,-16 -16,-16z"/>
-</vector>
diff --git a/packages/MediaComponents/res/drawable/ic_replay_circle_filled.xml b/packages/MediaComponents/res/drawable/ic_replay_circle_filled.xml
new file mode 100644
index 0000000..389396b
--- /dev/null
+++ b/packages/MediaComponents/res/drawable/ic_replay_circle_filled.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:pathData="M0,0h24v24H0V0z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:fillType="evenOdd"
+ android:pathData="M12,2C6.48,2,2,6.48,2,12c0,5.52,4.48,10,10,10c5.52,0,10-4.48,10-10
+C22,6.48,17.52,2,12,2z
+M18,12c0,3.31-2.69,6-6,6c-3.31,0-6-2.69-6-6h2c0,2.21,1.79,4,4,4s4-1.79,4-4s-1.79-4-4-4v3L8,7l4-4v3
+C15.31,6,18,8.69,18,12z" />
+</vector>
\ No newline at end of file
diff --git a/packages/MediaComponents/res/drawable/ic_sd.xml b/packages/MediaComponents/res/drawable/ic_sd.xml
new file mode 100644
index 0000000..decb6d2
--- /dev/null
+++ b/packages/MediaComponents/res/drawable/ic_sd.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:pathData="M0,0h24v24H0V0z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M19,3H5C3.89,3,3,3.9,3,5v14c0,1.1,0.89,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z
+M13,9h4c0.55,0,1,0.45,1,1v4 c0,0.55-0.45,1-1,1h-4V9z
+M9.5,13.5v-1H7c-0.55,0-1-0.45-1-1V10c0-0.55,0.45-1,1-1h3c0.55,0,1,0.45,1,1v1H9.5v-0.5h-2v1H10
+c0.55,0,1,0.45,1,1V14c0,0.55-0.45,1-1,1H7c-0.55,0-1-0.45-1-1v-1h1.5v0.5H9.5z
+M14.5,13.5h2v-3h-2V13.5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/MediaComponents/res/layout/media_controller.xml b/packages/MediaComponents/res/layout/media_controller.xml
index 73c1b38..38f139d 100644
--- a/packages/MediaComponents/res/layout/media_controller.xml
+++ b/packages/MediaComponents/res/layout/media_controller.xml
@@ -136,7 +136,7 @@
<RelativeLayout
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="44dp"
android:paddingLeft="15dp"
android:orientation="horizontal">
@@ -235,6 +235,4 @@
</LinearLayout>
</RelativeLayout>
-
-</LinearLayout>
-
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/MediaComponents/res/layout/settings_list.xml b/packages/MediaComponents/res/layout/settings_list.xml
new file mode 100644
index 0000000..37a3a60
--- /dev/null
+++ b/packages/MediaComponents/res/layout/settings_list.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2018 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.
+-->
+
+<ListView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="@dimen/MediaControlView2_settings_width"
+ android:layout_height="@dimen/MediaControlView2_settings_height"
+ android:divider="@null"
+ android:dividerHeight="0dp">
+</ListView>
\ No newline at end of file
diff --git a/packages/MediaComponents/res/layout/settings_list_item.xml b/packages/MediaComponents/res/layout/settings_list_item.xml
new file mode 100644
index 0000000..e7522b7
--- /dev/null
+++ b/packages/MediaComponents/res/layout/settings_list_item.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2018 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="@dimen/MediaControlView2_settings_width"
+ android:layout_height="@dimen/MediaControlView2_settings_height"
+ android:orientation="horizontal"
+ android:background="@color/black_transparent_70">
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/MediaControlView2_settings_height"
+ android:paddingRight="2dp"
+ android:gravity="center"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/check"
+ android:layout_width="@dimen/MediaControlView2_settings_icon_size"
+ android:layout_height="@dimen/MediaControlView2_settings_icon_size"
+ android:gravity="center"
+ android:paddingLeft="2dp"
+ android:src="@drawable/ic_check"/>
+
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_width="@dimen/MediaControlView2_settings_icon_size"
+ android:layout_height="@dimen/MediaControlView2_settings_icon_size"
+ android:gravity="center"
+ android:paddingLeft="2dp"/>
+ </LinearLayout>
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/MediaControlView2_settings_height"
+ android:gravity="center"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/main_text"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/MediaControlView2_text_width"
+ android:paddingLeft="2dp"
+ android:textColor="@color/white"
+ android:textSize="@dimen/MediaControlView2_settings_main_text_size"/>
+
+ <TextView
+ android:id="@+id/sub_text"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/MediaControlView2_text_width"
+ android:layout_below="@id/main_text"
+ android:paddingLeft="2dp"
+ android:textColor="@color/white_transparent_70"
+ android:textSize="@dimen/MediaControlView2_settings_sub_text_size"/>
+ </RelativeLayout>
+
+</LinearLayout>
+
diff --git a/packages/MediaComponents/res/values/colors.xml b/packages/MediaComponents/res/values/colors.xml
index 9e071d7..8ba069c 100644
--- a/packages/MediaComponents/res/values/colors.xml
+++ b/packages/MediaComponents/res/values/colors.xml
@@ -15,5 +15,8 @@
-->
<resources>
- <integer name="gray">0xff444444</integer>
+ <color name="gray">#808080</color>
+ <color name="white">#ffffff</color>
+ <color name="white_transparent_70">#B3ffffff</color>
+ <color name="black_transparent_70">#B3000000</color>
</resources>
\ No newline at end of file
diff --git a/packages/MediaComponents/res/values/dimens.xml b/packages/MediaComponents/res/values/dimens.xml
index 91241cd..b5ef626 100644
--- a/packages/MediaComponents/res/values/dimens.xml
+++ b/packages/MediaComponents/res/values/dimens.xml
@@ -40,4 +40,13 @@
<integer name="mr_controller_volume_group_list_fade_in_duration_ms">400</integer>
<!-- Group list fade out animation duration. -->
<integer name="mr_controller_volume_group_list_fade_out_duration_ms">200</integer>
+
+ <dimen name="MediaControlView2_settings_width">200dp</dimen>
+ <dimen name="MediaControlView2_settings_height">36dp</dimen>
+ <dimen name="MediaControlView2_settings_icon_size">28dp</dimen>
+ <dimen name="MediaControlView2_settings_offset">8dp</dimen>
+ <dimen name="MediaControlView2_text_width">18dp</dimen>
+
+ <dimen name="MediaControlView2_settings_main_text_size">12sp</dimen>
+ <dimen name="MediaControlView2_settings_sub_text_size">10sp</dimen>
</resources>
diff --git a/packages/MediaComponents/res/values/strings.xml b/packages/MediaComponents/res/values/strings.xml
index 333d400..5f9c78d 100644
--- a/packages/MediaComponents/res/values/strings.xml
+++ b/packages/MediaComponents/res/values/strings.xml
@@ -105,4 +105,11 @@
</string>
<!-- Placeholder text indicating that the user can press the button to go to an external website. -->
<string name="MediaControlView2_ad_text">Visit Advertiser</string>
+ <string name="MediaControlView2_cc_text">Closed caption</string>
+ <string name="MediaControlView2_audio_track_text">Audio track</string>
+ <string name="MediaControlView2_video_quality_text">Video quality</string>
+ <string name="MediaControlView2_video_quality_auto_text">Auto</string>
+ <string name="MediaControlView2_playback_speed_text">Playback speed</string>
+ <string name="MediaControlView2_playback_speed_normal_text">Normal</string>
+ <string name="MediaControlView2_help_text">Help & feedback</string>
</resources>
diff --git a/packages/MediaComponents/res/values/style.xml b/packages/MediaComponents/res/values/style.xml
index db5e8f3..299f16b 100644
--- a/packages/MediaComponents/res/values/style.xml
+++ b/packages/MediaComponents/res/values/style.xml
@@ -81,5 +81,4 @@
<style name="BottomBarButton.Mute">
<item name="android:src">@drawable/ic_mute</item>
</style>
-
</resources>
diff --git a/packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl b/packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl
index 9a0be7a..6a03989 100644
--- a/packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl
+++ b/packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl
@@ -47,12 +47,12 @@
//////////////////////////////////////////////////////////////////////////////////////////////
// Browser sepcific
//////////////////////////////////////////////////////////////////////////////////////////////
- void onGetRootResult(in Bundle rootHints, String rootMediaId, in Bundle rootExtra);
- void onItemLoaded(String mediaId, in Bundle result);
- void onChildrenChanged(String rootMediaId, int childCount, in Bundle extras);
- void onChildrenLoaded(String parentId, int page, int pageSize, in List<Bundle> result,
+ void onGetLibraryRootDone(in Bundle rootHints, String rootMediaId, in Bundle rootExtra);
+ void onGetItemDone(String mediaId, in Bundle result);
+ void onChildrenChanged(String rootMediaId, int itemCount, in Bundle extras);
+ void onGetChildrenDone(String parentId, int page, int pageSize, in List<Bundle> result,
in Bundle extras);
void onSearchResultChanged(String query, int itemCount, in Bundle extras);
- void onSearchResultLoaded(String query, int page, int pageSize, in List<Bundle> result,
+ void onGetSearchResultDone(String query, int page, int pageSize, in List<Bundle> result,
in Bundle extras);
}
diff --git a/packages/MediaComponents/src/com/android/media/MediaBrowser2Impl.java b/packages/MediaComponents/src/com/android/media/MediaBrowser2Impl.java
index c095187..9190dfc 100644
--- a/packages/MediaComponents/src/com/android/media/MediaBrowser2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaBrowser2Impl.java
@@ -180,23 +180,23 @@
}
}
- public void onGetRootResult(
+ public void onGetLibraryRootDone(
final Bundle rootHints, final String rootMediaId, final Bundle rootExtra) {
getCallbackExecutor().execute(() -> {
- mCallback.onGetRootResult(rootHints, rootMediaId, rootExtra);
+ mCallback.onGetLibraryRootDone(rootHints, rootMediaId, rootExtra);
});
}
- public void onItemLoaded(String mediaId, MediaItem2 item) {
+ public void onGetItemDone(String mediaId, MediaItem2 item) {
getCallbackExecutor().execute(() -> {
- mCallback.onItemLoaded(mediaId, item);
+ mCallback.onGetItemDone(mediaId, item);
});
}
- public void onChildrenLoaded(String parentId, int page, int pageSize, List<MediaItem2> result,
+ public void onGetChildrenDone(String parentId, int page, int pageSize, List<MediaItem2> result,
Bundle extras) {
getCallbackExecutor().execute(() -> {
- mCallback.onChildrenLoaded(parentId, page, pageSize, result, extras);
+ mCallback.onGetChildrenDone(parentId, page, pageSize, result, extras);
});
}
@@ -206,16 +206,16 @@
});
}
- public void onSearchResultLoaded(String query, int page, int pageSize, List<MediaItem2> result,
+ public void onGetSearchResultDone(String query, int page, int pageSize, List<MediaItem2> result,
Bundle extras) {
getCallbackExecutor().execute(() -> {
- mCallback.onSearchResultLoaded(query, page, pageSize, result, extras);
+ mCallback.onGetSearchResultDone(query, page, pageSize, result, extras);
});
}
- public void onChildrenChanged(final String parentId, int childCount, final Bundle extras) {
+ public void onChildrenChanged(final String parentId, int itemCount, final Bundle extras) {
getCallbackExecutor().execute(() -> {
- mCallback.onChildrenChanged(parentId, childCount, extras);
+ mCallback.onChildrenChanged(parentId, itemCount, extras);
});
}
}
diff --git a/packages/MediaComponents/src/com/android/media/MediaController2Impl.java b/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
index 77db355..13f9208 100644
--- a/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
@@ -118,16 +118,15 @@
@Override
public void initialize() {
- SessionToken2Impl impl = SessionToken2Impl.from(mToken);
// TODO(jaewan): More sanity checks.
- if (impl.getSessionBinder() == null) {
+ if (mToken.getType() == SessionToken2.TYPE_SESSION) {
+ // Session
+ mServiceConnection = null;
+ connectToSession(SessionToken2Impl.from(mToken).getSessionBinder());
+ } else {
// Session service
mServiceConnection = new SessionServiceConnection();
connectToService();
- } else {
- // Session
- mServiceConnection = null;
- connectToSession(impl.getSessionBinder());
}
}
@@ -466,11 +465,14 @@
}
@Override
- public void setCurrentPlaylistItem_impl(int index) {
+ public void skipToPlaylistItem_impl(MediaItem2 item) {
+ // TODO(jaewan): Implement this
+ /*
Bundle args = new Bundle();
- args.putInt(MediaSession2Stub.ARGUMENT_KEY_ITEM_INDEX, index);
+ args.putInt(MediaSession2Stub.ARGUMENT_KEY_ITEM_INDEX, item);
sendTransportControlCommand(
MediaSession2.COMMAND_CODE_PLAYBACK_SET_CURRENT_PLAYLIST_ITEM, args);
+ */
}
@Override
@@ -487,7 +489,7 @@
@Override
public void addPlaylistItem_impl(int index, MediaItem2 item) {
- // TODO(jaewan): Implement
+ // TODO(jaewan): Implement
}
@Override
@@ -514,6 +516,36 @@
sendTransportControlCommand(MediaSession2.COMMAND_CODE_PLAYBACK_SET_PLAYLIST_PARAMS, args);
}
+ @Override
+ public int getPlayerState_impl() {
+ // TODO(jaewan): Implement
+ return 0;
+ }
+
+ @Override
+ public long getPosition_impl() {
+ // TODO(jaewan): Implement
+ return 0;
+ }
+
+ @Override
+ public float getPlaybackSpeed_impl() {
+ // TODO(jaewan): Implement
+ return 0;
+ }
+
+ @Override
+ public long getBufferedPosition_impl() {
+ // TODO(jaewan): Implement
+ return 0;
+ }
+
+ @Override
+ public MediaItem2 getCurrentPlaylistItem_impl() {
+ // TODO(jaewan): Implement
+ return null;
+ }
+
void pushPlaybackStateChanges(final PlaybackState2 state) {
synchronized (mLock) {
mPlaybackState = state;
diff --git a/packages/MediaComponents/src/com/android/media/MediaLibraryService2Impl.java b/packages/MediaComponents/src/com/android/media/MediaLibraryService2Impl.java
index b9d2fa4..18ff1b9 100644
--- a/packages/MediaComponents/src/com/android/media/MediaLibraryService2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaLibraryService2Impl.java
@@ -21,9 +21,9 @@
import android.media.MediaLibraryService2;
import android.media.MediaLibraryService2.LibraryRoot;
import android.media.MediaLibraryService2.MediaLibrarySession;
-import android.media.MediaLibraryService2.MediaLibrarySessionBuilder;
-import android.media.MediaLibraryService2.MediaLibrarySessionCallback;
-import android.media.MediaPlayerInterface;
+import android.media.MediaLibraryService2.MediaLibrarySession.Builder;
+import android.media.MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback;
+import android.media.MediaPlayerBase;
import android.media.MediaSession2;
import android.media.MediaSession2.ControllerInfo;
import android.media.MediaSessionService2;
@@ -67,7 +67,7 @@
public static class MediaLibrarySessionImpl extends MediaSession2Impl
implements MediaLibrarySessionProvider {
public MediaLibrarySessionImpl(Context context,
- MediaPlayerInterface player, String id, VolumeProvider2 volumeProvider,
+ MediaPlayerBase player, String id, VolumeProvider2 volumeProvider,
PendingIntent sessionActivity, Executor callbackExecutor,
MediaLibrarySessionCallback callback) {
super(context, player, id, volumeProvider, sessionActivity, callbackExecutor, callback);
@@ -95,23 +95,23 @@
@Override
public void notifyChildrenChanged_impl(ControllerInfo controller, String parentId,
- int childCount, Bundle extras) {
+ int itemCount, Bundle extras) {
if (controller == null) {
throw new IllegalArgumentException("controller shouldn't be null");
}
if (parentId == null) {
throw new IllegalArgumentException("parentId shouldn't be null");
}
- getSessionStub().notifyChildrenChangedNotLocked(controller, parentId, childCount,
+ getSessionStub().notifyChildrenChangedNotLocked(controller, parentId, itemCount,
extras);
}
@Override
- public void notifyChildrenChanged_impl(String parentId, int childCount, Bundle extras) {
+ public void notifyChildrenChanged_impl(String parentId, int itemCount, Bundle extras) {
if (parentId == null) {
throw new IllegalArgumentException("parentId shouldn't be null");
}
- getSessionStub().notifyChildrenChangedNotLocked(parentId, childCount, extras);
+ getSessionStub().notifyChildrenChangedNotLocked(parentId, itemCount, extras);
}
@Override
@@ -130,10 +130,10 @@
public static class BuilderImpl
extends BuilderBaseImpl<MediaLibrarySession, MediaLibrarySessionCallback> {
- public BuilderImpl(Context context, MediaLibrarySessionBuilder instance,
- MediaPlayerInterface player, Executor callbackExecutor,
+ public BuilderImpl(MediaLibraryService2 service, Builder instance,
+ MediaPlayerBase player, Executor callbackExecutor,
MediaLibrarySessionCallback callback) {
- super(context, player);
+ super(service, player);
setSessionCallback_impl(callbackExecutor, callback);
}
diff --git a/packages/MediaComponents/src/com/android/media/MediaMetadata2Impl.java b/packages/MediaComponents/src/com/android/media/MediaMetadata2Impl.java
index 9088029..7b2ee32 100644
--- a/packages/MediaComponents/src/com/android/media/MediaMetadata2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaMetadata2Impl.java
@@ -38,16 +38,11 @@
public class MediaMetadata2Impl implements MediaMetadata2Provider {
private static final String TAG = "MediaMetadata2";
- /**
- * A {@link Bundle} extra.
- * @hide
- */
- public static final String METADATA_KEY_EXTRA = "android.media.metadata.EXTRA";
-
static final int METADATA_TYPE_LONG = 0;
static final int METADATA_TYPE_TEXT = 1;
static final int METADATA_TYPE_BITMAP = 2;
static final int METADATA_TYPE_RATING = 3;
+ static final int METADATA_TYPE_FLOAT = 4;
static final ArrayMap<String, Integer> METADATA_KEYS_TYPE;
static {
@@ -83,6 +78,8 @@
METADATA_KEYS_TYPE.put(METADATA_KEY_MEDIA_URI, METADATA_TYPE_TEXT);
METADATA_KEYS_TYPE.put(METADATA_KEY_ADVERTISEMENT, METADATA_TYPE_LONG);
METADATA_KEYS_TYPE.put(METADATA_KEY_DOWNLOAD_STATUS, METADATA_TYPE_LONG);
+ METADATA_KEYS_TYPE.put(METADATA_KEY_RADIO_FREQUENCY, METADATA_TYPE_FLOAT);
+ METADATA_KEYS_TYPE.put(METADATA_KEY_RADIO_CALLSIGN, METADATA_TYPE_TEXT);
}
private static final @TextKey
@@ -167,6 +164,11 @@
}
@Override
+ public float getFloat_impl(@FloatKey String key) {
+ return mBundle.getFloat(key);
+ }
+
+ @Override
public Bitmap getBitmap_impl(@BitmapKey String key) {
Bitmap bmp = null;
try {
@@ -179,9 +181,9 @@
}
@Override
- public Bundle getExtra_impl() {
+ public Bundle getExtras_impl() {
try {
- return mBundle.getBundle(METADATA_KEY_EXTRA);
+ return mBundle.getBundle(METADATA_KEY_EXTRAS);
} catch (Exception e) {
// ignore, value was not an bundle
Log.w(TAG, "Failed to retrieve an extra");
@@ -305,8 +307,20 @@
}
@Override
- public Builder setExtra_impl(Bundle bundle) {
- mBundle.putBundle(METADATA_KEY_EXTRA, bundle);
+ public Builder putFloat_impl(@FloatKey String key, float value) {
+ if (METADATA_KEYS_TYPE.containsKey(key)) {
+ if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_FLOAT) {
+ throw new IllegalArgumentException("The " + key
+ + " key cannot be used to put a float");
+ }
+ }
+ mBundle.putFloat(key, value);
+ return mInstance;
+ }
+
+ @Override
+ public Builder setExtras_impl(Bundle bundle) {
+ mBundle.putBundle(METADATA_KEY_EXTRAS, bundle);
return mInstance;
}
diff --git a/packages/MediaComponents/src/com/android/media/MediaSession2CallbackStub.java b/packages/MediaComponents/src/com/android/media/MediaSession2CallbackStub.java
index e174d91..2178ccd 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSession2CallbackStub.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSession2CallbackStub.java
@@ -209,7 +209,7 @@
// MediaBrowser specific
////////////////////////////////////////////////////////////////////////////////////////////
@Override
- public void onGetRootResult(Bundle rootHints, String rootMediaId, Bundle rootExtra)
+ public void onGetLibraryRootDone(Bundle rootHints, String rootMediaId, Bundle rootExtra)
throws RuntimeException {
final MediaBrowser2Impl browser;
try {
@@ -222,12 +222,12 @@
// TODO(jaewan): Revisit here. Could be a bug
return;
}
- browser.onGetRootResult(rootHints, rootMediaId, rootExtra);
+ browser.onGetLibraryRootDone(rootHints, rootMediaId, rootExtra);
}
@Override
- public void onItemLoaded(String mediaId, Bundle itemBundle) throws RuntimeException {
+ public void onGetItemDone(String mediaId, Bundle itemBundle) throws RuntimeException {
final MediaBrowser2Impl browser;
try {
browser = getBrowser();
@@ -239,12 +239,12 @@
// TODO(jaewan): Revisit here. Could be a bug
return;
}
- browser.onItemLoaded(mediaId,
+ browser.onGetItemDone(mediaId,
MediaItem2Impl.fromBundle(browser.getContext(), itemBundle));
}
@Override
- public void onChildrenLoaded(String parentId, int page, int pageSize,
+ public void onGetChildrenDone(String parentId, int page, int pageSize,
List<Bundle> itemBundleList, Bundle extras) throws RuntimeException {
final MediaBrowser2Impl browser;
try {
@@ -265,7 +265,7 @@
result.add(MediaItem2.fromBundle(browser.getContext(), bundle));
}
}
- browser.onChildrenLoaded(parentId, page, pageSize, result, extras);
+ browser.onGetChildrenDone(parentId, page, pageSize, result, extras);
}
@Override
@@ -286,7 +286,7 @@
}
@Override
- public void onSearchResultLoaded(String query, int page, int pageSize,
+ public void onGetSearchResultDone(String query, int page, int pageSize,
List<Bundle> itemBundleList, Bundle extras) throws RuntimeException {
final MediaBrowser2Impl browser;
try {
@@ -307,11 +307,11 @@
result.add(MediaItem2.fromBundle(browser.getContext(), bundle));
}
}
- browser.onSearchResultLoaded(query, page, pageSize, result, extras);
+ browser.onGetSearchResultDone(query, page, pageSize, result, extras);
}
@Override
- public void onChildrenChanged(String parentId, int childCount, Bundle extras) {
+ public void onChildrenChanged(String parentId, int itemCount, Bundle extras) {
final MediaBrowser2Impl browser;
try {
browser = getBrowser();
@@ -323,6 +323,6 @@
// TODO(jaewan): Revisit here. Could be a bug
return;
}
- browser.onChildrenChanged(parentId, childCount, extras);
+ browser.onChildrenChanged(parentId, itemCount, extras);
}
}
diff --git a/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java b/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
index a32ea0a..ec4ce8d 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
@@ -37,8 +37,8 @@
import android.media.MediaItem2;
import android.media.MediaLibraryService2;
import android.media.MediaMetadata2;
-import android.media.MediaPlayerInterface;
-import android.media.MediaPlayerInterface.EventCallback;
+import android.media.MediaPlayerBase;
+import android.media.MediaPlayerBase.EventCallback;
import android.media.MediaSession2;
import android.media.MediaSession2.Builder;
import android.media.MediaSession2.Command;
@@ -105,7 +105,7 @@
//
// TODO(jaewan): Should we put volatile here?
@GuardedBy("mLock")
- private MediaPlayerInterface mPlayer;
+ private MediaPlayerBase mPlayer;
@GuardedBy("mLock")
private VolumeProvider2 mVolumeProvider;
@GuardedBy("mLock")
@@ -124,7 +124,7 @@
* @param callbackExecutor
* @param callback
*/
- public MediaSession2Impl(Context context, MediaPlayerInterface player, String id,
+ public MediaSession2Impl(Context context, MediaPlayerBase player, String id,
VolumeProvider2 volumeProvider, PendingIntent sessionActivity,
Executor callbackExecutor, SessionCallback callback) {
// TODO(jaewan): Keep other params.
@@ -148,10 +148,10 @@
+ " session services define the same id=" + id);
} else if (libraryService != null) {
mSessionToken = new SessionToken2Impl(context, Process.myUid(), TYPE_LIBRARY_SERVICE,
- mContext.getPackageName(), libraryService, id, mSessionStub).getInstance();
+ mContext.getPackageName(), libraryService, id, null).getInstance();
} else if (sessionService != null) {
mSessionToken = new SessionToken2Impl(context, Process.myUid(), TYPE_SESSION_SERVICE,
- mContext.getPackageName(), sessionService, id, mSessionStub).getInstance();
+ mContext.getPackageName(), sessionService, id, null).getInstance();
} else {
mSessionToken = new SessionToken2Impl(context, Process.myUid(), TYPE_SESSION,
mContext.getPackageName(), null, id, mSessionStub).getInstance();
@@ -166,7 +166,7 @@
// a session in another package.
MediaSessionManager manager =
(MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
- if (!manager.onSessionCreated(mSessionToken)) {
+ if (!manager.createSession2(mSessionToken)) {
throw new IllegalStateException("Session with the same id is already used by"
+ " another process. Use MediaController2 instead.");
}
@@ -202,7 +202,7 @@
}
@Override
- public void setPlayer_impl(MediaPlayerInterface player) {
+ public void setPlayer_impl(MediaPlayerBase player) {
ensureCallingThread();
if (player == null) {
throw new IllegalArgumentException("player shouldn't be null");
@@ -211,7 +211,7 @@
}
@Override
- public void setPlayer_impl(MediaPlayerInterface player, VolumeProvider2 volumeProvider)
+ public void setPlayer_impl(MediaPlayerBase player, VolumeProvider2 volumeProvider)
throws IllegalArgumentException {
ensureCallingThread();
if (player == null) {
@@ -223,7 +223,7 @@
setPlayer(player, volumeProvider);
}
- private void setPlayer(MediaPlayerInterface player, VolumeProvider2 volumeProvider) {
+ private void setPlayer(MediaPlayerBase player, VolumeProvider2 volumeProvider) {
final PlaybackInfo info = createPlaybackInfo(volumeProvider, player.getAudioAttributes());
synchronized (mLock) {
if (mPlayer != null && mEventCallback != null) {
@@ -281,7 +281,7 @@
// Stop system service from listening this session first.
MediaSessionManager manager =
(MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
- manager.onSessionDestroyed(mSessionToken);
+ manager.destroySession2(mSessionToken);
if (mSessionStub != null) {
if (DEBUG) {
@@ -300,7 +300,7 @@
}
@Override
- public MediaPlayerInterface getPlayer_impl() {
+ public MediaPlayerBase getPlayer_impl() {
return getPlayer();
}
@@ -323,7 +323,7 @@
@Override
public void play_impl() {
ensureCallingThread();
- final MediaPlayerInterface player = mPlayer;
+ final MediaPlayerBase player = mPlayer;
if (player != null) {
player.play();
} else if (DEBUG) {
@@ -334,7 +334,7 @@
@Override
public void pause_impl() {
ensureCallingThread();
- final MediaPlayerInterface player = mPlayer;
+ final MediaPlayerBase player = mPlayer;
if (player != null) {
player.pause();
} else if (DEBUG) {
@@ -345,7 +345,7 @@
@Override
public void stop_impl() {
ensureCallingThread();
- final MediaPlayerInterface player = mPlayer;
+ final MediaPlayerBase player = mPlayer;
if (player != null) {
player.stop();
} else if (DEBUG) {
@@ -356,7 +356,7 @@
@Override
public void skipToPrevious_impl() {
ensureCallingThread();
- final MediaPlayerInterface player = mPlayer;
+ final MediaPlayerBase player = mPlayer;
if (player != null) {
player.skipToPrevious();
} else if (DEBUG) {
@@ -367,7 +367,7 @@
@Override
public void skipToNext_impl() {
ensureCallingThread();
- final MediaPlayerInterface player = mPlayer;
+ final MediaPlayerBase player = mPlayer;
if (player != null) {
player.skipToNext();
} else if (DEBUG) {
@@ -393,7 +393,7 @@
throw new IllegalArgumentException("params shouldn't be null");
}
ensureCallingThread();
- final MediaPlayerInterface player = mPlayer;
+ final MediaPlayerBase player = mPlayer;
if (player != null) {
player.setPlaylistParams(params);
mSessionStub.notifyPlaylistParamsChanged(params);
@@ -402,7 +402,7 @@
@Override
public PlaylistParams getPlaylistParams_impl() {
- final MediaPlayerInterface player = mPlayer;
+ final MediaPlayerBase player = mPlayer;
if (player != null) {
// TODO(jaewan): Is it safe to be called on any thread?
// Otherwise MediaSession2 should cache parameter of setPlaylistParams.
@@ -423,11 +423,6 @@
}
@Override
- public void notifyMetadataChanged_impl() {
- // TODO(jaewan): Implement
- }
-
- @Override
public void sendCustomCommand_impl(ControllerInfo controller, Command command, Bundle args,
ResultReceiver receiver) {
mSessionStub.sendCustomCommand(controller, command, args, receiver);
@@ -444,7 +439,7 @@
throw new IllegalArgumentException("playlist shouldn't be null");
}
ensureCallingThread();
- final MediaPlayerInterface player = mPlayer;
+ final MediaPlayerBase player = mPlayer;
if (player != null) {
player.setPlaylist(playlist);
mSessionStub.notifyPlaylistChanged(playlist);
@@ -454,8 +449,23 @@
}
@Override
+ public void addPlaylistItem_impl(int index, MediaItem2 item) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void removePlaylistItem_impl(MediaItem2 item) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void editPlaylistItem_impl(MediaItem2 item) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
public List<MediaItem2> getPlaylist_impl() {
- final MediaPlayerInterface player = mPlayer;
+ final MediaPlayerBase player = mPlayer;
if (player != null) {
// TODO(jaewan): Is it safe to be called on any thread?
// Otherwise MediaSession2 should cache parameter of setPlaylist.
@@ -467,9 +477,15 @@
}
@Override
+ public MediaItem2 getCurrentPlaylistItem_impl() {
+ // TODO(jaewan): Implement
+ return null;
+ }
+
+ @Override
public void prepare_impl() {
ensureCallingThread();
- final MediaPlayerInterface player = mPlayer;
+ final MediaPlayerBase player = mPlayer;
if (player != null) {
player.prepare();
} else if (DEBUG) {
@@ -480,7 +496,7 @@
@Override
public void fastForward_impl() {
ensureCallingThread();
- final MediaPlayerInterface player = mPlayer;
+ final MediaPlayerBase player = mPlayer;
if (player != null) {
player.fastForward();
} else if (DEBUG) {
@@ -491,7 +507,7 @@
@Override
public void rewind_impl() {
ensureCallingThread();
- final MediaPlayerInterface player = mPlayer;
+ final MediaPlayerBase player = mPlayer;
if (player != null) {
player.rewind();
} else if (DEBUG) {
@@ -502,7 +518,7 @@
@Override
public void seekTo_impl(long pos) {
ensureCallingThread();
- final MediaPlayerInterface player = mPlayer;
+ final MediaPlayerBase player = mPlayer;
if (player != null) {
player.seekTo(pos);
} else if (DEBUG) {
@@ -511,11 +527,11 @@
}
@Override
- public void setCurrentPlaylistItem_impl(int index) {
+ public void skipToPlaylistItem_impl(MediaItem2 item) {
ensureCallingThread();
- final MediaPlayerInterface player = mPlayer;
+ final MediaPlayerBase player = mPlayer;
if (player != null) {
- player.setCurrentPlaylistItem(index);
+ player.setCurrentPlaylistItem(item);
} else if (DEBUG) {
Log.d(TAG, "API calls after the close()", new IllegalStateException());
}
@@ -552,7 +568,7 @@
@Override
public PlaybackState2 getPlaybackState_impl() {
ensureCallingThread();
- final MediaPlayerInterface player = mPlayer;
+ final MediaPlayerBase player = mPlayer;
if (player != null) {
// TODO(jaewan): Is it safe to be called on any thread?
// Otherwise MediaSession2 should cache the result from listener.
@@ -563,6 +579,11 @@
return null;
}
+ @Override
+ public void notifyError_impl(int errorCode, int extra) {
+ // TODO(jaewan): Implement
+ }
+
///////////////////////////////////////////////////
// Protected or private methods
///////////////////////////////////////////////////
@@ -624,7 +645,7 @@
return mInstance;
}
- MediaPlayerInterface getPlayer() {
+ MediaPlayerBase getPlayer() {
return mPlayer;
}
@@ -654,11 +675,11 @@
return mSessionActivity;
}
- private static class MyEventCallback implements EventCallback {
+ private static class MyEventCallback extends EventCallback {
private final WeakReference<MediaSession2Impl> mSession;
- private final MediaPlayerInterface mPlayer;
+ private final MediaPlayerBase mPlayer;
- private MyEventCallback(MediaSession2Impl session, MediaPlayerInterface player) {
+ private MyEventCallback(MediaSession2Impl session, MediaPlayerBase player) {
mSession = new WeakReference<>(session);
mPlayer = player;
}
@@ -1195,7 +1216,7 @@
public static abstract class BuilderBaseImpl<T extends MediaSession2, C extends SessionCallback>
implements BuilderBaseProvider<T, C> {
final Context mContext;
- final MediaPlayerInterface mPlayer;
+ final MediaPlayerBase mPlayer;
String mId;
Executor mCallbackExecutor;
C mCallback;
@@ -1211,7 +1232,7 @@
* {@link MediaSession2} or {@link MediaController2}.
*/
// TODO(jaewan): Also need executor
- public BuilderBaseImpl(Context context, MediaPlayerInterface player) {
+ public BuilderBaseImpl(Context context, MediaPlayerBase player) {
if (context == null) {
throw new IllegalArgumentException("context shouldn't be null");
}
@@ -1254,7 +1275,7 @@
}
public static class BuilderImpl extends BuilderBaseImpl<MediaSession2, SessionCallback> {
- public BuilderImpl(Context context, Builder instance, MediaPlayerInterface player) {
+ public BuilderImpl(Context context, Builder instance, MediaPlayerBase player) {
super(context, player);
}
@@ -1264,7 +1285,7 @@
mCallbackExecutor = mContext.getMainExecutor();
}
if (mCallback == null) {
- mCallback = new SessionCallback(mContext);
+ mCallback = new SessionCallback(mContext) {};
}
return new MediaSession2Impl(mContext, mPlayer, mId, mVolumeProvider,
diff --git a/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java b/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
index 914f85e..7fb6f0f 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
@@ -126,26 +126,26 @@
throws RuntimeException {
final MediaSession2Impl sessionImpl = getSession();
final Context context = sessionImpl.getContext();
- final ControllerInfo request = new ControllerInfo(context,
+ final ControllerInfo controllerInfo = new ControllerInfo(context,
Binder.getCallingUid(), Binder.getCallingPid(), callingPackage, caller);
sessionImpl.getCallbackExecutor().execute(() -> {
final MediaSession2Impl session = mSession.get();
if (session == null) {
return;
}
- CommandGroup allowedCommands = session.getCallback().onConnect(request);
- // Don't reject connection for the request from trusted app.
+ CommandGroup allowedCommands = session.getCallback().onConnect(controllerInfo);
+ // Don't reject connection for the controllerInfo from trusted app.
// Otherwise server will fail to retrieve session's information to dispatch
// media keys to.
- boolean accept = allowedCommands != null || request.isTrusted();
- ControllerInfoImpl impl = ControllerInfoImpl.from(request);
+ boolean accept = allowedCommands != null || controllerInfo.isTrusted();
+ ControllerInfoImpl impl = ControllerInfoImpl.from(controllerInfo);
if (accept) {
if (DEBUG) {
- Log.d(TAG, "Accepting connection, request=" + request
+ Log.d(TAG, "Accepting connection, controllerInfo=" + controllerInfo
+ " allowedCommands=" + allowedCommands);
}
synchronized (mLock) {
- mControllers.put(impl.getId(), request);
+ mControllers.put(impl.getId(), controllerInfo);
}
if (allowedCommands == null) {
// For trusted apps, send non-null allowed commands to keep connection.
@@ -195,7 +195,7 @@
}
} else {
if (DEBUG) {
- Log.d(TAG, "Rejecting connection, request=" + request);
+ Log.d(TAG, "Rejecting connection, controllerInfo=" + controllerInfo);
}
try {
caller.onDisconnected();
@@ -357,8 +357,11 @@
session.getInstance().seekTo(args.getLong(ARGUMENT_KEY_POSITION));
break;
case MediaSession2.COMMAND_CODE_PLAYBACK_SET_CURRENT_PLAYLIST_ITEM:
- session.getInstance().setCurrentPlaylistItem(
+ // TODO(jaewan): Implement
+ /*
+ session.getInstance().skipToPlaylistItem(
args.getInt(ARGUMENT_KEY_ITEM_INDEX));
+ */
break;
case MediaSession2.COMMAND_CODE_PLAYBACK_SET_PLAYLIST_PARAMS:
session.getInstance().setPlaylistParams(
@@ -554,9 +557,9 @@
return;
}
final ControllerInfoImpl controllerImpl = ControllerInfoImpl.from(controller);
- LibraryRoot root = session.getCallback().onGetRoot(controller, rootHints);
+ LibraryRoot root = session.getCallback().onGetLibraryRoot(controller, rootHints);
try {
- controllerImpl.getControllerBinder().onGetRootResult(rootHints,
+ controllerImpl.getControllerBinder().onGetLibraryRootDone(rootHints,
root == null ? null : root.getRootId(),
root == null ? null : root.getExtras());
} catch (RemoteException e) {
@@ -588,9 +591,9 @@
return;
}
final ControllerInfoImpl controllerImpl = ControllerInfoImpl.from(controller);
- MediaItem2 result = session.getCallback().onLoadItem(controller, mediaId);
+ MediaItem2 result = session.getCallback().onGetItem(controller, mediaId);
try {
- controllerImpl.getControllerBinder().onItemLoaded(
+ controllerImpl.getControllerBinder().onGetItemDone(
mediaId, result == null ? null : result.toBundle());
} catch (RemoteException e) {
// Controller may be died prematurely.
@@ -629,10 +632,10 @@
return;
}
final ControllerInfoImpl controllerImpl = ControllerInfoImpl.from(controller);
- List<MediaItem2> result = session.getCallback().onLoadChildren(
+ List<MediaItem2> result = session.getCallback().onGetChildren(
controller, parentId, page, pageSize, extras);
if (result != null && result.size() > pageSize) {
- throw new IllegalArgumentException("onLoadChildren() shouldn't return media items "
+ throw new IllegalArgumentException("onGetChildren() shouldn't return media items "
+ "more than pageSize. result.size()=" + result.size() + " pageSize="
+ pageSize);
}
@@ -646,7 +649,7 @@
}
try {
- controllerImpl.getControllerBinder().onChildrenLoaded(
+ controllerImpl.getControllerBinder().onGetChildrenDone(
parentId, page, pageSize, bundleList, extras);
} catch (RemoteException e) {
// Controller may be died prematurely.
@@ -712,10 +715,10 @@
return;
}
final ControllerInfoImpl controllerImpl = ControllerInfoImpl.from(controller);
- List<MediaItem2> result = session.getCallback().onLoadSearchResult(
+ List<MediaItem2> result = session.getCallback().onGetSearchResult(
controller, query, page, pageSize, extras);
if (result != null && result.size() > pageSize) {
- throw new IllegalArgumentException("onLoadSearchResult() shouldn't return media "
+ throw new IllegalArgumentException("onGetSearchResult() shouldn't return media "
+ "items more than pageSize. result.size()=" + result.size() + " pageSize="
+ pageSize);
}
@@ -729,7 +732,7 @@
}
try {
- controllerImpl.getControllerBinder().onSearchResultLoaded(
+ controllerImpl.getControllerBinder().onGetSearchResultDone(
query, page, pageSize, bundleList, extras);
} catch (RemoteException e) {
// Controller may be died prematurely.
@@ -754,7 +757,7 @@
if (session == null) {
return;
}
- session.getCallback().onSubscribed(controller, parentId, option);
+ session.getCallback().onSubscribe(controller, parentId, option);
synchronized (mLock) {
Set<String> subscription = mSubscriptions.get(controller);
if (subscription == null) {
@@ -781,7 +784,7 @@
if (session == null) {
return;
}
- session.getCallback().onUnsubscribed(controller, parentId);
+ session.getCallback().onUnsubscribe(controller, parentId);
synchronized (mLock) {
mSubscriptions.remove(controller);
}
@@ -951,23 +954,23 @@
}
public void notifyChildrenChangedNotLocked(ControllerInfo controller, String parentId,
- int childCount, Bundle extras) {
+ int itemCount, Bundle extras) {
// TODO(jaewan): Handle when controller is disconnected and no longer valid.
// Note: Commands may be sent while onConnected() is running. Should we also
// consider it as error?
- notifyChildrenChangedInternalNotLocked(controller, parentId, childCount, extras);
+ notifyChildrenChangedInternalNotLocked(controller, parentId, itemCount, extras);
}
- public void notifyChildrenChangedNotLocked(String parentId, int childCount, Bundle extras) {
+ public void notifyChildrenChangedNotLocked(String parentId, int itemCount, Bundle extras) {
final List<ControllerInfo> controllers = getControllers();
for (int i = 0; i < controllers.size(); i++) {
- notifyChildrenChangedInternalNotLocked(controllers.get(i), parentId, childCount,
+ notifyChildrenChangedInternalNotLocked(controllers.get(i), parentId, itemCount,
extras);
}
}
public void notifyChildrenChangedInternalNotLocked(final ControllerInfo controller,
- String parentId, int childCount, Bundle extras) {
+ String parentId, int itemCount, Bundle extras) {
// Ensure subscription
synchronized (mLock) {
Set<String> subscriptions = mSubscriptions.get(controller);
@@ -978,7 +981,7 @@
final IMediaSession2Callback callbackBinder =
ControllerInfoImpl.from(controller).getControllerBinder();
try {
- callbackBinder.onChildrenChanged(parentId, childCount, extras);
+ callbackBinder.onChildrenChanged(parentId, itemCount, extras);
} catch (RemoteException e) {
// TODO(jaewan): Handle controller removed?
}
diff --git a/packages/MediaComponents/src/com/android/media/MediaSessionService2Impl.java b/packages/MediaComponents/src/com/android/media/MediaSessionService2Impl.java
index aa5ac84..e640f4c 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSessionService2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSessionService2Impl.java
@@ -22,7 +22,7 @@
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
-import android.media.MediaPlayerInterface.EventCallback;
+import android.media.MediaPlayerBase.EventCallback;
import android.media.MediaSession2;
import android.media.MediaSessionService2;
import android.media.MediaSessionService2.MediaNotification;
@@ -72,7 +72,7 @@
}
@Override
- public MediaNotification onUpdateNotification_impl(PlaybackState2 state) {
+ public MediaNotification onUpdateNotification_impl() {
// Provide default notification UI later.
return null;
}
@@ -103,13 +103,13 @@
public IBinder onBind_impl(Intent intent) {
if (MediaSessionService2.SERVICE_INTERFACE.equals(intent.getAction())) {
- return SessionToken2Impl.from(mSession.getToken()).getSessionBinder().asBinder();
+ return ((MediaSession2Impl) mSession.getProvider()).getSessionStub().asBinder();
}
return null;
}
private void updateNotification(PlaybackState2 state) {
- MediaNotification mediaNotification = mInstance.onUpdateNotification(state);
+ MediaNotification mediaNotification = mInstance.onUpdateNotification();
if (mediaNotification == null) {
return;
}
@@ -135,7 +135,7 @@
mediaNotification.getNotification());
}
- private class SessionServiceEventCallback implements EventCallback {
+ private class SessionServiceEventCallback extends EventCallback {
@Override
public void onPlaybackStateChanged(PlaybackState2 state) {
if (state == null) {
@@ -143,7 +143,7 @@
return;
}
MediaSession2Impl impl = (MediaSession2Impl) mSession.getProvider();
- updateNotification(state);
+ updateNotification(impl.getInstance().getPlaybackState());
}
}
diff --git a/packages/MediaComponents/src/com/android/media/SessionToken2Impl.java b/packages/MediaComponents/src/com/android/media/SessionToken2Impl.java
index f36aa43..b1ba8aa 100644
--- a/packages/MediaComponents/src/com/android/media/SessionToken2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/SessionToken2Impl.java
@@ -53,8 +53,8 @@
private final IMediaSession2 mSessionBinder;
/**
- * Public constructor for the legacy support (i.e. browser can try connecting to any browser service
- * if it knows the service name)
+ * Public constructor for the legacy support (i.e. browser can try connecting to any browser
+ * service if it knows the service name)
*/
public SessionToken2Impl(Context context, SessionToken2 instance,
String packageName, String serviceName, int uid) {
@@ -235,8 +235,7 @@
+ prime * (mUid
+ prime * (mPackageName.hashCode()
+ prime * (mId.hashCode()
- + prime * ((mServiceName != null ? mServiceName.hashCode() : 0)
- + prime * (mSessionBinder != null ? mSessionBinder.asBinder().hashCode() : 0)))));
+ + prime * (mServiceName != null ? mServiceName.hashCode() : 0))));
}
@Override
@@ -245,19 +244,11 @@
return false;
}
SessionToken2Impl other = from((SessionToken2) obj);
- if (mUid != other.mUid
- || !TextUtils.equals(mPackageName, other.mPackageName)
- || !TextUtils.equals(mServiceName, other.mServiceName)
- || !TextUtils.equals(mId, other.mId)
- || mType != other.mType) {
- return false;
- }
- if (mSessionBinder == other.mSessionBinder) {
- return true;
- } else if (mSessionBinder == null || other.mSessionBinder == null) {
- return false;
- }
- return mSessionBinder.asBinder().equals(other.mSessionBinder.asBinder());
+ return mUid == other.mUid
+ && TextUtils.equals(mPackageName, other.mPackageName)
+ && TextUtils.equals(mServiceName, other.mServiceName)
+ && TextUtils.equals(mId, other.mId)
+ && mType == other.mType;
}
@Override
diff --git a/packages/MediaComponents/src/com/android/media/update/ApiFactory.java b/packages/MediaComponents/src/com/android/media/update/ApiFactory.java
index 994824d..577173d 100644
--- a/packages/MediaComponents/src/com/android/media/update/ApiFactory.java
+++ b/packages/MediaComponents/src/com/android/media/update/ApiFactory.java
@@ -29,13 +29,11 @@
import android.media.MediaLibraryService2;
import android.media.MediaLibraryService2.LibraryRoot;
import android.media.MediaLibraryService2.MediaLibrarySession;
-import android.media.MediaLibraryService2.MediaLibrarySessionBuilder;
-import android.media.MediaLibraryService2.MediaLibrarySessionCallback;
+import android.media.MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback;
import android.media.MediaMetadata2;
-import android.media.MediaPlayerInterface;
+import android.media.MediaPlayerBase;
import android.media.MediaSession2;
import android.media.MediaSession2.Command;
-import android.media.MediaSession2.CommandButton.Builder;
import android.media.MediaSession2.CommandGroup;
import android.media.MediaSession2.ControllerInfo;
import android.media.MediaSession2.PlaylistParams;
@@ -159,12 +157,12 @@
@Override
public BuilderProvider createMediaSession2CommandButtonBuilder(Context context,
- Builder instance) {
+ MediaSession2.CommandButton.Builder instance) {
return new MediaSession2Impl.CommandButtonImpl.BuilderImpl(context, instance);
}
public BuilderBaseProvider<MediaSession2, SessionCallback> createMediaSession2Builder(
- Context context, MediaSession2.Builder instance, MediaPlayerInterface player) {
+ Context context, MediaSession2.Builder instance, MediaPlayerBase player) {
return new MediaSession2Impl.BuilderImpl(context, instance, player);
}
@@ -189,10 +187,10 @@
@Override
public BuilderBaseProvider<MediaLibrarySession, MediaLibrarySessionCallback>
- createMediaLibraryService2Builder(
- Context context, MediaLibrarySessionBuilder instance, MediaPlayerInterface player,
+ createMediaLibraryService2Builder(MediaLibraryService2 service,
+ MediaLibrarySession.Builder instance, MediaPlayerBase player,
Executor callbackExecutor, MediaLibrarySessionCallback callback) {
- return new MediaLibraryService2Impl.BuilderImpl(context, instance, player, callbackExecutor,
+ return new MediaLibraryService2Impl.BuilderImpl(service, instance, player, callbackExecutor,
callback);
}
@@ -223,7 +221,7 @@
}
@Override
- public SessionToken2 SessionToken2_fromBundle(Context context, Bundle bundle) {
+ public SessionToken2 fromBundle_SessionToken2(Context context, Bundle bundle) {
return SessionToken2Impl.fromBundle_impl(context, bundle);
}
diff --git a/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java b/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
index e937659..f440ad6 100644
--- a/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
+++ b/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
@@ -26,13 +26,19 @@
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ListView;
import android.widget.MediaControlView2;
import android.widget.ProgressBar;
+import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
@@ -44,6 +50,7 @@
import com.android.support.mediarouter.media.MediaRouter;
import com.android.support.mediarouter.media.MediaRouteSelector;
+import java.util.ArrayList;
import java.util.Formatter;
import java.util.List;
import java.util.Locale;
@@ -68,7 +75,9 @@
private static final int REWIND_TIME_MS = 10000;
private static final int FORWARD_TIME_MS = 30000;
private static final int AD_SKIP_WAIT_TIME_MS = 5000;
+ private static final int RESOURCE_NON_EXISTENT = -1;
+ private Resources mResources;
private MediaController mController;
private MediaController.TransportControls mControls;
private PlaybackState mPlaybackState;
@@ -109,6 +118,12 @@
private ImageButton mAspectRationButton;
private ImageButton mSettingsButton;
+ private PopupWindow mSettingsWindow;
+ private SettingsAdapter mSettingsAdapter;
+ private List<Integer> mSettingsMainTextIdsList;
+ private List<Integer> mSettingsSubTextIdsList;
+ private List<Integer> mSettingsIconIdsList;
+
private CharSequence mPlayDescription;
private CharSequence mPauseDescription;
private CharSequence mReplayDescription;
@@ -127,6 +142,7 @@
@Override
public void initialize(@Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ mResources = ApiHelper.getLibResources();
// Inflate MediaControlView2 from XML
mRoot = makeControllerView();
mRoot.addOnLayoutChangeListener(mTitleBarLayoutChangeListener);
@@ -356,10 +372,11 @@
}
private void initControllerView(View v) {
- Resources res = ApiHelper.getLibResources();
- mPlayDescription = res.getText(R.string.lockscreen_play_button_content_description);
- mPauseDescription = res.getText(R.string.lockscreen_pause_button_content_description);
- mReplayDescription = res.getText(R.string.lockscreen_replay_button_content_description);
+ mPlayDescription = mResources.getText(R.string.lockscreen_play_button_content_description);
+ mPauseDescription =
+ mResources.getText(R.string.lockscreen_pause_button_content_description);
+ mReplayDescription =
+ mResources.getText(R.string.lockscreen_replay_button_content_description);
mRouteButton = v.findViewById(R.id.cast);
@@ -367,19 +384,19 @@
if (mPlayPauseButton != null) {
mPlayPauseButton.requestFocus();
mPlayPauseButton.setOnClickListener(mPlayPauseListener);
- mPlayPauseButton.setColorFilter(R.integer.gray);
+ mPlayPauseButton.setColorFilter(R.color.gray);
mPlayPauseButton.setEnabled(false);
}
mFfwdButton = v.findViewById(R.id.ffwd);
if (mFfwdButton != null) {
mFfwdButton.setOnClickListener(mFfwdListener);
- mFfwdButton.setColorFilter(R.integer.gray);
+ mFfwdButton.setColorFilter(R.color.gray);
mFfwdButton.setEnabled(false);
}
mRewButton = v.findViewById(R.id.rew);
if (mRewButton != null) {
mRewButton.setOnClickListener(mRewListener);
- mRewButton.setColorFilter(R.integer.gray);
+ mRewButton.setColorFilter(R.color.gray);
mRewButton.setEnabled(false);
}
mNextButton = v.findViewById(R.id.next);
@@ -395,7 +412,7 @@
mSubtitleButton = v.findViewById(R.id.subtitle);
if (mSubtitleButton != null) {
mSubtitleButton.setOnClickListener(mSubtitleListener);
- mSubtitleButton.setColorFilter(R.integer.gray);
+ mSubtitleButton.setColorFilter(R.color.gray);
mSubtitleButton.setEnabled(false);
}
mFullScreenButton = v.findViewById(R.id.fullscreen);
@@ -418,6 +435,9 @@
mMuteButton = v.findViewById(R.id.mute);
mAspectRationButton = v.findViewById(R.id.aspect_ratio);
mSettingsButton = v.findViewById(R.id.settings);
+ if (mSettingsButton != null) {
+ mSettingsButton.setOnClickListener(mSettingsButtonListener);
+ }
mProgress = v.findViewById(R.id.mediacontroller_progress);
if (mProgress != null) {
@@ -438,6 +458,18 @@
mAdSkipView = v.findViewById(R.id.ad_skip_time);
mAdRemainingView = v.findViewById(R.id.ad_remaining);
mAdExternalLink = v.findViewById(R.id.ad_external_link);
+
+ populateResourceIds();
+ ListView settingsListView = (ListView) ApiHelper.inflateLibLayout(mInstance.getContext(),
+ R.layout.settings_list);
+ mSettingsAdapter = new SettingsAdapter(mSettingsMainTextIdsList, mSettingsSubTextIdsList,
+ mSettingsIconIdsList, true);
+ settingsListView.setAdapter(mSettingsAdapter);
+
+ int width = mResources.getDimensionPixelSize(R.dimen.MediaControlView2_settings_width);
+ mSettingsWindow = new PopupWindow(settingsListView, width,
+ ViewGroup.LayoutParams.WRAP_CONTENT, true);
+ // TODO: add listener to list view to allow each item to be selected.
}
/**
@@ -530,7 +562,7 @@
if (mAdSkipView.getVisibility() == View.GONE) {
mAdSkipView.setVisibility(View.VISIBLE);
}
- String skipTimeText = ApiHelper.getLibResources().getString(
+ String skipTimeText = mResources.getString(
R.string.MediaControlView2_ad_skip_wait_time,
((AD_SKIP_WAIT_TIME_MS - currentPosition) / 1000 + 1));
mAdSkipView.setText(skipTimeText);
@@ -546,7 +578,7 @@
if (mAdRemainingView != null) {
int remainingTime =
(mDuration - currentPosition < 0) ? 0 : (mDuration - currentPosition);
- String remainingTimeText = ApiHelper.getLibResources().getString(
+ String remainingTimeText = mResources.getString(
R.string.MediaControlView2_ad_remaining_time,
stringForTime(remainingTime));
mAdRemainingView.setText(remainingTimeText);
@@ -559,14 +591,12 @@
if (isPlaying()) {
mControls.pause();
mPlayPauseButton.setImageDrawable(
- ApiHelper.getLibResources().getDrawable(
- R.drawable.ic_play_circle_filled, null));
+ mResources.getDrawable(R.drawable.ic_play_circle_filled, null));
mPlayPauseButton.setContentDescription(mPlayDescription);
} else {
mControls.play();
mPlayPauseButton.setImageDrawable(
- ApiHelper.getLibResources().getDrawable(
- R.drawable.ic_pause_circle_filled, null));
+ mResources.getDrawable(R.drawable.ic_pause_circle_filled, null));
mPlayPauseButton.setContentDescription(mPauseDescription);
}
}
@@ -602,8 +632,7 @@
// show the play image instead of the replay image.
if (mIsStopped) {
mPlayPauseButton.setImageDrawable(
- ApiHelper.getLibResources().getDrawable(
- R.drawable.ic_play_circle_filled, null));
+ mResources.getDrawable(R.drawable.ic_play_circle_filled, null));
mPlayPauseButton.setContentDescription(mPlayDescription);
mIsStopped = false;
}
@@ -689,14 +718,12 @@
public void onClick(View v) {
if (!mSubtitleIsEnabled) {
mSubtitleButton.setImageDrawable(
- ApiHelper.getLibResources().getDrawable(
- R.drawable.ic_media_subtitle_enabled, null));
+ mResources.getDrawable(R.drawable.ic_media_subtitle_enabled, null));
mController.sendCommand(MediaControlView2.COMMAND_SHOW_SUBTITLE, null, null);
mSubtitleIsEnabled = true;
} else {
mSubtitleButton.setImageDrawable(
- ApiHelper.getLibResources().getDrawable(
- R.drawable.ic_media_subtitle_disabled, null));
+ mResources.getDrawable(R.drawable.ic_media_subtitle_disabled, null));
mController.sendCommand(MediaControlView2.COMMAND_HIDE_SUBTITLE, null, null);
mSubtitleIsEnabled = false;
}
@@ -710,11 +737,10 @@
// TODO: Re-arrange the button layouts according to the UX.
if (isEnteringFullScreen) {
mFullScreenButton.setImageDrawable(
- ApiHelper.getLibResources().getDrawable(
- R.drawable.ic_fullscreen_exit, null));
+ mResources.getDrawable(R.drawable.ic_fullscreen_exit, null));
} else {
mFullScreenButton.setImageDrawable(
- ApiHelper.getLibResources().getDrawable(R.drawable.ic_fullscreen, null));
+ mResources.getDrawable(R.drawable.ic_fullscreen, null));
}
Bundle args = new Bundle();
args.putBoolean(ARGUMENT_KEY_FULLSCREEN, isEnteringFullScreen);
@@ -740,6 +766,19 @@
}
};
+ private final View.OnClickListener mSettingsButtonListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ int itemHeight = mResources.getDimensionPixelSize(
+ R.dimen.MediaControlView2_settings_height);
+ int totalHeight = mSettingsAdapter.getCount() * itemHeight;
+ int margin = (-1) * mResources.getDimensionPixelSize(
+ R.dimen.MediaControlView2_settings_offset);
+ mSettingsWindow.showAsDropDown(mInstance, margin, margin - totalHeight,
+ Gravity.BOTTOM | Gravity.RIGHT);
+ }
+ };
+
// The title bar is made up of two separate LinearLayouts. If the sum of the two bars are
// greater than the length of the title bar, reduce the size of the left bar (which makes the
// TextView that contains the title of the media file shrink).
@@ -802,7 +841,7 @@
mProgress.setEnabled(false);
mNextButton.setEnabled(false);
- mNextButton.setColorFilter(R.integer.gray);
+ mNextButton.setColorFilter(R.color.gray);
} else {
mRewButton.setVisibility(View.VISIBLE);
mFfwdButton.setVisibility(View.VISIBLE);
@@ -821,6 +860,31 @@
}
}
+ private void populateResourceIds() {
+ // TODO: create record class for storing this info
+ mSettingsMainTextIdsList = new ArrayList<Integer>();
+ mSettingsMainTextIdsList.add(R.string.MediaControlView2_cc_text);
+ mSettingsMainTextIdsList.add(R.string.MediaControlView2_audio_track_text);
+ mSettingsMainTextIdsList.add(R.string.MediaControlView2_video_quality_text);
+ mSettingsMainTextIdsList.add(R.string.MediaControlView2_playback_speed_text);
+ mSettingsMainTextIdsList.add(R.string.MediaControlView2_help_text);
+
+ // TODO: Update the following code to be dynamic.
+ mSettingsSubTextIdsList = new ArrayList<Integer>();
+ mSettingsSubTextIdsList.add(R.string.MediaControlView2_cc_text);
+ mSettingsSubTextIdsList.add(R.string.MediaControlView2_audio_track_text);
+ mSettingsSubTextIdsList.add(R.string.MediaControlView2_video_quality_text);
+ mSettingsSubTextIdsList.add(R.string.MediaControlView2_playback_speed_text);
+ mSettingsSubTextIdsList.add(RESOURCE_NON_EXISTENT);
+
+ mSettingsIconIdsList = new ArrayList<Integer>();
+ mSettingsIconIdsList.add(R.drawable.ic_closed_caption_off);
+ mSettingsIconIdsList.add(R.drawable.ic_audiotrack);
+ mSettingsIconIdsList.add(R.drawable.ic_high_quality);
+ mSettingsIconIdsList.add(R.drawable.ic_play_circle_filled);
+ mSettingsIconIdsList.add(R.drawable.ic_help);
+ }
+
private class MediaControllerCallback extends MediaController.Callback {
@Override
public void onPlaybackStateChanged(PlaybackState state) {
@@ -834,22 +898,19 @@
switch (mPlaybackState.getState()) {
case PlaybackState.STATE_PLAYING:
mPlayPauseButton.setImageDrawable(
- ApiHelper.getLibResources().getDrawable(
- R.drawable.ic_pause_circle_filled, null));
+ mResources.getDrawable(R.drawable.ic_pause_circle_filled, null));
mPlayPauseButton.setContentDescription(mPauseDescription);
mInstance.removeCallbacks(mUpdateProgress);
mInstance.post(mUpdateProgress);
break;
case PlaybackState.STATE_PAUSED:
mPlayPauseButton.setImageDrawable(
- ApiHelper.getLibResources().getDrawable(
- R.drawable.ic_play_circle_filled, null));
+ mResources.getDrawable(R.drawable.ic_play_circle_filled, null));
mPlayPauseButton.setContentDescription(mPlayDescription);
break;
case PlaybackState.STATE_STOPPED:
mPlayPauseButton.setImageDrawable(
- ApiHelper.getLibResources().getDrawable(
- R.drawable.ic_replay, null));
+ mResources.getDrawable(R.drawable.ic_replay_circle_filled, null));
mPlayPauseButton.setContentDescription(mReplayDescription);
mIsStopped = true;
break;
@@ -923,7 +984,7 @@
mSubtitleButton.clearColorFilter();
mSubtitleButton.setEnabled(true);
} else {
- mSubtitleButton.setColorFilter(R.integer.gray);
+ mSubtitleButton.setColorFilter(R.color.gray);
mSubtitleButton.setEnabled(false);
}
mContainsSubtitle = newSubtitleStatus;
@@ -937,4 +998,76 @@
}
}
}
+
+ private class SettingsAdapter extends BaseAdapter {
+ List<Integer> mMainTextIds;
+ List<Integer> mSubTextIds;
+ List<Integer> mIconIds;
+ boolean mIsCheckable;
+
+ public SettingsAdapter(List<Integer> mainTextIds, @Nullable List<Integer> subTextIds,
+ @Nullable List<Integer> iconIds, boolean isCheckable) {
+ mMainTextIds = mainTextIds;
+ mSubTextIds = subTextIds;
+ mIconIds = iconIds;
+ mIsCheckable = isCheckable;
+ }
+
+ @Override
+ public int getCount() {
+ return (mMainTextIds == null) ? 0 : mMainTextIds.size();
+ }
+
+ @Override
+ public long getItemId(int position) {
+ // Auto-generated method stub--does not have any purpose here
+ // TODO: implement this.
+ return 0;
+ }
+
+ @Override
+ public Object getItem(int position) {
+ // Auto-generated method stub--does not have any purpose here
+ // TODO: implement this.
+ return null;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup container) {
+ View row = ApiHelper.inflateLibLayout(mInstance.getContext(),
+ R.layout.settings_list_item);
+ TextView mainTextView = (TextView) row.findViewById(R.id.main_text);
+ TextView subTextView = (TextView) row.findViewById(R.id.sub_text);
+ ImageView iconView = (ImageView) row.findViewById(R.id.icon);
+ ImageView checkView = (ImageView) row.findViewById(R.id.check);
+
+ // Set main text
+ mainTextView.setText(mResources.getString(mMainTextIds.get(position)));
+
+ // Remove sub text and center the main text if sub texts do not exist at all or the sub
+ // text at this particular position is set to RESOURCE_NON_EXISTENT.
+ if (mSubTextIds == null || mSubTextIds.get(position) == RESOURCE_NON_EXISTENT) {
+ subTextView.setVisibility(View.GONE);
+ } else {
+ // Otherwise, set sub text.
+ subTextView.setText(mResources.getString(mSubTextIds.get(position)));
+ }
+
+ // Remove main icon and set visibility to gone if icons are set to null or the icon at
+ // this particular position is set to RESOURCE_NON_EXISTENT.
+ if (mIconIds == null || mIconIds.get(position) == RESOURCE_NON_EXISTENT) {
+ iconView.setVisibility(View.GONE);
+ } else {
+ // Otherwise, set main icon.
+ iconView.setImageDrawable(mResources.getDrawable(mIconIds.get(position), null));
+ }
+
+ // Set check icon
+ // TODO: make the following code dynamic
+ if (!mIsCheckable) {
+ checkView.setVisibility(View.GONE);
+ }
+ return row;
+ }
+ }
}
diff --git a/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java b/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
index 805c262..928b2a5 100644
--- a/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
+++ b/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
@@ -24,7 +24,7 @@
import android.media.AudioManager;
import android.media.MediaMetadata;
import android.media.MediaPlayer;
-import android.media.MediaPlayerInterface;
+import android.media.MediaPlayerBase;
import android.media.Cea708CaptionRenderer;
import android.media.ClosedCaptionRenderer;
import android.media.MediaMetadata2;
@@ -312,7 +312,7 @@
}
@Override
- public void setRouteAttributes_impl(List<String> routeCategories, MediaPlayerInterface player) {
+ public void setRouteAttributes_impl(List<String> routeCategories, MediaPlayerBase player) {
// TODO: implement this.
}
diff --git a/packages/MediaComponents/test/src/android/media/MediaBrowser2Test.java b/packages/MediaComponents/test/src/android/media/MediaBrowser2Test.java
index 7e93232..1abb9b4 100644
--- a/packages/MediaComponents/test/src/android/media/MediaBrowser2Test.java
+++ b/packages/MediaComponents/test/src/android/media/MediaBrowser2Test.java
@@ -71,13 +71,13 @@
interface TestBrowserCallbackInterface extends TestControllerCallbackInterface {
// Browser specific callbacks
- default void onGetRootResult(Bundle rootHints, String rootMediaId, Bundle rootExtra) {}
- default void onItemLoaded(String mediaId, MediaItem2 result) {}
- default void onChildrenChanged(String parentId, int childCount, Bundle extras) {}
- default void onChildrenLoaded(String parentId, int page, int pageSize,
+ default void onGetLibraryRootDone(Bundle rootHints, String rootMediaId, Bundle rootExtra) {}
+ default void onGetItemDone(String mediaId, MediaItem2 result) {}
+ default void onChildrenChanged(String parentId, int itemCount, Bundle extras) {}
+ default void onGetChildrenDone(String parentId, int page, int pageSize,
List<MediaItem2> result, Bundle extras) {}
default void onSearchResultChanged(String query, int itemCount, Bundle extras) {}
- default void onSearchResultLoaded(String query, int page, int pageSize,
+ default void onGetSearchResultDone(String query, int page, int pageSize,
List<MediaItem2> result, Bundle extras) {}
}
@@ -89,7 +89,8 @@
final CountDownLatch latch = new CountDownLatch(1);
final TestControllerCallbackInterface callback = new TestBrowserCallbackInterface() {
@Override
- public void onGetRootResult(Bundle rootHints, String rootMediaId, Bundle rootExtra) {
+ public void onGetLibraryRootDone(Bundle rootHints, String rootMediaId,
+ Bundle rootExtra) {
assertTrue(TestUtils.equals(param, rootHints));
assertEquals(MockMediaLibraryService2.ROOT_ID, rootMediaId);
assertTrue(TestUtils.equals(MockMediaLibraryService2.EXTRAS, rootExtra));
@@ -111,7 +112,7 @@
final CountDownLatch latch = new CountDownLatch(1);
final TestControllerCallbackInterface callback = new TestBrowserCallbackInterface() {
@Override
- public void onItemLoaded(String mediaIdOut, MediaItem2 result) {
+ public void onGetItemDone(String mediaIdOut, MediaItem2 result) {
assertEquals(mediaId, mediaIdOut);
assertNotNull(result);
assertEquals(mediaId, result.getMediaId());
@@ -132,7 +133,7 @@
final CountDownLatch latch = new CountDownLatch(1);
final TestControllerCallbackInterface callback = new TestBrowserCallbackInterface() {
@Override
- public void onItemLoaded(String mediaIdOut, MediaItem2 result) {
+ public void onGetItemDone(String mediaIdOut, MediaItem2 result) {
assertEquals(mediaId, mediaIdOut);
assertNull(result);
latch.countDown();
@@ -156,7 +157,7 @@
final CountDownLatch latch = new CountDownLatch(1);
final TestControllerCallbackInterface callback = new TestBrowserCallbackInterface() {
@Override
- public void onChildrenLoaded(String parentIdOut, int pageOut, int pageSizeOut,
+ public void onGetChildrenDone(String parentIdOut, int pageOut, int pageSizeOut,
List<MediaItem2> result, Bundle extrasOut) {
assertEquals(parentId, parentIdOut);
assertEquals(page, pageOut);
@@ -192,7 +193,7 @@
final CountDownLatch latch = new CountDownLatch(1);
final TestControllerCallbackInterface callback = new TestBrowserCallbackInterface() {
@Override
- public void onChildrenLoaded(String parentIdOut, int pageOut, int pageSizeOut,
+ public void onGetChildrenDone(String parentIdOut, int pageOut, int pageSizeOut,
List<MediaItem2> result, Bundle extrasOut) {
assertNotNull(result);
assertEquals(0, result.size());
@@ -213,7 +214,7 @@
final CountDownLatch latch = new CountDownLatch(1);
final TestControllerCallbackInterface callback = new TestBrowserCallbackInterface() {
@Override
- public void onChildrenLoaded(String parentIdOut, int pageOut, int pageSizeOut,
+ public void onGetChildrenDone(String parentIdOut, int pageOut, int pageSizeOut,
List<MediaItem2> result, Bundle extrasOut) {
assertNull(result);
latch.countDown();
@@ -246,7 +247,7 @@
}
@Override
- public void onSearchResultLoaded(String queryOut, int pageOut, int pageSizeOut,
+ public void onGetSearchResultDone(String queryOut, int pageOut, int pageSizeOut,
List<MediaItem2> result, Bundle extrasOut) {
assertEquals(query, queryOut);
assertEquals(page, pageOut);
@@ -336,7 +337,7 @@
final CountDownLatch latch = new CountDownLatch(1);
final SessionCallbackProxy callbackProxy = new SessionCallbackProxy(mContext) {
@Override
- public void onSubscribed(ControllerInfo info, String parentId, Bundle extras) {
+ public void onSubscribe(ControllerInfo info, String parentId, Bundle extras) {
if (Process.myUid() == info.getUid()) {
assertEquals(testParentId, parentId);
assertTrue(TestUtils.equals(testExtras, extras));
@@ -357,7 +358,7 @@
final CountDownLatch latch = new CountDownLatch(1);
final SessionCallbackProxy callbackProxy = new SessionCallbackProxy(mContext) {
@Override
- public void onUnsubscribed(ControllerInfo info, String parentId) {
+ public void onUnsubscribe(ControllerInfo info, String parentId) {
if (Process.myUid() == info.getUid()) {
assertEquals(testParentId, parentId);
latch.countDown();
@@ -395,7 +396,7 @@
}
@Override
- public void onSubscribed(ControllerInfo info, String parentId, Bundle extras) {
+ public void onSubscribe(ControllerInfo info, String parentId, Bundle extras) {
if (Process.myUid() == info.getUid()) {
final MediaLibrarySession session = (MediaLibrarySession) mSession;
session.notifyChildrenChanged(testParentId2, testChildrenCount, null);
@@ -407,18 +408,17 @@
final TestBrowserCallbackInterface controllerCallbackProxy =
new TestBrowserCallbackInterface() {
@Override
- public void onChildrenChanged(String parentId, int childCount,
- Bundle extras) {
+ public void onChildrenChanged(String parentId, int itemCount, Bundle extras) {
switch ((int) latch.getCount()) {
case 3:
assertEquals(testParentId2, parentId);
- assertEquals(testChildrenCount, childCount);
+ assertEquals(testChildrenCount, itemCount);
assertNull(extras);
latch.countDown();
break;
case 2:
assertEquals(testParentId2, parentId);
- assertEquals(testChildrenCount, childCount);
+ assertEquals(testChildrenCount, itemCount);
assertTrue(TestUtils.equals(testExtras, extras));
latch.countDown();
break;
@@ -496,29 +496,29 @@
}
@Override
- public void onGetRootResult(Bundle rootHints, String rootMediaId, Bundle rootExtra) {
- super.onGetRootResult(rootHints, rootMediaId, rootExtra);
+ public void onGetLibraryRootDone(Bundle rootHints, String rootMediaId, Bundle rootExtra) {
+ super.onGetLibraryRootDone(rootHints, rootMediaId, rootExtra);
if (mCallbackProxy instanceof TestBrowserCallbackInterface) {
((TestBrowserCallbackInterface) mCallbackProxy)
- .onGetRootResult(rootHints, rootMediaId, rootExtra);
+ .onGetLibraryRootDone(rootHints, rootMediaId, rootExtra);
}
}
@Override
- public void onItemLoaded(String mediaId, MediaItem2 result) {
- super.onItemLoaded(mediaId, result);
+ public void onGetItemDone(String mediaId, MediaItem2 result) {
+ super.onGetItemDone(mediaId, result);
if (mCallbackProxy instanceof TestBrowserCallbackInterface) {
- ((TestBrowserCallbackInterface) mCallbackProxy).onItemLoaded(mediaId, result);
+ ((TestBrowserCallbackInterface) mCallbackProxy).onGetItemDone(mediaId, result);
}
}
@Override
- public void onChildrenLoaded(String parentId, int page, int pageSize,
+ public void onGetChildrenDone(String parentId, int page, int pageSize,
List<MediaItem2> result, Bundle extras) {
- super.onChildrenLoaded(parentId, page, pageSize, result, extras);
+ super.onGetChildrenDone(parentId, page, pageSize, result, extras);
if (mCallbackProxy instanceof TestBrowserCallbackInterface) {
((TestBrowserCallbackInterface) mCallbackProxy)
- .onChildrenLoaded(parentId, page, pageSize, result, extras);
+ .onGetChildrenDone(parentId, page, pageSize, result, extras);
}
}
@@ -532,21 +532,21 @@
}
@Override
- public void onSearchResultLoaded(String query, int page, int pageSize,
+ public void onGetSearchResultDone(String query, int page, int pageSize,
List<MediaItem2> result, Bundle extras) {
- super.onSearchResultLoaded(query, page, pageSize, result, extras);
+ super.onGetSearchResultDone(query, page, pageSize, result, extras);
if (mCallbackProxy instanceof TestBrowserCallbackInterface) {
((TestBrowserCallbackInterface) mCallbackProxy)
- .onSearchResultLoaded(query, page, pageSize, result, extras);
+ .onGetSearchResultDone(query, page, pageSize, result, extras);
}
}
@Override
- public void onChildrenChanged(String parentId, int childCount, Bundle extras) {
- super.onChildrenChanged(parentId, childCount, extras);
+ public void onChildrenChanged(String parentId, int itemCount, Bundle extras) {
+ super.onChildrenChanged(parentId, itemCount, extras);
if (mCallbackProxy instanceof TestBrowserCallbackInterface) {
((TestBrowserCallbackInterface) mCallbackProxy)
- .onChildrenChanged(parentId, childCount, extras);
+ .onChildrenChanged(parentId, itemCount, extras);
}
}
diff --git a/packages/MediaComponents/test/src/android/media/MediaController2Test.java b/packages/MediaComponents/test/src/android/media/MediaController2Test.java
index e162f1d..69769bf 100644
--- a/packages/MediaComponents/test/src/android/media/MediaController2Test.java
+++ b/packages/MediaComponents/test/src/android/media/MediaController2Test.java
@@ -19,7 +19,7 @@
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
-import android.media.MediaPlayerInterface.EventCallback;
+import android.media.MediaPlayerBase.EventCallback;
import android.media.MediaSession2.Command;
import android.media.MediaSession2.CommandGroup;
import android.media.MediaSession2.ControllerInfo;
@@ -39,6 +39,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -76,7 +77,7 @@
mPlayer = new MockPlayer(1);
mSession = new MediaSession2.Builder(mContext, mPlayer)
- .setSessionCallback(sHandlerExecutor, new SessionCallback(mContext))
+ .setSessionCallback(sHandlerExecutor, new SessionCallback(mContext) {})
.setSessionActivity(mIntent)
.setId(TAG).build();
mController = createController(mSession.getToken());
@@ -194,18 +195,22 @@
assertEquals(seekPosition, mPlayer.mSeekPosition);
}
+ // TODO(jaewan): Re-enable this test
+ /*
@Test
public void testSetCurrentPlaylistItem() throws InterruptedException {
+ final
final int itemIndex = 9;
- mController.setCurrentPlaylistItem(itemIndex);
+ mController.skipToPlaylistItem(itemIndex);
try {
assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
} catch (InterruptedException e) {
fail(e.getMessage());
}
assertTrue(mPlayer.mSetCurrentPlaylistItemCalled);
- assertEquals(itemIndex, mPlayer.mItemIndex);
+ assertEquals(itemIndex, mPlayer.mCurrentItem);
}
+ */
@Test
public void testGetSessionActivity() throws InterruptedException {
@@ -578,7 +583,7 @@
final MockPlayer player = new MockPlayer(0);
sessionHandler.postAndSync(() -> {
mSession = new MediaSession2.Builder(mContext, mPlayer)
- .setSessionCallback(sHandlerExecutor, new SessionCallback(mContext))
+ .setSessionCallback(sHandlerExecutor, new SessionCallback(mContext) {})
.setId("testDeadlock").build();
});
final MediaController2 controller = createController(mSession.getToken());
@@ -722,11 +727,13 @@
testControllerAfterSessionIsGone(id);
}
+ @Ignore
@Test
public void testClose_sessionService() throws InterruptedException {
testCloseFromService(MockMediaSessionService2.ID);
}
+ @Ignore
@Test
public void testClose_libraryService() throws InterruptedException {
testCloseFromService(MockMediaLibraryService2.ID);
@@ -766,7 +773,7 @@
// Recreated session has different session stub, so previously created controller
// shouldn't be available.
mSession = new MediaSession2.Builder(mContext, mPlayer)
- .setSessionCallback(sHandlerExecutor, new SessionCallback(mContext))
+ .setSessionCallback(sHandlerExecutor, new SessionCallback(mContext) {})
.setId(id).build();
});
testNoInteraction();
diff --git a/packages/MediaComponents/test/src/android/media/MediaMetadata2Test.java b/packages/MediaComponents/test/src/android/media/MediaMetadata2Test.java
index ea42651..06b51bd 100644
--- a/packages/MediaComponents/test/src/android/media/MediaMetadata2Test.java
+++ b/packages/MediaComponents/test/src/android/media/MediaMetadata2Test.java
@@ -42,20 +42,20 @@
@Test
public void testBuilder() {
- final Bundle extra = new Bundle();
- extra.putString("MediaMetadata2Test", "testBuilder");
+ final Bundle extras = new Bundle();
+ extras.putString("MediaMetadata2Test", "testBuilder");
final String title = "title";
final long discNumber = 10;
final Rating2 rating = Rating2.newThumbRating(mContext, true);
MediaMetadata2.Builder builder = new Builder(mContext);
- builder.setExtra(extra);
+ builder.setExtras(extras);
builder.putString(MediaMetadata2.METADATA_KEY_DISPLAY_TITLE, title);
builder.putLong(MediaMetadata2.METADATA_KEY_DISC_NUMBER, discNumber);
builder.putRating(MediaMetadata2.METADATA_KEY_USER_RATING, rating);
MediaMetadata2 metadata = builder.build();
- assertTrue(TestUtils.equals(extra, metadata.getExtra()));
+ assertTrue(TestUtils.equals(extras, metadata.getExtras()));
assertEquals(title, metadata.getString(MediaMetadata2.METADATA_KEY_DISPLAY_TITLE));
assertEquals(discNumber, metadata.getLong(MediaMetadata2.METADATA_KEY_DISC_NUMBER));
assertEquals(rating, metadata.getRating(MediaMetadata2.METADATA_KEY_USER_RATING));
diff --git a/packages/MediaComponents/test/src/android/media/MediaSession2Test.java b/packages/MediaComponents/test/src/android/media/MediaSession2Test.java
index 9de4ce7..441d38c 100644
--- a/packages/MediaComponents/test/src/android/media/MediaSession2Test.java
+++ b/packages/MediaComponents/test/src/android/media/MediaSession2Test.java
@@ -29,7 +29,7 @@
import android.content.Context;
import android.media.MediaController2.PlaybackInfo;
-import android.media.MediaPlayerInterface.EventCallback;
+import android.media.MediaPlayerBase.EventCallback;
import android.media.MediaSession2.Builder;
import android.media.MediaSession2.Command;
import android.media.MediaSession2.CommandButton;
@@ -73,7 +73,7 @@
super.setUp();
mPlayer = new MockPlayer(0);
mSession = new MediaSession2.Builder(mContext, mPlayer)
- .setSessionCallback(sHandlerExecutor, new SessionCallback(mContext)).build();
+ .setSessionCallback(sHandlerExecutor, new SessionCallback(mContext) {}).build();
}
@After
diff --git a/packages/MediaComponents/test/src/android/media/MediaSession2TestBase.java b/packages/MediaComponents/test/src/android/media/MediaSession2TestBase.java
index 7106561..c30b9a6 100644
--- a/packages/MediaComponents/test/src/android/media/MediaSession2TestBase.java
+++ b/packages/MediaComponents/test/src/android/media/MediaSession2TestBase.java
@@ -117,8 +117,7 @@
* @return a PlaybackState
*/
public PlaybackState2 createPlaybackState(int state) {
- return new PlaybackState2(mContext, state, 0, 0, 1.0f,
- 0, 0);
+ return new PlaybackState2(mContext, state, 0, 0, 1.0f, 0, 0);
}
final MediaController2 createController(SessionToken2 token) throws InterruptedException {
diff --git a/packages/MediaComponents/test/src/android/media/MediaSessionManager_MediaSession2.java b/packages/MediaComponents/test/src/android/media/MediaSessionManager_MediaSession2.java
index d61baab..50599b6 100644
--- a/packages/MediaComponents/test/src/android/media/MediaSessionManager_MediaSession2.java
+++ b/packages/MediaComponents/test/src/android/media/MediaSessionManager_MediaSession2.java
@@ -55,7 +55,7 @@
// per test thread differs across the {@link MediaSession2} with the same TAG.
final MockPlayer player = new MockPlayer(1);
mSession = new MediaSession2.Builder(mContext, player)
- .setSessionCallback(sHandlerExecutor, new SessionCallback(mContext))
+ .setSessionCallback(sHandlerExecutor, new SessionCallback(mContext) { })
.setId(TAG)
.build();
ensureChangeInSession();
diff --git a/packages/MediaComponents/test/src/android/media/MockMediaLibraryService2.java b/packages/MediaComponents/test/src/android/media/MockMediaLibraryService2.java
index e1cce25..b0fbde0 100644
--- a/packages/MediaComponents/test/src/android/media/MockMediaLibraryService2.java
+++ b/packages/MediaComponents/test/src/android/media/MockMediaLibraryService2.java
@@ -23,6 +23,8 @@
import android.content.Context;
import android.media.MediaSession2.CommandGroup;
import android.media.MediaSession2.ControllerInfo;
+import android.media.MediaLibraryService2.MediaLibrarySession;
+import android.media.MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback;
import android.media.TestServiceRegistry.SessionCallbackProxy;
import android.media.TestUtils.SyncHandler;
import android.os.Bundle;
@@ -112,7 +114,7 @@
}
TestLibrarySessionCallback callback =
new TestLibrarySessionCallback(sessionCallbackProxy);
- mSession = new MediaLibrarySessionBuilder(MockMediaLibraryService2.this, player,
+ mSession = new MediaLibrarySession.Builder(MockMediaLibraryService2.this, player,
executor, callback).setId(sessionId).build();
return mSession;
}
@@ -148,12 +150,12 @@
}
@Override
- public LibraryRoot onGetRoot(ControllerInfo controller, Bundle rootHints) {
+ public LibraryRoot onGetLibraryRoot(ControllerInfo controller, Bundle rootHints) {
return new LibraryRoot(MockMediaLibraryService2.this, ROOT_ID, EXTRAS);
}
@Override
- public MediaItem2 onLoadItem(ControllerInfo controller, String mediaId) {
+ public MediaItem2 onGetItem(ControllerInfo controller, String mediaId) {
if (MEDIA_ID_GET_ITEM.equals(mediaId)) {
return createMediaItem(mediaId);
} else {
@@ -162,7 +164,7 @@
}
@Override
- public List<MediaItem2> onLoadChildren(ControllerInfo controller, String parentId, int page,
+ public List<MediaItem2> onGetChildren(ControllerInfo controller, String parentId, int page,
int pageSize, Bundle extras) {
if (PARENT_ID.equals(parentId)) {
return getPaginatedResult(GET_CHILDREN_RESULT, page, pageSize);
@@ -195,7 +197,7 @@
}
@Override
- public List<MediaItem2> onLoadSearchResult(ControllerInfo controllerInfo,
+ public List<MediaItem2> onGetSearchResult(ControllerInfo controllerInfo,
String query, int page, int pageSize, Bundle extras) {
if (SEARCH_QUERY.equals(query)) {
return getPaginatedResult(SEARCH_RESULT, page, pageSize);
@@ -205,13 +207,13 @@
}
@Override
- public void onSubscribed(ControllerInfo controller, String parentId, Bundle extras) {
- mCallbackProxy.onSubscribed(controller, parentId, extras);
+ public void onSubscribe(ControllerInfo controller, String parentId, Bundle extras) {
+ mCallbackProxy.onSubscribe(controller, parentId, extras);
}
@Override
- public void onUnsubscribed(ControllerInfo controller, String parentId) {
- mCallbackProxy.onUnsubscribed(controller, parentId);
+ public void onUnsubscribe(ControllerInfo controller, String parentId) {
+ mCallbackProxy.onUnsubscribe(controller, parentId);
}
}
diff --git a/packages/MediaComponents/test/src/android/media/MockMediaSessionService2.java b/packages/MediaComponents/test/src/android/media/MockMediaSessionService2.java
index 12c2c9f..b63104a 100644
--- a/packages/MediaComponents/test/src/android/media/MockMediaSessionService2.java
+++ b/packages/MediaComponents/test/src/android/media/MockMediaSessionService2.java
@@ -77,7 +77,7 @@
}
@Override
- public MediaNotification onUpdateNotification(PlaybackState2 state) {
+ public MediaNotification onUpdateNotification() {
if (mDefaultNotificationChannel == null) {
mDefaultNotificationChannel = new NotificationChannel(
DEFAULT_MEDIA_NOTIFICATION_CHANNEL_ID,
@@ -88,7 +88,7 @@
Notification notification = new Notification.Builder(
this, DEFAULT_MEDIA_NOTIFICATION_CHANNEL_ID)
.setContentTitle(getPackageName())
- .setContentText("Playback state: " + state.getState())
+ .setContentText("Dummt test notification")
.setSmallIcon(android.R.drawable.sym_def_app_icon).build();
return new MediaNotification(this, DEFAULT_MEDIA_NOTIFICATION_ID, notification);
}
diff --git a/packages/MediaComponents/test/src/android/media/MockPlayer.java b/packages/MediaComponents/test/src/android/media/MockPlayer.java
index ae31ce6..1b3da73 100644
--- a/packages/MediaComponents/test/src/android/media/MockPlayer.java
+++ b/packages/MediaComponents/test/src/android/media/MockPlayer.java
@@ -21,15 +21,14 @@
import android.support.annotation.Nullable;
import android.util.ArrayMap;
-import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
/**
- * A mock implementation of {@link MediaPlayerInterface} for testing.
+ * A mock implementation of {@link MediaPlayerBase} for testing.
*/
-public class MockPlayer implements MediaPlayerInterface {
+public class MockPlayer extends MediaPlayerBase {
public final CountDownLatch mCountDownLatch;
public boolean mPlayCalled;
@@ -43,7 +42,7 @@
public boolean mSeekToCalled;
public long mSeekPosition;
public boolean mSetCurrentPlaylistItemCalled;
- public int mItemIndex;
+ public MediaItem2 mCurrentItem;
public boolean mSetPlaylistCalled;
public boolean mSetPlaylistParamsCalled;
@@ -59,6 +58,11 @@
}
@Override
+ public void close() {
+ // no-op
+ }
+
+ @Override
public void play() {
mPlayCalled = true;
if (mCountDownLatch != null) {
@@ -132,9 +136,9 @@
}
@Override
- public void setCurrentPlaylistItem(int index) {
+ public void setCurrentPlaylistItem(MediaItem2 item) {
mSetCurrentPlaylistItemCalled = true;
- mItemIndex = index;
+ mCurrentItem = item;
if (mCountDownLatch != null) {
mCountDownLatch.countDown();
}
@@ -147,6 +151,11 @@
}
@Override
+ public int getPlayerState() {
+ return mLastPlaybackState.getState();
+ }
+
+ @Override
public void registerEventCallback(@NonNull Executor executor,
@NonNull EventCallback callback) {
mCallbacks.put(callback, executor);
diff --git a/packages/MediaComponents/test/src/android/media/TestServiceRegistry.java b/packages/MediaComponents/test/src/android/media/TestServiceRegistry.java
index a18ad8e..08e0cf0 100644
--- a/packages/MediaComponents/test/src/android/media/TestServiceRegistry.java
+++ b/packages/MediaComponents/test/src/android/media/TestServiceRegistry.java
@@ -75,8 +75,8 @@
*/
public void onServiceDestroyed() { }
- public void onSubscribed(ControllerInfo info, String parentId, Bundle extra) { }
- public void onUnsubscribed(ControllerInfo info, String parentId) { }
+ public void onSubscribe(ControllerInfo info, String parentId, Bundle extra) { }
+ public void onUnsubscribe(ControllerInfo info, String parentId) { }
}
@GuardedBy("TestServiceRegistry.class")
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 9a30f71..229e08e 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -39,8 +39,8 @@
#include <memunreachable/memunreachable.h>
#include <utils/String16.h>
#include <utils/threads.h>
-#include <utils/Atomic.h>
+#include <cutils/atomic.h>
#include <cutils/properties.h>
#include <system/audio.h>
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index ebd1b18..0e2da4e 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -27,6 +27,7 @@
#include <android-base/macros.h>
+#include <cutils/atomic.h>
#include <cutils/compiler.h>
#include <cutils/properties.h>
@@ -38,7 +39,6 @@
#include <media/MmapStreamInterface.h>
#include <media/MmapStreamCallback.h>
-#include <utils/Atomic.h>
#include <utils/Errors.h>
#include <utils/threads.h>
#include <utils/SortedVector.h>
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 0ce5350..979290f 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -589,13 +589,6 @@
status = cmdStatus;
}
- // Ignore error if non-offloadable effect is created on an offload thread.
- // Will be switched to non-offload thread when the effect is enabled.
- if (status != NO_ERROR && thread->type() == ThreadBase::OFFLOAD && !isOffloaded()) {
- ALOGV("Ignore error %d on non-offloadable effect on offload thread", status);
- status = NO_ERROR;
- }
-
#ifdef MULTICHANNEL_EFFECT_CHAIN
if (status != NO_ERROR &&
(mConfig.inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 1df6b6a..dcc7ad2 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -2239,9 +2239,13 @@
// Transition device availability listeners from PRESENT -> NOT_AVAILABLE
sCameraService->updateStatus(StatusInternal::NOT_AVAILABLE, mCameraIdStr);
+ int apiLevel = hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1;
+ if (canCastToApiClient(API_2)) {
+ apiLevel = hardware::ICameraServiceProxy::CAMERA_API_LEVEL_2;
+ }
// Transition device state to OPEN
sCameraService->updateProxyDeviceState(ICameraServiceProxy::CAMERA_STATE_OPEN,
- mCameraIdStr, mCameraFacing, mClientPackageName);
+ mCameraIdStr, mCameraFacing, mClientPackageName, apiLevel);
return OK;
}
@@ -2266,9 +2270,13 @@
sCameraService->updateStatus(StatusInternal::PRESENT,
mCameraIdStr, rejected);
+ int apiLevel = hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1;
+ if (canCastToApiClient(API_2)) {
+ apiLevel = hardware::ICameraServiceProxy::CAMERA_API_LEVEL_2;
+ }
// Transition device state to CLOSED
sCameraService->updateProxyDeviceState(ICameraServiceProxy::CAMERA_STATE_CLOSED,
- mCameraIdStr, mCameraFacing, mClientPackageName);
+ mCameraIdStr, mCameraFacing, mClientPackageName, apiLevel);
}
// Always stop watching, even if no camera op is active
if (mOpsCallback != NULL) {
@@ -2884,11 +2892,11 @@
}
void CameraService::updateProxyDeviceState(int newState,
- const String8& cameraId, int facing, const String16& clientName) {
+ const String8& cameraId, int facing, const String16& clientName, int apiLevel) {
sp<ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
if (proxyBinder == nullptr) return;
String16 id(cameraId);
- proxyBinder->notifyCameraState(id, newState, facing, clientName);
+ proxyBinder->notifyCameraState(id, newState, facing, clientName, apiLevel);
}
status_t CameraService::getTorchStatusLocked(
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index cbfc50b..3812925 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -189,7 +189,8 @@
int newState,
const String8& cameraId,
int facing,
- const String16& clientName);
+ const String16& clientName,
+ int apiLevel);
/////////////////////////////////////////////////////////////////////
// CameraDeviceFactory functionality
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index f6d27ab..f1203f9 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -263,7 +263,8 @@
mHardware->stopPreview();
sCameraService->updateProxyDeviceState(
hardware::ICameraServiceProxy::CAMERA_STATE_IDLE,
- mCameraIdStr, mCameraFacing, mClientPackageName);
+ mCameraIdStr, mCameraFacing, mClientPackageName,
+ hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1);
mHardware->cancelPicture();
// Release the hardware resources.
mHardware->release();
@@ -425,7 +426,8 @@
if (result == NO_ERROR) {
sCameraService->updateProxyDeviceState(
hardware::ICameraServiceProxy::CAMERA_STATE_ACTIVE,
- mCameraIdStr, mCameraFacing, mClientPackageName);
+ mCameraIdStr, mCameraFacing, mClientPackageName,
+ hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1);
}
return result;
}
@@ -468,7 +470,8 @@
mHardware->stopPreview();
sCameraService->updateProxyDeviceState(
hardware::ICameraServiceProxy::CAMERA_STATE_IDLE,
- mCameraIdStr, mCameraFacing, mClientPackageName);
+ mCameraIdStr, mCameraFacing, mClientPackageName,
+ hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1);
mPreviewBuffer.clear();
}
@@ -974,7 +977,8 @@
// idle now, until preview is restarted
sCameraService->updateProxyDeviceState(
hardware::ICameraServiceProxy::CAMERA_STATE_IDLE,
- mCameraIdStr, mCameraFacing, mClientPackageName);
+ mCameraIdStr, mCameraFacing, mClientPackageName,
+ hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1);
mLock.unlock();
}
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 459e45d..ce006a7 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -253,7 +253,9 @@
if (mDeviceActive) {
getCameraService()->updateProxyDeviceState(
hardware::ICameraServiceProxy::CAMERA_STATE_IDLE, TClientBase::mCameraIdStr,
- TClientBase::mCameraFacing, TClientBase::mClientPackageName);
+ TClientBase::mCameraFacing, TClientBase::mClientPackageName,
+ ((mApi1CameraId < 0) ? hardware::ICameraServiceProxy::CAMERA_API_LEVEL_2 :
+ hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1));
}
mDeviceActive = false;
@@ -269,7 +271,9 @@
if (!mDeviceActive) {
getCameraService()->updateProxyDeviceState(
hardware::ICameraServiceProxy::CAMERA_STATE_ACTIVE, TClientBase::mCameraIdStr,
- TClientBase::mCameraFacing, TClientBase::mClientPackageName);
+ TClientBase::mCameraFacing, TClientBase::mClientPackageName,
+ ((mApi1CameraId < 0) ? hardware::ICameraServiceProxy::CAMERA_API_LEVEL_2 :
+ hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1));
}
mDeviceActive = true;