1 软解码加载简介
1.1 编解码器信息与配置导入
android中decoder的管理是以plugin的模式,其控制是在OMXMaster内完成的。
OMXMaster是在omx被创建时就创建了
OMX::OMX()
: mMaster(new OMXMaster),
mNodeCounter(0) {
}
Plugin在OMXMaster构造的时候载入
OMXMaster::OMXMaster()
: mVendorLibHandle(NULL) {
addVendorPlugin(); //创建硬解码Plugin
addPlugin(new SoftOMXPlugin); //创建软解码的Plugin
}
void OMXMaster::addPlugin(OMXPluginBase *plugin) {
Mutex::Autolock autoLock(mLock);
mPlugins.push_back(plugin); //将这个plugin放进mPlugins
OMX_U32 index = 0;
char name[128];
OMX_ERRORTYPE err;
//enumerateComponents:遍历本组件支持的编解码格式
while ((err = plugin->enumerateComponents(name, sizeof(name), index++)) == OMX_ErrorNone) {
String8 name8(name);
if (mPluginByComponentName.indexOfKey(name8) >= 0) {
ALOGE("A component of name '%s' already exists, ignoring this one.",
name8.string());
continue;
}
//将Plugin的名字和plugin加入到mPluginByComponentName中
mPluginByComponentName.add(name8, plugin);
}
}
OMXMaster::addPlugin接口是用来添加解码组件到stagefright中的,组件名称保存在mPluginByComponentName中,(mPluginByComponentName的数据类型是KeyedVector<String8, OMXPluginBase *> 前面是组件名 后面是插件对象)
addPlugin会循环调用SoftOMXPlugin中的enumerateComponents获取需要添加组件支持的编解码名称,再在mPluginByComponentName中查找是否已经存在,如果存在就跳过,否则添加。
OMXMaster::addPlugin还可以添加库,主要用于添加硬编解码库,例如
void OMXMaster::addVendorPlugin() {
addPlugin("libstagefrighthw.so");
}
OMXMaster::addPlugin(const char *libname) 这个接口首先会从库中获取创建插件对象的接口,
createOMXPlugin = (CreateOMXPluginFunc)dlsym(mVendorLibHandle, "_ZN7android15createOMXPluginEv");
然后再创建一个插件类对象,再调用3步的OMXMaster::addPlugin (这个插件类与SoftOMXPlugin类似。)
具体载入的实现是在SoftOMXPlugin中:
static const struct {
const char *mName; //component name
//生成的plugin名字的最后名字,例如aac dec:libstagefright_soft_aacdec.so
const char *mLibNameSuffix;
const char *mRole; //职责
} kComponents[] = {
{ "OMX.google.aac.decoder", "aacdec", "audio_decoder.aac" },
{ "OMX.google.aac.encoder", "aacenc", "audio_encoder.aac" },
{ "OMX.google.h264.decoder", "h264dec", "video_decoder.avc" },
{ "OMX.google.h264.encoder", "h264enc", "video_encoder.avc" },
{ "OMX.google.h263.decoder", "mpeg4dec", "video_decoder.h263" },
{ "OMX.google.mpeg4.encoder", "mpeg4enc", "video_encoder.mpeg4" },
{ "OMX.google.mp3.decoder", "mp3dec", "audio_decoder.mp3" },
};
makeComponentInstance: 作用是根据输入的组件名拼接解码库名,软件解码库的命名格式如libstagefright_soft_xx.so,然后打开这个库获取里面创建组件对象的的接口createSoftOMXComponent(这个库中必须包含),再调用这个接口创建组件对象,通过makeComponentInstance最后一个参数OMX_COMPONENTTYPE **component返回给调用者。(这个参数会一层一层上传,最后会到OMXCoder:create接口中)
OMX_ERRORTYPE SoftOMXPlugin::makeComponentInstance(
const char *name,
const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData,
OMX_COMPONENTTYPE **component) {
for (size_t i = 0; i < kNumComponents; ++i) {
if (strcmp(name, kComponents[i].mName)) {
continue;
}
//libName名字必须是libstagefright_soft_"kComponents[i].mLibNameSuffix".so
AString libName = "libstagefright_soft_";
libName.append(kComponents[i].mLibNameSuffix);
libName.append(".so");
//通过dlopen调用
void *libHandle = dlopen(libName.c_str(), RTLD_NOW);
typedef SoftOMXComponent *(*CreateSoftOMXComponentFunc)(
const char *, const OMX_CALLBACKTYPE *, OMX_PTR, OMX_COMPONENTTYPE **);
//调用该plugin的createSoftOMXComponent函数,每个Plugin必须实现这个方法
CreateSoftOMXComponentFunc createSoftOMXComponent =
(CreateSoftOMXComponentFunc)dlsym(libHandle,
"_Z22createSoftOMXComponentPKcPK16OMX_CALLBACKTYPE"
"PvPP17OMX_COMPONENTTYPE");
sp<SoftOMXComponent> codec =
(*createSoftOMXComponent)(name, callbacks, appData, component);
return OMX_ErrorInsufficientResources;
}
return OMX_ErrorInvalidComponentName;
}
备注:
1、所有的软编解码都在SoftOMXPlugin中添加 (kComponents数组)
2、所有软编解码组件对象的新建都是通过SoftOMXPlugin:makeComponentInstance来完成,实际上是可以分开的,比如硬编解码就是独立的。之所以这么做是因为软编解码实现大体类似,可以抽象成一个插件类。
1.2 编解码插件对象的创建
OMXCodec::Create -> omx->allocateNode -> OMX::allocateNode -> mMaster->makeComponentInstance -> OMXMaster::makeComponentInstance
OMXPluginBase *plugin = mPluginByComponentName.valueAt(index);
OMX_ERRORTYPE err = plugin->makeComponentInstance(name, callbacks, appData, component);
1.3 OMXCodec对象创建时编解码器类型确定
OMXCodec::Create中会调用OMXCodec::findMatchingCodecs来确定编解码器类型,stagefright支持的编解码器保存在MediaCodecList对象中,这个是单例。MediaCodecList类在构造函数中解析配置文件/etc/media_codecs.xml,把编解码类型信息保存到mCodecInfos中。使用时通过接口MediaCodecList::findCodecByType和MediaCodecList::findCodecByName类查找。
1.4 MediaCodec 软硬解优先级
软解码器通常是以OMX.google开头的。硬解码器通常是以OMX.[hardware_vendor]开头的,比如TI的解码器是以OMX.TI开头的。当然还有一些不遵守这个命名规范的,不以OMX.开头的,那也会被认为是软解码器。
//frameworks/av/media/libstagefright/OMXCodec.cpp:
static bool IsSoftwareCodec(const char *componentName) {
if (!strncmp("OMX.google.", componentName, 11)) {
return true;
}
if (!strncmp("OMX.", componentName, 4)) {
return false;
}
return true;
}
通常系统中的编解码器会存在一个配置文件中/system/etc/media_codecc.xml,这个文件配置了系统支持的codec及其能力。
在这个配置文件里面,如果出现多个codec对应同样类型的媒体格式的时候,这些codec都会被保留起来。当系统使用的时候,将会选择第一个匹配的codec。除非是指明了要软解码还是硬解码,但是Android的framework层为上层提供服务的AwesomePlayer中在处理音频和视频的时候,对到底是选择软解还是硬解的参数没有设置。所以虽然底层是支持选择的,但是对于上层使用MediaPlayer的Java程序来说,还是只能接受默认的codec选取规则。
2 增加音频软解
这里已添加raw音频格式的编解码器为例。
首先,增加kComponents[],标示自己的软解码库。
diff --git a/media/libstagefright/omx/SoftOMXPlugin.cpp b/media/libstagefright/omx/SoftOMXPlugin.cpp
index 99ffe7d6..d0c73467 100644
--- a/media/libstagefright/omx/SoftOMXPlugin.cpp
+++ b/media/libstagefright/omx/SoftOMXPlugin.cpp
@@ -48,6 +48,7 @@ static const struct {
const char *mName;
const char *mLibNameSuffix;
const char *mRole;
} kComponents[] = {
{ "OMX.google.mp3.decoder", "mp3dec", "audio_decoder.mp3" },
{ "OMX.google.vorbis.decoder", "vorbisdec", "audio_decoder.vorbis" },
{ "OMX.google.vpx.decoder", "vpxdec", "video_decoder.vpx" },
+ { "OMX.google.raw.decoder", "rawdec", "audio_decoder.raw" },
};
设置raw的角色
//android/frameworks/av/media/libstagefright/media/libstagefright/ACodec.cpp
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index db2bedad..e6e0413b 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -768,6 +768,8 @@ status_t ACodec::setComponentRole(
bool isEncoder, const char *mime) {
struct MimeToRole {
const char *mime;
const char *decoderRole;
const char *encoderRole;
};
static const MimeToRole kMimeToRole[] = {
"video_decoder.h263", "video_encoder.h263" },
{ MEDIA_MIMETYPE_VIDEO_VPX,
"video_decoder.vpx", "video_encoder.vpx" },
+ { MEDIA_MIMETYPE_AUDIO_RAW,
+ "audio_decoder.raw", "audio_encoder.raw" },
};
static const size_t kNumMimeToRole =
@@ -873,6 +875,15 @@ status_t ACodec::configureCodec(
} else {
err = setupG711Codec(encoder, numChannels);
}
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
+ int32_t numChannels, sampleRate;
+ if (encoder
+ || !msg->findInt32("channel-count", &numChannels)
+ || !msg->findInt32("sample-rate", &sampleRate)) {
+ err = INVALID_OPERATION;
+ } else {
+ err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
+ }
}
stagefright支持的编解码器保存在MediaCodecList对象中
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 6b64e21c..a31be0ab 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -64,6 +64,9 @@ MediaCodecList::MediaCodecList()
: mInitCheck(NO_INIT) {
FILE *file = fopen("/etc/media_codecs.xml", "r");
if (file == NULL) {
ALOGW("unable to open media codecs configuration xml file.");
return;
}
parseXMLFile(file);
if (mInitCheck == OK) {
// These are currently still used by the video editing suite.
addMediaCodec(true /* encoder */, "AACEncoder", "audio/mp4a-latm");
+
+ addMediaCodec(
+ false /* encoder */, "OMX.google.raw.decoder", "audio/raw");
}
raw解码器配置
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index d9ad5259..e844e36e 100755
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -534,6 +534,14 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
setG711Format(numChannels);
+ } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_RAW, mMIME)) {
+ CHECK(!mIsEncoder);
+
+ int32_t numChannels, sampleRate;
+ CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
+ CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
+
+ setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
}
if (!strncasecmp(mMIME, "video/", 6)) {
@@ -1359,6 +1367,8 @@ void OMXCodec::setComponentRole(
"video_decoder.h263", "video_encoder.h263" },
{ MEDIA_MIMETYPE_VIDEO_VPX,
"video_decoder.vpx", "video_encoder.vpx" },
+ { MEDIA_MIMETYPE_AUDIO_RAW,
+ "audio_decoder.raw", "audio_encoder.raw" },
};
添加raw解码器库,添加Android.mk
diff --git a/media/libstagefright/codecs/raw/Android.mk b/media/libstagefright/codecs/raw/Android.mk
new file mode 100644
index 00000000..285c7478
--- /dev/null
+++ b/media/libstagefright/codecs/raw/Android.mk
@@ -0,0 +1,17 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ SoftRaw.cpp
+
+LOCAL_C_INCLUDES := \
+ frameworks/av/media/libstagefright/include \
+ frameworks/native/include/media/openmax
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright_omx libstagefright_foundation libutils
+
+LOCAL_MODULE := libstagefright_soft_rawdec
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
添加核心库
diff --git a/media/libstagefright/codecs/raw/SoftRaw.cpp b/media/libstagefright/codecs/raw/SoftRaw.cpp
new file mode 100644
index 00000000..19d6f13c
--- /dev/null
+++ b/media/libstagefright/codecs/raw/SoftRaw.cpp
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2012 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 "SoftRaw"
+#include <utils/Log.h>
+
+#include "SoftRaw.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/hexdump.h>
+
+namespace android {
+
+template<class T>
+static void InitOMXParams(T *params) {
+ params->nSize = sizeof(T);
+ params->nVersion.s.nVersionMajor = 1;
+ params->nVersion.s.nVersionMinor = 0;
+ params->nVersion.s.nRevision = 0;
+ params->nVersion.s.nStep = 0;
+}
+
+SoftRaw::SoftRaw(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component)
+ : SimpleSoftOMXComponent(name, callbacks, appData, component),
+ mSignalledError(false),
+ mChannelCount(2),
+ mSampleRate(44100) {
+ initPorts();
+ CHECK_EQ(initDecoder(), (status_t)OK);
+}
+
+SoftRaw::~SoftRaw() {
+}
+
+void SoftRaw::initPorts() {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+
+ def.nPortIndex = 0;
+ def.eDir = OMX_DirInput;
+ def.nBufferCountMin = kNumBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.nBufferSize = 32 * 1024;
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainAudio;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.nBufferAlignment = 1;
+
+ def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
+ def.format.audio.pNativeRender = NULL;
+ def.format.audio.bFlagErrorConcealment = OMX_FALSE;
+ def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
+
+ addPort(def);
+
+ def.nPortIndex = 1;
+ def.eDir = OMX_DirOutput;
+ def.nBufferCountMin = kNumBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.nBufferSize = 32 * 1024;
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainAudio;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.nBufferAlignment = 2;
+
+ def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
+ def.format.audio.pNativeRender = NULL;
+ def.format.audio.bFlagErrorConcealment = OMX_FALSE;
+ def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
+
+ addPort(def);
+}
+
+status_t SoftRaw::initDecoder() {
+ return OK;
+}
+
+OMX_ERRORTYPE SoftRaw::internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamAudioPcm:
+ {
+ OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
+ (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+
+ if (pcmParams->nPortIndex != 0 && pcmParams->nPortIndex != 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ pcmParams->eNumData = OMX_NumericalDataSigned;
+ pcmParams->eEndian = OMX_EndianBig;
+ pcmParams->bInterleaved = OMX_TRUE;
+ pcmParams->nBitPerSample = 16;
+ pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
+ pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
+ pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
+
+ pcmParams->nChannels = mChannelCount;
+ pcmParams->nSamplingRate = mSampleRate;
+
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SimpleSoftOMXComponent::internalGetParameter(index, params);
+ }
+}
+
+OMX_ERRORTYPE SoftRaw::internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamStandardComponentRole:
+ {
+ const OMX_PARAM_COMPONENTROLETYPE *roleParams =
+ (const OMX_PARAM_COMPONENTROLETYPE *)params;
+
+ if (strncmp((const char *)roleParams->cRole,
+ "audio_decoder.raw",
+ OMX_MAX_STRINGNAME_SIZE - 1)) {
+ return OMX_ErrorUndefined;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamAudioPcm:
+ {
+ const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
+ (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+
+ if (pcmParams->nPortIndex != 0) {
+ return OMX_ErrorUndefined;
+ }
+
+ mChannelCount = pcmParams->nChannels;
+ mSampleRate = pcmParams->nSamplingRate;
+
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SimpleSoftOMXComponent::internalSetParameter(index, params);
+ }
+}
+
+void SoftRaw::onQueueFilled(OMX_U32 portIndex) {
+ if (mSignalledError) {
+ return;
+ }
+
+ List<BufferInfo *> &inQueue = getPortQueue(0);
+ List<BufferInfo *> &outQueue = getPortQueue(1);
+
+ while (!inQueue.empty() && !outQueue.empty()) {
+ BufferInfo *inInfo = *inQueue.begin();
+ OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
+
+ BufferInfo *outInfo = *outQueue.begin();
+ OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
+
+ CHECK_GE(outHeader->nAllocLen, inHeader->nFilledLen);
+ memcpy(outHeader->pBuffer,
+ inHeader->pBuffer + inHeader->nOffset,
+ inHeader->nFilledLen);
+
+ outHeader->nFlags = inHeader->nFlags;
+ outHeader->nOffset = 0;
+ outHeader->nFilledLen = inHeader->nFilledLen;
+ outHeader->nTimeStamp = inHeader->nTimeStamp;
+
+ bool sawEOS = (inHeader->nFlags & OMX_BUFFERFLAG_EOS) != 0;
+
+ inQueue.erase(inQueue.begin());
+ inInfo->mOwnedByUs = false;
+ notifyEmptyBufferDone(inHeader);
+
+ outQueue.erase(outQueue.begin());
+ outInfo->mOwnedByUs = false;
+ notifyFillBufferDone(outHeader);
+
+ if (sawEOS) {
+ break;
+ }
+ }
+}
+
+} // namespace android
+
+android::SoftOMXComponent *createSoftOMXComponent(
+ const char *name, const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData, OMX_COMPONENTTYPE **component) {
+ return new android::SoftRaw(name, callbacks, appData, component);
+}
添加对应头文件
diff --git a/media/libstagefright/codecs/raw/SoftRaw.h b/media/libstagefright/codecs/raw/SoftRaw.h
new file mode 100644
index 00000000..015c4a32
--- /dev/null
+++ b/media/libstagefright/codecs/raw/SoftRaw.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2012 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 SOFT_RAW_H_
+
+#define SOFT_RAW_H_
+
+#include "SimpleSoftOMXComponent.h"
+
+struct tPVMP4AudioDecoderExternal;
+
+namespace android {
+
+struct SoftRaw : public SimpleSoftOMXComponent {
+ SoftRaw(const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component);
+
+protected:
+ virtual ~SoftRaw();
+
+ virtual OMX_ERRORTYPE internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params);
+
+ virtual OMX_ERRORTYPE internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params);
+
+ virtual void onQueueFilled(OMX_U32 portIndex);
+
+private:
+ enum {
+ kNumBuffers = 4
+ };
+
+ bool mSignalledError;
+
+ int32_t mChannelCount;
+ int32_t mSampleRate;
+
+ void initPorts();
+ status_t initDecoder();
+
+ DISALLOW_EVIL_CONSTRUCTORS(SoftRaw);
+};
+
+} // namespace android
+
+#endif // SOFT_RAW_H_
3 视频解码
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 924cf6d1b..f8fc8ed79 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -616,7 +616,7 @@ static void dumpCodecProfiles(const sp<IOMX>& omx, bool queryDecoders) {
MEDIA_MIMETYPE_AUDIO_AMR_NB, MEDIA_MIMETYPE_AUDIO_AMR_WB,
MEDIA_MIMETYPE_AUDIO_MPEG, MEDIA_MIMETYPE_AUDIO_G711_MLAW,
MEDIA_MIMETYPE_AUDIO_G711_ALAW, MEDIA_MIMETYPE_AUDIO_VORBIS,
- MEDIA_MIMETYPE_VIDEO_VPX
+ MEDIA_MIMETYPE_VIDEO_VP8, MEDIA_MIMETYPE_VIDEO_VP9
};
diff --git a/include/media/stagefright/MediaDefs.h b/include/media/stagefright/MediaDefs.h
index 81de6e4ae..85693d444 100644
--- a/include/media/stagefright/MediaDefs.h
+++ b/include/media/stagefright/MediaDefs.h
@@ -22,7 +22,8 @@ namespace android {
extern const char *MEDIA_MIMETYPE_IMAGE_JPEG;
-extern const char *MEDIA_MIMETYPE_VIDEO_VPX;
+extern const char *MEDIA_MIMETYPE_VIDEO_VP8;
+extern const char *MEDIA_MIMETYPE_VIDEO_VP9;
extern const char *MEDIA_MIMETYPE_VIDEO_AVC;
extern const char *MEDIA_MIMETYPE_VIDEO_MPEG4;
extern const char *MEDIA_MIMETYPE_VIDEO_H263;
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index bf650b498..2466a6b80 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -836,8 +836,10 @@ status_t ACodec::setComponentRole(
"video_decoder.mpeg4", "video_encoder.mpeg4" },
{ MEDIA_MIMETYPE_VIDEO_H263,
"video_decoder.h263", "video_encoder.h263" },
- { MEDIA_MIMETYPE_VIDEO_VPX,
- "video_decoder.vpx", "video_encoder.vpx" },
+ { MEDIA_MIMETYPE_VIDEO_VP8,
+ "video_decoder.vp8", "video_encoder.vp8" },
+ { MEDIA_MIMETYPE_VIDEO_VP9,
+ "video_decoder.vp9", "video_encoder.vp9" },
{ MEDIA_MIMETYPE_AUDIO_RAW,
"audio_decoder.raw", "audio_encoder.raw" },
{ MEDIA_MIMETYPE_AUDIO_FLAC,
@@ -1501,7 +1503,8 @@ static const struct VideoCodingMapEntry {
{ MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 },
{ MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 },
{ MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 },
- { MEDIA_MIMETYPE_VIDEO_VPX, OMX_VIDEO_CodingVPX },
+ { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 },
+ { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 },
};
diff --git a/media/libstagefright/MediaDefs.cpp b/media/libstagefright/MediaDefs.cpp
index 5d8029c79..b5d4e443f 100644
--- a/media/libstagefright/MediaDefs.cpp
+++ b/media/libstagefright/MediaDefs.cpp
@@ -20,7 +20,8 @@ namespace android {
const char *MEDIA_MIMETYPE_IMAGE_JPEG = "image/jpeg";
-const char *MEDIA_MIMETYPE_VIDEO_VPX = "video/x-vnd.on2.vp8";
+const char *MEDIA_MIMETYPE_VIDEO_VP8 = "video/x-vnd.on2.vp8";
+const char *MEDIA_MIMETYPE_VIDEO_VP9 = "video/x-vnd.on2.vp9";
const char *MEDIA_MIMETYPE_VIDEO_AVC = "video/avc";
const char *MEDIA_MIMETYPE_VIDEO_MPEG4 = "video/mp4v-es";
const char *MEDIA_MIMETYPE_VIDEO_H263 = "video/3gpp";
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 9d349a188..3de3c28a7 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1195,8 +1195,10 @@ status_t OMXCodec::setVideoOutputFormat(
compressionFormat = OMX_VIDEO_CodingMPEG4;
} else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
compressionFormat = OMX_VIDEO_CodingH263;
- } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_VPX, mime)) {
- compressionFormat = OMX_VIDEO_CodingVPX;
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_VP8, mime)) {
+ compressionFormat = OMX_VIDEO_CodingVP8;
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_VP9, mime)) {
+ compressionFormat = OMX_VIDEO_CodingVP9;
} else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG2, mime)) {
compressionFormat = OMX_VIDEO_CodingMPEG2;
} else {
@@ -1388,8 +1390,10 @@ void OMXCodec::setComponentRole(
"video_decoder.mpeg4", "video_encoder.mpeg4" },
{ MEDIA_MIMETYPE_VIDEO_H263,
"video_decoder.h263", "video_encoder.h263" },
- { MEDIA_MIMETYPE_VIDEO_VPX,
- "video_decoder.vpx", "video_encoder.vpx" },
+ { MEDIA_MIMETYPE_VIDEO_VP8,
+ "video_decoder.vp8", "video_encoder.vp8" },
+ { MEDIA_MIMETYPE_VIDEO_VP9,
+ "video_decoder.vp9", "video_encoder.vp9" },
{ MEDIA_MIMETYPE_AUDIO_RAW,
"audio_decoder.raw", "audio_encoder.raw" },
{ MEDIA_MIMETYPE_AUDIO_FLAC,
diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
index 43d026309..476e98696 100644
--- a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
+++ b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
@@ -31,16 +31,20 @@ namespace android {
SoftVPX::SoftVPX(
const char *name,
+ const char *componentRole,
+ OMX_VIDEO_CODINGTYPE codingType,
const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData,
OMX_COMPONENTTYPE **component)
: SoftVideoDecoderOMXComponent(
- name, "video_decoder.vpx", OMX_VIDEO_CodingVPX,
+ name, componentRole, codingType,
NULL /* profileLevels */, 0 /* numProfileLevels */,
320 /* width */, 240 /* height */, callbacks, appData, component),
+ mMode(codingType == OMX_VIDEO_CodingVP8 ? MODE_VP8 : MODE_VP9),
mCtx(NULL) {
initPorts(kNumBuffers, 768 * 1024 /* inputBufferSize */,
- kNumBuffers, MEDIA_MIMETYPE_VIDEO_VPX);
+ kNumBuffers,
+ codingType == OMX_VIDEO_CodingVP8 ? MEDIA_MIMETYPE_VIDEO_VP8 : MEDIA_MIMETYPE_VIDEO_VP9);
CHECK_EQ(initDecoder(), (status_t)OK);
}
@@ -71,7 +75,9 @@ status_t SoftVPX::initDecoder() {
memset(&cfg, 0, sizeof(vpx_codec_dec_cfg_t));
cfg.threads = GetCPUCoreCount();
if ((vpx_err = vpx_codec_dec_init(
- (vpx_codec_ctx_t *)mCtx, &vpx_codec_vp8_dx_algo, &cfg, 0))) {
+ (vpx_codec_ctx_t *)mCtx,
+ mMode == MODE_VP8 ? &vpx_codec_vp8_dx_algo : &vpx_codec_vp9_dx_algo,
+ &cfg, 0))) {
ALOGE("on2 decoder failed to initialize. (%d)", vpx_err);
return UNKNOWN_ERROR;
}
@@ -194,6 +200,15 @@ void SoftVPX::onQueueFilled(OMX_U32 portIndex) {
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
- return new android::SoftVPX(name, callbacks, appData, component);
+ if (!strcmp(name, "OMX.google.vp8.decoder")) {
+ return new android::SoftVPX(
+ name, "video_decoder.vp8", OMX_VIDEO_CodingVP8,
+ callbacks, appData, component);
+ } else if (!strcmp(name, "OMX.google.vp9.decoder")) {
+ return new android::SoftVPX(
+ name, "video_decoder.vp9", OMX_VIDEO_CodingVP9,
+ callbacks, appData, component);
+ } else {
+ CHECK(!"Unknown component");
+ }
}
diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.h b/media/libstagefright/codecs/on2/dec/SoftVPX.h
index 626307be7..cd5eb286c 100644
--- a/media/libstagefright/codecs/on2/dec/SoftVPX.h
+++ b/media/libstagefright/codecs/on2/dec/SoftVPX.h
@@ -24,6 +24,8 @@ namespace android {
struct SoftVPX : public SoftVideoDecoderOMXComponent {
SoftVPX(const char *name,
+ const char *componentRole,
+ OMX_VIDEO_CODINGTYPE codingType,
const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData,
OMX_COMPONENTTYPE **component);
@@ -38,6 +40,11 @@ private:
kNumBuffers = 4
};
+ enum {
+ MODE_VP8,
+ MODE_VP9
+ } mMode;
+
void *mCtx;
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
index e25637ae7..74d6df5d2 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
@@ -165,8 +165,8 @@ void SoftVPXEncoder::initPorts() {
outputPort.eDir = OMX_DirOutput;
outputPort.nBufferAlignment = kOutputBufferAlignment;
outputPort.format.video.cMIMEType =
- const_cast<char *>(MEDIA_MIMETYPE_VIDEO_VPX);
- outputPort.format.video.eCompressionFormat = OMX_VIDEO_CodingVPX;
+ const_cast<char *>(MEDIA_MIMETYPE_VIDEO_VP8);
+ outputPort.format.video.eCompressionFormat = OMX_VIDEO_CodingVP8;
outputPort.format.video.eColorFormat = OMX_COLOR_FormatUnused;
outputPort.format.video.pNativeWindow = NULL;
outputPort.nBufferSize = 256 * 1024; // arbitrary
@@ -315,7 +315,7 @@ OMX_ERRORTYPE SoftVPXEncoder::internalGetParameter(OMX_INDEXTYPE index,
formatParams->xFramerate = (1000000/mFrameDurationUs) << 16;
return OMX_ErrorNone;
} else if (formatParams->nPortIndex == kOutputPortIndex) {
- formatParams->eCompressionFormat = OMX_VIDEO_CodingVPX;
+ formatParams->eCompressionFormat = OMX_VIDEO_CodingVP8;
formatParams->eColorFormat = OMX_COLOR_FormatUnused;
formatParams->xFramerate = 0;
return OMX_ErrorNone;
@@ -513,7 +513,7 @@ OMX_ERRORTYPE SoftVPXEncoder::internalSetFormatParams(
return OMX_ErrorUnsupportedSetting;
}
} else if (format->nPortIndex == kOutputPortIndex) {
- if (format->eCompressionFormat == OMX_VIDEO_CodingVPX) {
+ if (format->eCompressionFormat == OMX_VIDEO_CodingVP8) {
return OMX_ErrorNone;
} else {
return OMX_ErrorUnsupportedSetting;
@@ -529,7 +529,7 @@ OMX_ERRORTYPE SoftVPXEncoder::internalSetRoleParams(
const char* roleText = (const char*)role->cRole;
const size_t roleTextMaxSize = OMX_MAX_STRINGNAME_SIZE - 1;
- if (strncmp(roleText, "video_encoder.vpx", roleTextMaxSize)) {
+ if (strncmp(roleText, "video_encoder.vp8", roleTextMaxSize)) {
ALOGE("Unsupported component role");
return OMX_ErrorBadParameter;
}
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
index 3bc05c0ab..a0a8ee699 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
@@ -175,7 +175,7 @@ class SoftVPXEncoder : public SimpleSoftOMXComponent {
const OMX_VIDEO_PARAM_PORTFORMATTYPE* format);
// Verifies the component role tried to be set to this OMX component is
- // strictly video_encoder.vpx
+ // strictly video_encoder.vp8
OMX_ERRORTYPE internalSetRoleParams(
const OMX_PARAM_COMPONENTROLETYPE* role);
diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp
index b3047493b..d260d0f8d 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.cpp
+++ b/media/libstagefright/matroska/MatroskaExtractor.cpp
@@ -870,7 +870,9 @@ void MatroskaExtractor::addTracks() {
continue;
}
} else if (!strcmp("V_VP8", codecID)) {
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VPX);
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP8);
+ } else if (!strcmp("V_VP9", codecID)) {
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP9);
} else {
ALOGW("%s is not supported.", codecID);
continue;
diff --git a/media/libstagefright/omx/SoftOMXPlugin.cpp b/media/libstagefright/omx/SoftOMXPlugin.cpp
index b3fe98e2d..d6cde7303 100644
--- a/media/libstagefright/omx/SoftOMXPlugin.cpp
+++ b/media/libstagefright/omx/SoftOMXPlugin.cpp
@@ -50,8 +50,9 @@ static const struct {
{ "OMX.google.mpeg4.encoder", "mpeg4enc", "video_encoder.mpeg4" },
{ "OMX.google.mp3.decoder", "mp3dec", "audio_decoder.mp3" },
{ "OMX.google.vorbis.decoder", "vorbisdec", "audio_decoder.vorbis" },
- { "OMX.google.vpx.decoder", "vpxdec", "video_decoder.vpx" },
- { "OMX.google.vpx.encoder", "vpxenc", "video_encoder.vpx" },
+ { "OMX.google.vp8.decoder", "vpxdec", "video_decoder.vp8" },
+ { "OMX.google.vp9.decoder", "vpxdec", "video_decoder.vp9" },
+ { "OMX.google.vp8.encoder", "vpxenc", "video_encoder.vp8" },
{ "OMX.google.raw.decoder", "rawdec", "audio_decoder.raw" },
{ "OMX.google.flac.encoder", "flacenc", "audio_encoder.flac" },
{ "OMX.google.gsm.decoder", "gsmdec", "audio_decoder.gsm" },
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index 6cca8da25..4bee8085d 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -449,7 +449,8 @@ static const char *GetMimeFromComponentRole(const char *componentRole) {
{ "video_decoder.avc", "video/avc" },
{ "video_decoder.mpeg4", "video/mp4v-es" },
{ "video_decoder.h263", "video/3gpp" },
- { "video_decoder.vpx", "video/x-vnd.on2.vp8" },
+ { "video_decoder.vp8", "video/x-vnd.on2.vp8" },
+ { "video_decoder.vp9", "video/x-vnd.on2.vp9" },
// we appear to use this as a synonym to amrnb.
{ "audio_decoder.amr", "audio/3gpp" },
4 android MediaPlayer修改参考
http://scm.osdn.net/gitroot/android-x86/frameworks-av.git
https://osdn.net/projects/android-x86/scm/git/frameworks-av
https://blog.csdn.net/gzzaigcnforever/article/details/26405739
https://blog.csdn.net/junluoyu000/article/details/108536505