media: add list of codecs in dumpsys media.player
Test: adb shell dumpsys media.player
Change-Id: I4e074c472496ebaa0ec2b966088949ce2eea4671
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index dfd3933..8ac169f 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -58,6 +58,7 @@
#include <media/AudioTrack.h>
#include <media/MemoryLeakTrackUtil.h>
#include <media/stagefright/InterfaceUtils.h>
+#include <media/stagefright/MediaCodecConstants.h>
#include <media/stagefright/MediaCodecList.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/Utils.h>
@@ -264,6 +265,172 @@
return ok;
}
+static void dumpCodecDetails(int fd, const sp<IMediaCodecList> &codecList, bool queryDecoders) {
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ const char *codecType = queryDecoders? "Decoder" : "Encoder";
+ snprintf(buffer, SIZE - 1, "\n%s infos by media types:\n"
+ "=============================\n", codecType);
+ result.append(buffer);
+
+ size_t numCodecs = codecList->countCodecs();
+
+ // gather all media types supported by codec class, and link to codecs that support them
+ KeyedVector<AString, Vector<sp<MediaCodecInfo>>> allMediaTypes;
+ for (size_t codec_ix = 0; codec_ix < numCodecs; ++codec_ix) {
+ sp<MediaCodecInfo> info = codecList->getCodecInfo(codec_ix);
+ if (info->isEncoder() == !queryDecoders) {
+ Vector<AString> supportedMediaTypes;
+ info->getSupportedMediaTypes(&supportedMediaTypes);
+ if (!supportedMediaTypes.size()) {
+ snprintf(buffer, SIZE - 1, "warning: %s does not support any media types\n",
+ info->getCodecName());
+ result.append(buffer);
+ } else {
+ for (const AString &mediaType : supportedMediaTypes) {
+ if (allMediaTypes.indexOfKey(mediaType) < 0) {
+ allMediaTypes.add(mediaType, Vector<sp<MediaCodecInfo>>());
+ }
+ allMediaTypes.editValueFor(mediaType).add(info);
+ }
+ }
+ }
+ }
+
+ KeyedVector<AString, bool> visitedCodecs;
+ for (size_t type_ix = 0; type_ix < allMediaTypes.size(); ++type_ix) {
+ const AString &mediaType = allMediaTypes.keyAt(type_ix);
+ snprintf(buffer, SIZE - 1, "\nMedia type '%s':\n", mediaType.c_str());
+ result.append(buffer);
+
+ for (const sp<MediaCodecInfo> &info : allMediaTypes.valueAt(type_ix)) {
+ sp<MediaCodecInfo::Capabilities> caps = info->getCapabilitiesFor(mediaType.c_str());
+ if (caps == NULL) {
+ snprintf(buffer, SIZE - 1, "warning: %s does not have capabilities for type %s\n",
+ info->getCodecName(), mediaType.c_str());
+ result.append(buffer);
+ continue;
+ }
+ snprintf(buffer, SIZE - 1, " %s \"%s\" supports\n",
+ codecType, info->getCodecName());
+ result.append(buffer);
+
+ auto printList = [&](const char *type, const Vector<AString> &values){
+ snprintf(buffer, SIZE - 1, " %s: [", type);
+ result.append(buffer);
+ for (size_t j = 0; j < values.size(); ++j) {
+ snprintf(buffer, SIZE - 1, "\n %s%s", values[j].c_str(),
+ j == values.size() - 1 ? " " : ",");
+ result.append(buffer);
+ }
+ result.append("]\n");
+ };
+
+ if (visitedCodecs.indexOfKey(info->getCodecName()) < 0) {
+ visitedCodecs.add(info->getCodecName(), true);
+ {
+ Vector<AString> aliases;
+ info->getAliases(&aliases);
+ // quote alias
+ for (AString &alias : aliases) {
+ alias.insert("\"", 1, 0);
+ alias.append('"');
+ }
+ printList("aliases", aliases);
+ }
+ {
+ uint32_t attrs = info->getAttributes();
+ Vector<AString> list;
+ list.add(AStringPrintf("encoder: %d",
+ !!(attrs & MediaCodecInfo::kFlagIsEncoder)));
+ list.add(AStringPrintf("vendor: %d",
+ !!(attrs & MediaCodecInfo::kFlagIsVendor)));
+ list.add(AStringPrintf("software-only: %d",
+ !!(attrs & MediaCodecInfo::kFlagIsSoftwareOnly)));
+ list.add(AStringPrintf("hw-accelerated: %d",
+ !!(attrs & MediaCodecInfo::kFlagIsHardwareAccelerated)));
+ printList(AStringPrintf("attributes: %#x", attrs).c_str(), list);
+ }
+
+ snprintf(buffer, SIZE - 1, " owner: \"%s\"\n", info->getOwnerName());
+ result.append(buffer);
+ snprintf(buffer, SIZE - 1, " rank: %u\n", info->getRank());
+ result.append(buffer);
+ } else {
+ result.append(" aliases, attributes, owner, rank: see above\n");
+ }
+
+ {
+ Vector<AString> list;
+ Vector<MediaCodecInfo::ProfileLevel> profileLevels;
+ caps->getSupportedProfileLevels(&profileLevels);
+ for (const MediaCodecInfo::ProfileLevel &pl : profileLevels) {
+ const char *niceProfile =
+ mediaType.equalsIgnoreCase(MIMETYPE_AUDIO_AAC)
+ ? asString_AACObject(pl.mProfile) :
+ mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_MPEG2)
+ ? asString_MPEG2Profile(pl.mProfile) :
+ mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_H263)
+ ? asString_H263Profile(pl.mProfile) :
+ mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_MPEG4)
+ ? asString_MPEG4Profile(pl.mProfile) :
+ mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_AVC)
+ ? asString_AVCProfile(pl.mProfile) :
+ mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_VP8)
+ ? asString_VP8Profile(pl.mProfile) :
+ mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_HEVC)
+ ? asString_HEVCProfile(pl.mProfile) :
+ mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_VP9)
+ ? asString_VP9Profile(pl.mProfile) :
+ mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_AV1)
+ ? asString_AV1Profile(pl.mProfile) : "??";
+ const char *niceLevel =
+ mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_MPEG2)
+ ? asString_MPEG2Level(pl.mLevel) :
+ mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_H263)
+ ? asString_H263Level(pl.mLevel) :
+ mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_MPEG4)
+ ? asString_MPEG4Level(pl.mLevel) :
+ mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_AVC)
+ ? asString_AVCLevel(pl.mLevel) :
+ mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_VP8)
+ ? asString_VP8Level(pl.mLevel) :
+ mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_HEVC)
+ ? asString_HEVCTierLevel(pl.mLevel) :
+ mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_VP9)
+ ? asString_VP9Level(pl.mLevel) :
+ mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_AV1)
+ ? asString_AV1Level(pl.mLevel) : "??";
+
+ list.add(AStringPrintf("% 5u/% 5u (%s/%s)",
+ pl.mProfile, pl.mLevel, niceProfile, niceLevel));
+ }
+ printList("profile/levels", list);
+ }
+
+ {
+ Vector<AString> list;
+ Vector<uint32_t> colors;
+ caps->getSupportedColorFormats(&colors);
+ for (uint32_t color : colors) {
+ list.add(AStringPrintf("%#x (%s)", color,
+ asString_ColorFormat((int32_t)color)));
+ }
+ printList("colors", list);
+ }
+
+ snprintf(buffer, SIZE - 1, " details: %s\n",
+ caps->getDetails()->debugString(6).c_str());
+ result.append(buffer);
+ }
+ }
+ result.append("\n");
+ ::write(fd, result.string(), result.size());
+}
+
+
// TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
/* static */ int MediaPlayerService::AudioOutput::mMinBufferCount = 4;
/* static */ bool MediaPlayerService::AudioOutput::mIsOnEmulator = false;
@@ -423,7 +590,7 @@
SortedVector< sp<MediaRecorderClient> > mediaRecorderClients;
if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
- snprintf(buffer, SIZE, "Permission Denial: "
+ snprintf(buffer, SIZE - 1, "Permission Denial: "
"can't dump MediaPlayerService from pid=%d, uid=%d\n",
IPCThreadState::self()->getCallingPid(),
IPCThreadState::self()->getCallingUid());
@@ -452,11 +619,11 @@
}
result.append(" Files opened and/or mapped:\n");
- snprintf(buffer, SIZE, "/proc/%d/maps", getpid());
+ snprintf(buffer, SIZE - 1, "/proc/%d/maps", getpid());
FILE *f = fopen(buffer, "r");
if (f) {
while (!feof(f)) {
- fgets(buffer, SIZE, f);
+ fgets(buffer, SIZE - 1, f);
if (strstr(buffer, " /storage/") ||
strstr(buffer, " /system/sounds/") ||
strstr(buffer, " /data/") ||
@@ -472,13 +639,13 @@
result.append("\n");
}
- snprintf(buffer, SIZE, "/proc/%d/fd", getpid());
+ snprintf(buffer, SIZE - 1, "/proc/%d/fd", getpid());
DIR *d = opendir(buffer);
if (d) {
struct dirent *ent;
while((ent = readdir(d)) != NULL) {
if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
- snprintf(buffer, SIZE, "/proc/%d/fd/%s", getpid(), ent->d_name);
+ snprintf(buffer, SIZE - 1, "/proc/%d/fd/%s", getpid(), ent->d_name);
struct stat s;
if (lstat(buffer, &s) == 0) {
if ((s.st_mode & S_IFMT) == S_IFLNK) {
@@ -543,6 +710,11 @@
}
}
write(fd, result.string(), result.size());
+
+ sp<IMediaCodecList> codecList = getCodecList();
+ dumpCodecDetails(fd, codecList, true /* decoders */);
+ dumpCodecDetails(fd, codecList, false /* !decoders */);
+
return NO_ERROR;
}