NdkMediaExtractor: per-sample format metadata API
Bug: 63934228
Test: MediaPlayer2Test
Change-Id: I8ac081ba91152b1bb2e7bb61bf6977f90bcb8e3c
diff --git a/media/ndk/NdkMediaExtractor.cpp b/media/ndk/NdkMediaExtractor.cpp
index ea43d2e..ac837a3 100644
--- a/media/ndk/NdkMediaExtractor.cpp
+++ b/media/ndk/NdkMediaExtractor.cpp
@@ -43,7 +43,12 @@
static media_status_t translate_error(status_t err) {
if (err == OK) {
return AMEDIA_OK;
+ } else if (err == ERROR_END_OF_STREAM) {
+ return AMEDIA_ERROR_END_OF_STREAM;
+ } else if (err == ERROR_IO) {
+ return AMEDIA_ERROR_IO;
}
+
ALOGE("sf error code: %d", err);
return AMEDIA_ERROR_UNKNOWN;
}
@@ -411,5 +416,64 @@
return -1;
}
+EXPORT
+media_status_t AMediaExtractor_getSampleFormat(AMediaExtractor *ex, AMediaFormat *fmt) {
+ if (fmt == NULL) {
+ return AMEDIA_ERROR_INVALID_PARAMETER;
+ }
+
+ sp<MetaData> sampleMeta;
+ status_t err = ex->mImpl->getSampleMeta(&sampleMeta);
+ if (err != OK) {
+ return translate_error(err);
+ }
+
+ sp<AMessage> meta;
+ AMediaFormat_getFormat(fmt, &meta);
+ meta->clear();
+
+ int32_t layerId;
+ if (sampleMeta->findInt32(kKeyTemporalLayerId, &layerId)) {
+ meta->setInt32(AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID, layerId);
+ }
+
+ size_t trackIndex;
+ err = ex->mImpl->getSampleTrackIndex(&trackIndex);
+ if (err == OK) {
+ meta->setInt32(AMEDIAFORMAT_KEY_TRACK_INDEX, trackIndex);
+ sp<AMessage> trackFormat;
+ AString mime;
+ err = ex->mImpl->getTrackFormat(trackIndex, &trackFormat);
+ if (err == OK
+ && trackFormat != NULL
+ && trackFormat->findString(AMEDIAFORMAT_KEY_MIME, &mime)) {
+ meta->setString(AMEDIAFORMAT_KEY_MIME, mime);
+ }
+ }
+
+ int64_t durationUs;
+ if (sampleMeta->findInt64(kKeyDuration, &durationUs)) {
+ meta->setInt64(AMEDIAFORMAT_KEY_DURATION, durationUs);
+ }
+
+ uint32_t dataType; // unused
+ const void *seiData;
+ size_t seiLength;
+ if (sampleMeta->findData(kKeySEI, &dataType, &seiData, &seiLength)) {
+ sp<ABuffer> sei = ABuffer::CreateAsCopy(seiData, seiLength);;
+ meta->setBuffer(AMEDIAFORMAT_KEY_SEI, sei);
+ }
+
+ const void *mpegUserDataPointer;
+ size_t mpegUserDataLength;
+ if (sampleMeta->findData(
+ kKeyMpegUserData, &dataType, &mpegUserDataPointer, &mpegUserDataLength)) {
+ sp<ABuffer> mpegUserData = ABuffer::CreateAsCopy(mpegUserDataPointer, mpegUserDataLength);
+ meta->setBuffer(AMEDIAFORMAT_KEY_MPEG_USER_DATA, mpegUserData);
+ }
+
+ return AMEDIA_OK;
+}
+
} // extern "C"
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index b86876b..abcaa0a 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -309,6 +309,7 @@
EXPORT const char* AMEDIAFORMAT_KEY_MAX_INPUT_SIZE = "max-input-size";
EXPORT const char* AMEDIAFORMAT_KEY_MAX_WIDTH = "max-width";
EXPORT const char* AMEDIAFORMAT_KEY_MIME = "mime";
+EXPORT const char* AMEDIAFORMAT_KEY_MPEG_USER_DATA = "mpeg-user-data";
EXPORT const char* AMEDIAFORMAT_KEY_OPERATING_RATE = "operating-rate";
EXPORT const char* AMEDIAFORMAT_KEY_PCM_ENCODING = "pcm-encoding";
EXPORT const char* AMEDIAFORMAT_KEY_PRIORITY = "priority";
@@ -317,10 +318,13 @@
EXPORT const char* AMEDIAFORMAT_KEY_REPEAT_PREVIOUS_FRAME_AFTER = "repeat-previous-frame-after";
EXPORT const char* AMEDIAFORMAT_KEY_ROTATION = "rotation-degrees";
EXPORT const char* AMEDIAFORMAT_KEY_SAMPLE_RATE = "sample-rate";
+EXPORT const char* AMEDIAFORMAT_KEY_SEI = "sei";
EXPORT const char* AMEDIAFORMAT_KEY_SLICE_HEIGHT = "slice-height";
EXPORT const char* AMEDIAFORMAT_KEY_STRIDE = "stride";
+EXPORT const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID = "temporal-layer-id";
EXPORT const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYERING = "ts-schema";
EXPORT const char* AMEDIAFORMAT_KEY_TRACK_ID = "track-id";
+EXPORT const char* AMEDIAFORMAT_KEY_TRACK_INDEX = "track-index";
EXPORT const char* AMEDIAFORMAT_KEY_WIDTH = "width";
diff --git a/media/ndk/include/media/NdkMediaError.h b/media/ndk/include/media/NdkMediaError.h
index e48fcbe..13aacc9 100644
--- a/media/ndk/include/media/NdkMediaError.h
+++ b/media/ndk/include/media/NdkMediaError.h
@@ -53,6 +53,8 @@
AMEDIA_ERROR_INVALID_OBJECT = AMEDIA_ERROR_BASE - 3,
AMEDIA_ERROR_INVALID_PARAMETER = AMEDIA_ERROR_BASE - 4,
AMEDIA_ERROR_INVALID_OPERATION = AMEDIA_ERROR_BASE - 5,
+ AMEDIA_ERROR_END_OF_STREAM = AMEDIA_ERROR_BASE - 6,
+ AMEDIA_ERROR_IO = AMEDIA_ERROR_BASE - 7,
AMEDIA_DRM_ERROR_BASE = -20000,
AMEDIA_DRM_NOT_PROVISIONED = AMEDIA_DRM_ERROR_BASE - 1,
diff --git a/media/ndk/include/media/NdkMediaExtractor.h b/media/ndk/include/media/NdkMediaExtractor.h
index 3c9e23d..f7b9cfd 100644
--- a/media/ndk/include/media/NdkMediaExtractor.h
+++ b/media/ndk/include/media/NdkMediaExtractor.h
@@ -203,6 +203,17 @@
*/
int64_t AMediaExtractor_getCachedDuration(AMediaExtractor *);
+/**
+ * Read the current sample's metadata format into |fmt|. Examples of sample metadata are
+ * SEI (supplemental enhancement information) and MPEG user data, both of which can embed
+ * closed-caption data.
+ *
+ * Returns AMEDIA_OK on success or AMEDIA_ERROR_* to indicate failure reason.
+ * Existing key-value pairs in |fmt| would be removed if this API returns AMEDIA_OK.
+ * The contents of |fmt| is undefined if this API returns AMEDIA_ERROR_*.
+ */
+media_status_t AMediaExtractor_getSampleFormat(AMediaExtractor *ex, AMediaFormat *fmt);
+
#endif /* __ANDROID_API__ >= 28 */
#endif /* __ANDROID_API__ >= 21 */
diff --git a/media/ndk/include/media/NdkMediaFormat.h b/media/ndk/include/media/NdkMediaFormat.h
index b6489c7..464c127 100644
--- a/media/ndk/include/media/NdkMediaFormat.h
+++ b/media/ndk/include/media/NdkMediaFormat.h
@@ -123,6 +123,7 @@
extern const char* AMEDIAFORMAT_KEY_MAX_INPUT_SIZE;
extern const char* AMEDIAFORMAT_KEY_MAX_WIDTH;
extern const char* AMEDIAFORMAT_KEY_MIME;
+extern const char* AMEDIAFORMAT_KEY_MPEG_USER_DATA;
extern const char* AMEDIAFORMAT_KEY_OPERATING_RATE;
extern const char* AMEDIAFORMAT_KEY_PCM_ENCODING;
extern const char* AMEDIAFORMAT_KEY_PRIORITY;
@@ -131,10 +132,13 @@
extern const char* AMEDIAFORMAT_KEY_REPEAT_PREVIOUS_FRAME_AFTER;
extern const char* AMEDIAFORMAT_KEY_ROTATION;
extern const char* AMEDIAFORMAT_KEY_SAMPLE_RATE;
+extern const char* AMEDIAFORMAT_KEY_SEI;
extern const char* AMEDIAFORMAT_KEY_SLICE_HEIGHT;
extern const char* AMEDIAFORMAT_KEY_STRIDE;
+extern const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID;
extern const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYERING;
extern const char* AMEDIAFORMAT_KEY_TRACK_ID;
+extern const char* AMEDIAFORMAT_KEY_TRACK_INDEX;
extern const char* AMEDIAFORMAT_KEY_WIDTH;
#endif /* __ANDROID_API__ >= 21 */
diff --git a/media/ndk/libmediandk.map.txt b/media/ndk/libmediandk.map.txt
index 17c1a0d..d8c41d2 100644
--- a/media/ndk/libmediandk.map.txt
+++ b/media/ndk/libmediandk.map.txt
@@ -159,6 +159,7 @@
AMediaExtractor_getPsshInfo;
AMediaExtractor_getSampleCryptoInfo;
AMediaExtractor_getSampleFlags;
+ AMediaExtractor_getSampleFormat; # introduced=28
AMediaExtractor_getSampleSize; # introduced=28
AMediaExtractor_getSampleTime;
AMediaExtractor_getSampleTrackIndex;