Android多媒体添加软解码

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

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值