diff options
Diffstat (limited to 'media/libavextensions')
-rw-r--r-- | media/libavextensions/Android.mk | 101 | ||||
-rw-r--r-- | media/libavextensions/common/AVExtensionsCommon.h | 67 | ||||
-rw-r--r-- | media/libavextensions/common/ExtensionsLoader.hpp | 97 | ||||
-rw-r--r-- | media/libavextensions/media/AVMediaExtensions.h | 96 | ||||
-rw-r--r-- | media/libavextensions/media/AVMediaUtils.cpp | 66 | ||||
-rw-r--r-- | media/libavextensions/mediaplayerservice/AVMediaServiceExtensions.h | 92 | ||||
-rw-r--r-- | media/libavextensions/mediaplayerservice/AVMediaServiceFactory.cpp | 72 | ||||
-rw-r--r-- | media/libavextensions/mediaplayerservice/AVMediaServiceUtils.cpp | 104 | ||||
-rw-r--r-- | media/libavextensions/mediaplayerservice/AVNuExtensions.h | 102 | ||||
-rw-r--r-- | media/libavextensions/mediaplayerservice/AVNuFactory.cpp | 89 | ||||
-rw-r--r-- | media/libavextensions/mediaplayerservice/AVNuUtils.cpp | 363 | ||||
-rw-r--r-- | media/libavextensions/stagefright/AVExtensions.h | 300 | ||||
-rw-r--r-- | media/libavextensions/stagefright/AVFactory.cpp | 141 | ||||
-rw-r--r-- | media/libavextensions/stagefright/AVUtils.cpp | 1139 | ||||
-rw-r--r-- | media/libavextensions/stagefright/ExtendedMediaDefs.cpp | 68 |
15 files changed, 2897 insertions, 0 deletions
diff --git a/media/libavextensions/Android.mk b/media/libavextensions/Android.mk new file mode 100644 index 0000000..3370116 --- /dev/null +++ b/media/libavextensions/Android.mk @@ -0,0 +1,101 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + stagefright/ExtendedMediaDefs.cpp \ + stagefright/AVUtils.cpp \ + stagefright/AVFactory.cpp \ + +LOCAL_C_INCLUDES:= \ + $(TOP)/frameworks/av/include/media/ \ + $(TOP)/frameworks/av/media/libavextensions \ + $(TOP)/frameworks/native/include/media/hardware \ + $(TOP)/frameworks/native/include/media/openmax \ + $(TOP)/external/flac/include \ + $(TOP)/$(call project-path-for,qcom-media)/mm-core/inc \ + $(TOP)/frameworks/av/media/libstagefright \ + +LOCAL_CFLAGS += -Wno-multichar -Werror + +LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/mm-audio + +ifeq ($(TARGET_ENABLE_QC_AV_ENHANCEMENTS),true) + LOCAL_CFLAGS += -DENABLE_AV_ENHANCEMENTS +endif + +ifeq ($(strip $(AUDIO_FEATURE_ENABLED_FLAC_OFFLOAD)),true) + LOCAL_CFLAGS += -DFLAC_OFFLOAD_ENABLED +endif + +LOCAL_MODULE:= libavextensions + +LOCAL_MODULE_TAGS := optional + +include $(BUILD_STATIC_LIBRARY) + +######################################################## + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + media/AVMediaUtils.cpp \ + +LOCAL_C_INCLUDES:= \ + $(TOP)/frameworks/av/include/media/ \ + $(TOP)/frameworks/av/media/libavextensions \ + $(TOP)/frameworks/native/include/media/hardware \ + $(TOP)/frameworks/native/include/media/openmax \ + $(TOP)/external/flac/include \ + $(TOP)/system/media/audio_utils/include \ + $(TOP)/$(call project-path-for,qcom-media)/mm-core/inc + +LOCAL_CFLAGS += -Wno-multichar -Werror + +ifeq ($(TARGET_ENABLE_QC_AV_ENHANCEMENTS),true) + LOCAL_CFLAGS += -DENABLE_AV_ENHANCEMENTS +endif + +LOCAL_MODULE:= libavmediaextentions + +LOCAL_MODULE_TAGS := optional + +include $(BUILD_STATIC_LIBRARY) + +######################################################## + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + mediaplayerservice/AVMediaServiceFactory.cpp \ + mediaplayerservice/AVMediaServiceUtils.cpp \ + mediaplayerservice/AVNuFactory.cpp \ + mediaplayerservice/AVNuUtils.cpp \ + +LOCAL_C_INCLUDES:= \ + $(TOP)/frameworks/av/include/media/ \ + $(TOP)/frameworks/av/media/libmediaplayerservice \ + $(TOP)/frameworks/av/media/libavextensions \ + $(TOP)/frameworks/av/media/libstagefright/include \ + $(TOP)/frameworks/av/media/libstagefright/rtsp \ + $(TOP)/frameworks/native/include/media/hardware \ + $(TOP)/frameworks/native/include/media/openmax \ + $(TOP)/external/flac/include \ + $(TOP)/system/media/audio_utils/include \ + $(TOP)/$(call project-path-for,qcom-media)/mm-core/inc + +LOCAL_CFLAGS += -Wno-multichar -Werror + +ifeq ($(TARGET_ENABLE_QC_AV_ENHANCEMENTS),true) + LOCAL_CFLAGS += -DENABLE_AV_ENHANCEMENTS +endif + +ifeq ($(TARGET_BOARD_PLATFORM),msm8974) + LOCAL_CFLAGS += -DTARGET_8974 +endif + +LOCAL_MODULE:= libavmediaserviceextensions + +LOCAL_MODULE_TAGS := optional + +include $(BUILD_STATIC_LIBRARY) + diff --git a/media/libavextensions/common/AVExtensionsCommon.h b/media/libavextensions/common/AVExtensionsCommon.h new file mode 100644 index 0000000..c39872e --- /dev/null +++ b/media/libavextensions/common/AVExtensionsCommon.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2013 - 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _AV_EXTENSIONS_COMMON_H_ +#define _AV_EXTENSIONS_COMMON_H_ + +namespace android { + +typedef void *(*createFunction_t)(void); + +template <typename T> +struct ExtensionsLoader { + + static T *createInstance(const char *createFunctionName); + +private: + static void loadLib(); + static createFunction_t loadCreateFunction(const char *createFunctionName); + static void *mLibHandle; +}; + +/* + * Boiler-plate to declare the class as a singleton (with a static getter) + * which can be loaded (dlopen'd) via ExtensionsLoader + */ +#define DECLARE_LOADABLE_SINGLETON(className) \ +protected: \ + className(); \ + virtual ~className(); \ + static className *sInst; \ +private: \ + className(const className&); \ + className &operator=(className &); \ +public: \ + static className *get() { \ + return sInst; \ + } \ + friend struct ExtensionsLoader<className>; + +} //namespace android + +#endif // _AV_EXTENSIONS_COMMON_H_ diff --git a/media/libavextensions/common/ExtensionsLoader.hpp b/media/libavextensions/common/ExtensionsLoader.hpp new file mode 100644 index 0000000..15728ed --- /dev/null +++ b/media/libavextensions/common/ExtensionsLoader.hpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2013 - 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include <dlfcn.h> +#include <common/AVExtensionsCommon.h> +#include <cutils/properties.h> + +namespace android { + +static const char * CUSTOMIZATION_LIB_NAME = "libavenhancements.so"; + +/* + * Create strongly-typed objects of type T + * If the customization library exists and does contain a "named" constructor, + * invoke and create an instance + * Else create the object of type T itself + * + * Contains a static instance to dlopen'd library, But may end up + * opening the library mutiple times. Following snip from dlopen man page is + * reassuring "...Only a single copy of an object file is brought into the + * address space, even if dlopen() is invoked multiple times in reference to + * the file, and even if different pathnames are used to reference the file.." + */ + +template <typename T> +T *ExtensionsLoader<T>::createInstance(const char *createFunctionName) { + (void)createFunctionName; + // create extended object if extensions-lib is available and + // AV_ENHANCEMENTS is enabled +#if ENABLE_AV_ENHANCEMENTS + bool enabled = property_get_bool("media.avenhancements.enabled", false); + if (enabled) { + createFunction_t createFunc = loadCreateFunction(createFunctionName); + if (createFunc) { + return reinterpret_cast<T *>((*createFunc)()); + } + } +#endif + // Else, create the default object + return new T; +} + +template <typename T> +void ExtensionsLoader<T>::loadLib() { + if (!mLibHandle) { + mLibHandle = ::dlopen(CUSTOMIZATION_LIB_NAME, RTLD_LAZY); + if (!mLibHandle) { + ALOGV("%s", dlerror()); + return; + } + ALOGV("Opened %s", CUSTOMIZATION_LIB_NAME); + } +} + +template <typename T> +createFunction_t ExtensionsLoader<T>::loadCreateFunction(const char *createFunctionName) { + loadLib(); + if (!mLibHandle) { + return NULL; + } + createFunction_t func = (createFunction_t)dlsym(mLibHandle, createFunctionName); + if (!func) { + ALOGW("symbol %s not found: %s",createFunctionName, dlerror()); + } + return func; +} + +//static +template <typename T> +void *ExtensionsLoader<T>::mLibHandle = NULL; + +} //namespace android diff --git a/media/libavextensions/media/AVMediaExtensions.h b/media/libavextensions/media/AVMediaExtensions.h new file mode 100644 index 0000000..9622253 --- /dev/null +++ b/media/libavextensions/media/AVMediaExtensions.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2013 - 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _AV_MEDIA_EXTENSIONS_H_ +#define _AV_MEDIA_EXTENSIONS_H_ + +#include <common/AVExtensionsCommon.h> +#include <hardware/audio.h> +#include <media/AudioTrack.h> +#include <audio_utils/format.h> + +namespace android { + +class MediaRecorder; +class Parcel; +/* + * Common delegate to the classes in libstagefright + */ +struct AVMediaUtils { + + virtual bool AudioTrackIsPcmOffloaded(const audio_format_t format) { + return audio_is_offload_pcm(format); + } + + virtual status_t AudioTrackGetPosition(AudioTrack* track, + uint32_t* position) { + uint32_t tempPos = (track->mState == AudioTrack::STATE_STOPPED || + track->mState == AudioTrack::STATE_FLUSHED) ? 0 : + track->updateAndGetPosition_l(); + *position = (tempPos / + (track->channelCount() * audio_bytes_per_sample(track->format()))); + return NO_ERROR; + } + + virtual status_t AudioTrackGetTimestamp(AudioTrack* track, + AudioTimestamp* timestamp) { + if (!AudioTrackIsPcmOffloaded(track->format())) { + return NO_INIT; + } + uint32_t tempPos = (track->mState == AudioTrack::STATE_STOPPED || + track->mState == AudioTrack::STATE_FLUSHED) ? 0 : + track->updateAndGetPosition_l(); + timestamp->mPosition = (tempPos / (track->channelCount() * + audio_bytes_per_sample(track->format()))); + clock_gettime(CLOCK_MONOTONIC, ×tamp->mTime); + return NO_ERROR; + } + + virtual size_t AudioTrackGetOffloadFrameCount(size_t frameCount) { + return frameCount * 2; + } + + virtual bool AudioTrackIsTrackOffloaded(audio_io_handle_t /*output*/) { + return false; + } + + virtual sp<MediaRecorder> createMediaRecorder(const String16& opPackageName); + virtual void writeCustomData( + Parcel * /* reply */, void * /* buffer_data */) {} + virtual void readCustomData( + const Parcel * /* reply */, void ** /*buffer_data */ ) {} + virtual void closeFileDescriptor(void * /* buffer_ptr */) {} + // ----- NO TRESSPASSING BEYOND THIS LINE ------ + DECLARE_LOADABLE_SINGLETON(AVMediaUtils); +}; + +} //namespace android + +#endif //_AV_MEDIA_EXTENSIONS_H_ + diff --git a/media/libavextensions/media/AVMediaUtils.cpp b/media/libavextensions/media/AVMediaUtils.cpp new file mode 100644 index 0000000..0f9e9eb --- /dev/null +++ b/media/libavextensions/media/AVMediaUtils.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2013 - 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "AVMediaUtils" +#include <utils/Log.h> + +#include <media/stagefright/foundation/ADebug.h> +#include <media/stagefright/foundation/AMessage.h> +#include <media/stagefright/foundation/ABuffer.h> +#include <media/stagefright/MediaDefs.h> +#include <media/stagefright/MediaCodecList.h> +#include <media/stagefright/MetaData.h> +#include <media/stagefright/ACodec.h> + +#include <media/AudioTrack.h> +#include <media/mediarecorder.h> + +#include "common/ExtensionsLoader.hpp" +#include "media/AVMediaExtensions.h" + +namespace android { + +// ----- NO TRESSPASSING BEYOND THIS LINE ------ +AVMediaUtils::AVMediaUtils() { +} + +AVMediaUtils::~AVMediaUtils() { +} + +sp<MediaRecorder> AVMediaUtils::createMediaRecorder(const String16& opPackageName) { + return new MediaRecorder(opPackageName); +} + +//static +AVMediaUtils *AVMediaUtils::sInst = + ExtensionsLoader<AVMediaUtils>::createInstance("createExtendedMediaUtils"); + +} //namespace android + diff --git a/media/libavextensions/mediaplayerservice/AVMediaServiceExtensions.h b/media/libavextensions/mediaplayerservice/AVMediaServiceExtensions.h new file mode 100644 index 0000000..f2c789e --- /dev/null +++ b/media/libavextensions/mediaplayerservice/AVMediaServiceExtensions.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2013 - 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _AV_MEDIA_SERVICE_EXTENSIONS_H_ +#define _AV_MEDIA_SERVICE_EXTENSIONS_H_ + +#include <common/AVExtensionsCommon.h> +#include <MediaPlayerFactory.h> + +#include <utils/List.h> +#include <utils/RefBase.h> +#include <utils/String16.h> + +#include <media/Metadata.h> + +namespace android { + +struct StagefrightRecorder; +struct ARTSPConnection; +struct ARTPConnection; +struct AString; +struct MyHandler; +struct ABuffer; + +/* + * Factory to create objects of base-classes in libmediaplayerservice + */ +struct AVMediaServiceFactory { + virtual StagefrightRecorder *createStagefrightRecorder(const String16 &); + + // RTSP extensions + virtual sp<ARTSPConnection> createARTSPConnection(bool uidValid, uid_t uid); + virtual sp<ARTPConnection> createARTPConnection(); + + // ----- NO TRESSPASSING BEYOND THIS LINE ------ + DECLARE_LOADABLE_SINGLETON(AVMediaServiceFactory); +}; + +/* + * Common delegate to the classes in libmediaplayerservice + */ +struct AVMediaServiceUtils { + virtual void getDashPlayerFactory(MediaPlayerFactory::IFactory *&, player_type ) {} + // RTSP IPV6 utils + virtual bool pokeAHole(sp<MyHandler> handler, int rtpSocket, int rtcpSocket, + const AString &transport, const AString &sessionHost); + virtual void makePortPair(int *rtpSocket, int *rtcpSocket, unsigned *rtpPort, + bool isIPV6); + virtual const char* parseURL(AString *host); + // RTSP customization utils + virtual bool parseTrackURL(AString url, AString val); + virtual void appendRange(AString *request); + virtual void setServerTimeoutUs(int64_t timeout); + virtual void appendMeta(media::Metadata *meta); + virtual bool checkNPTMapping(uint32_t *rtpInfoTime, int64_t *playTimeUs, + bool *nptValid, uint32_t rtpTime); + virtual void addH263AdvancedPacket(const sp<ABuffer> &buffer, + List<sp<ABuffer>> *packets, uint32_t rtpTime); + virtual bool parseNTPRange(const char *s, float *npt1, float *npt2); + + // ----- NO TRESSPASSING BEYOND THIS LINE ------ + DECLARE_LOADABLE_SINGLETON(AVMediaServiceUtils); +}; + +} + +#endif // _AV_EXTENSIONS__H_ diff --git a/media/libavextensions/mediaplayerservice/AVMediaServiceFactory.cpp b/media/libavextensions/mediaplayerservice/AVMediaServiceFactory.cpp new file mode 100644 index 0000000..10b66f5 --- /dev/null +++ b/media/libavextensions/mediaplayerservice/AVMediaServiceFactory.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2013 - 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "AVMediaServiceFactory" +#include <utils/Log.h> + +#include <media/stagefright/foundation/ADebug.h> +#include <media/stagefright/foundation/AMessage.h> +#include "ARTPConnection.h" +#include "ARTSPConnection.h" + +#include "MediaRecorderClient.h" +#include "MediaPlayerService.h" +#include "StagefrightRecorder.h" + +#include "common/ExtensionsLoader.hpp" +#include "mediaplayerservice/AVMediaServiceExtensions.h" + +namespace android { +StagefrightRecorder *AVMediaServiceFactory::createStagefrightRecorder( + const String16 &opPackageName) { + return new StagefrightRecorder(opPackageName); +} + +sp<ARTSPConnection> AVMediaServiceFactory::createARTSPConnection( + bool uidValid, uid_t uid) { + return new ARTSPConnection(uidValid, uid); +} + +sp<ARTPConnection> AVMediaServiceFactory::createARTPConnection() { + return new ARTPConnection(); +} + +// ----- NO TRESSPASSING BEYOND THIS LINE ------ +AVMediaServiceFactory::AVMediaServiceFactory() { +} + +AVMediaServiceFactory::~AVMediaServiceFactory() { +} + +//static +AVMediaServiceFactory *AVMediaServiceFactory::sInst = + ExtensionsLoader<AVMediaServiceFactory>::createInstance("createExtendedMediaServiceFactory"); + +} //namespace android + diff --git a/media/libavextensions/mediaplayerservice/AVMediaServiceUtils.cpp b/media/libavextensions/mediaplayerservice/AVMediaServiceUtils.cpp new file mode 100644 index 0000000..5306a39 --- /dev/null +++ b/media/libavextensions/mediaplayerservice/AVMediaServiceUtils.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2013 - 2016, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "AVMediaServiceUtils" +//#define LOG_NDEBUG 0 +#include <utils/Log.h> + +#include <media/stagefright/foundation/ADebug.h> +#include "ARTPConnection.h" +#include "ASessionDescription.h" +#include "MyHandler.h" + +#include "common/ExtensionsLoader.hpp" +#include "mediaplayerservice/AVMediaServiceExtensions.h" + +namespace android { + +bool AVMediaServiceUtils::pokeAHole(sp<MyHandler> handler, int rtpSocket, int rtcpSocket, + const AString &transport, const AString &/*sessionHost*/) { + if (handler == NULL) { + ALOGW("MyHandler is NULL"); + return false; + } + return handler->pokeAHole(rtpSocket, rtcpSocket, transport); +} + +void AVMediaServiceUtils::makePortPair(int *rtpSocket, int *rtcpSocket, unsigned *rtpPort, + bool /*isIPV6*/) { + return ARTPConnection::MakePortPair(rtpSocket, rtcpSocket, rtpPort); +} + +const char* AVMediaServiceUtils::parseURL(AString *host) { + return strchr(host->c_str(), ':'); +} + +bool AVMediaServiceUtils::parseTrackURL(AString /*url*/, AString /*val*/) { + return false; +} + +void AVMediaServiceUtils::appendRange(AString * /*request*/) { + return; +} + +void AVMediaServiceUtils::setServerTimeoutUs(int64_t /*timeout*/) { + return; +} + +void AVMediaServiceUtils::addH263AdvancedPacket(const sp<ABuffer> &/*buffer*/, + List<sp<ABuffer>> * /*packets*/, uint32_t /*rtpTime*/) { + return; +} + +void AVMediaServiceUtils::appendMeta(media::Metadata * /*meta*/) { + return; +} + +bool AVMediaServiceUtils::checkNPTMapping(uint32_t * /*rtpInfoTime*/, int64_t * /*playTimeUs*/, + bool * /*nptValid*/, uint32_t /*rtpTime*/) { + return false; +} + +bool AVMediaServiceUtils::parseNTPRange(const char *s, float *npt1, float *npt2) { + return ASessionDescription::parseNTPRange(s, npt1, npt2); +} + +// ----- NO TRESSPASSING BEYOND THIS LINE ------ +AVMediaServiceUtils::AVMediaServiceUtils() { +} + +AVMediaServiceUtils::~AVMediaServiceUtils() { +} + +//static +AVMediaServiceUtils *AVMediaServiceUtils::sInst = + ExtensionsLoader<AVMediaServiceUtils>::createInstance("createExtendedMediaServiceUtils"); + +} //namespace android + diff --git a/media/libavextensions/mediaplayerservice/AVNuExtensions.h b/media/libavextensions/mediaplayerservice/AVNuExtensions.h new file mode 100644 index 0000000..2fe56b8 --- /dev/null +++ b/media/libavextensions/mediaplayerservice/AVNuExtensions.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2013 - 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _AV_NU_EXTENSIONS_H_ +#define _AV_NU_EXTENSIONS_H_ + +#include <common/AVExtensionsCommon.h> + +namespace android { + +struct NuPlayer; +/* + * Factory to create extended NuPlayer objects + */ +struct AVNuFactory { + virtual sp<NuPlayer> createNuPlayer(pid_t pid); + + virtual sp<NuPlayer::DecoderBase> createPassThruDecoder( + const sp<AMessage> ¬ify, + const sp<NuPlayer::Source> &source, + const sp<NuPlayer::Renderer> &renderer); + + virtual sp<NuPlayer::DecoderBase> createDecoder( + const sp<AMessage> ¬ify, + const sp<NuPlayer::Source> &source, + pid_t pid, + const sp<NuPlayer::Renderer> &renderer); + + virtual sp<NuPlayer::Renderer> createRenderer( + const sp<MediaPlayerBase::AudioSink> &sink, + const sp<AMessage> ¬ify, + uint32_t flags); + + // ----- NO TRESSPASSING BEYOND THIS LINE ------ + DECLARE_LOADABLE_SINGLETON(AVNuFactory); +}; + +/* + * Common delegate to the classes in NuPlayer + */ +struct AVNuUtils { + + virtual sp<MetaData> createPCMMetaFromSource(const sp<MetaData> &); + virtual bool pcmOffloadException(const sp<MetaData> &); + virtual bool isRAWFormat(const sp<MetaData> &); + virtual bool isRAWFormat(const sp<AMessage> &); + virtual bool isVorbisFormat(const sp<MetaData> &); + virtual int updateAudioBitWidth(audio_format_t audioFormat, + const sp<AMessage> &); + virtual audio_format_t getKeyPCMFormat(const sp<MetaData> &); + virtual void setKeyPCMFormat(const sp<MetaData> &, audio_format_t audioFormat); + virtual audio_format_t getPCMFormat(const sp<AMessage> &); + virtual void setPCMFormat(const sp<AMessage> &, audio_format_t audioFormat); + virtual void setSourcePCMFormat(const sp<MetaData> &); + virtual void setDecodedPCMFormat(const sp<AMessage> &); + virtual status_t convertToSinkFormatIfNeeded(const sp<ABuffer> &, sp<ABuffer> &, + audio_format_t sinkFormat, bool isOffload); +#ifndef TARGET_8974 + virtual uint32_t getFlags(); + virtual bool canUseSetBuffers(const sp<MetaData> &Meta); +#endif + virtual void printFileName(int fd); + virtual void checkFormatChange(bool *formatChange, const sp<ABuffer> &accessUnit); +#ifdef TARGET_8974 + virtual void addFlagsInMeta(const sp<ABuffer> &buffer, int32_t flags, bool isAudio); + virtual uint32_t getFlags(); + virtual bool canUseSetBuffers(const sp<MetaData> &Meta); +#endif + virtual bool dropCorruptFrame(); + + // ----- NO TRESSPASSING BEYOND THIS LINE ------ + DECLARE_LOADABLE_SINGLETON(AVNuUtils); +}; + +} + +#endif // _AV_EXTENSIONS__H_ diff --git a/media/libavextensions/mediaplayerservice/AVNuFactory.cpp b/media/libavextensions/mediaplayerservice/AVNuFactory.cpp new file mode 100644 index 0000000..ff7c074 --- /dev/null +++ b/media/libavextensions/mediaplayerservice/AVNuFactory.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2013 - 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "AVNuFactory" +#include <utils/Log.h> + +#include <media/stagefright/foundation/ADebug.h> +#include <media/stagefright/foundation/AMessage.h> + +#include <nuplayer/NuPlayer.h> +#include <nuplayer/NuPlayerDecoderBase.h> +#include <nuplayer/NuPlayerDecoderPassThrough.h> +#include <nuplayer/NuPlayerDecoder.h> +#include <nuplayer/NuPlayerCCDecoder.h> +#include <gui/Surface.h> +#include <nuplayer/NuPlayerSource.h> +#include <nuplayer/NuPlayerRenderer.h> + +#include "common/ExtensionsLoader.hpp" +#include "mediaplayerservice/AVNuExtensions.h" + +namespace android { + +sp<NuPlayer> AVNuFactory::createNuPlayer(pid_t pid) { + return new NuPlayer(pid); +} + +sp<NuPlayer::DecoderBase> AVNuFactory::createPassThruDecoder( + const sp<AMessage> ¬ify, + const sp<NuPlayer::Source> &source, + const sp<NuPlayer::Renderer> &renderer) { + return new NuPlayer::DecoderPassThrough(notify, source, renderer); +} + +sp<NuPlayer::DecoderBase> AVNuFactory::createDecoder( + const sp<AMessage> ¬ify, + const sp<NuPlayer::Source> &source, + pid_t pid, + const sp<NuPlayer::Renderer> &renderer) { + return new NuPlayer::Decoder(notify, source, pid, renderer); +} + +sp<NuPlayer::Renderer> AVNuFactory::createRenderer( + const sp<MediaPlayerBase::AudioSink> &sink, + const sp<AMessage> ¬ify, + uint32_t flags) { + return new NuPlayer::Renderer(sink, notify, flags); +} + +// ----- NO TRESSPASSING BEYOND THIS LINE ------ +AVNuFactory::AVNuFactory() { +} + +AVNuFactory::~AVNuFactory() { +} + +//static +AVNuFactory *AVNuFactory::sInst = + ExtensionsLoader<AVNuFactory>::createInstance("createExtendedNuFactory"); + +} //namespace android + diff --git a/media/libavextensions/mediaplayerservice/AVNuUtils.cpp b/media/libavextensions/mediaplayerservice/AVNuUtils.cpp new file mode 100644 index 0000000..773a098 --- /dev/null +++ b/media/libavextensions/mediaplayerservice/AVNuUtils.cpp @@ -0,0 +1,363 @@ +/* + * Copyright (c) 2013 - 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "AVNuUtils" +#include <utils/Log.h> + +#include <media/stagefright/MetaData.h> +#include <media/stagefright/foundation/ABitReader.h> +#include <media/stagefright/foundation/ADebug.h> +#include <media/stagefright/foundation/ABuffer.h> +#include <media/stagefright/MediaDefs.h> +#include <media/stagefright/OMXCodec.h> +#include <cutils/properties.h> +#include <media/stagefright/MediaExtractor.h> +#include <media/MediaProfiles.h> +#include <media/stagefright/Utils.h> + +#include <audio_utils/format.h> + +#include <nuplayer/NuPlayer.h> +#include <nuplayer/NuPlayerDecoderBase.h> +#include <nuplayer/NuPlayerDecoderPassThrough.h> +#include <nuplayer/NuPlayerSource.h> +#include <nuplayer/NuPlayerRenderer.h> + +#include "common/ExtensionsLoader.hpp" +#include "mediaplayerservice/AVNuExtensions.h" + +namespace android { + +static bool is24bitPCMOffloadEnabled() { + return property_get_bool("audio.offload.pcm.24bit.enable", false); +} + +static bool is16bitPCMOffloadEnabled() { + return property_get_bool("audio.offload.pcm.16bit.enable", false); +} + +sp<MetaData> AVNuUtils::createPCMMetaFromSource(const sp<MetaData> &sMeta) { + sp<MetaData> tPCMMeta = new MetaData; + //hard code as RAW + tPCMMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); + + int32_t bits = 16; + sMeta->findInt32(kKeyBitsPerSample, &bits); + tPCMMeta->setInt32(kKeyBitsPerSample, bits > 24 ? 24 : bits); + + if (sMeta == NULL) { + ALOGW("no meta returning dummy meta"); + return tPCMMeta; + } + + int32_t srate = -1; + if (!sMeta->findInt32(kKeySampleRate, &srate)) { + ALOGV("No sample rate"); + } + tPCMMeta->setInt32(kKeySampleRate, srate); + + int32_t cmask = 0; + if (!sMeta->findInt32(kKeyChannelMask, &cmask) || (cmask == 0)) { + ALOGI("No channel mask, try channel count"); + } + int32_t channelCount = 0; + if (!sMeta->findInt32(kKeyChannelCount, &channelCount)) { + ALOGI("No channel count either"); + } else { + //if channel mask is not set till now, use channel count + //to retrieve channel count + if (!cmask) { + cmask = audio_channel_out_mask_from_count(channelCount); + } + } + tPCMMeta->setInt32(kKeyChannelCount, channelCount); + tPCMMeta->setInt32(kKeyChannelMask, cmask); + + int64_t duration = INT_MAX; + if (!sMeta->findInt64(kKeyDuration, &duration)) { + ALOGW("No duration in meta setting max duration"); + } + tPCMMeta->setInt64(kKeyDuration, duration); + + int32_t bitRate = -1; + if (!sMeta->findInt32(kKeyBitRate, &bitRate)) { + ALOGW("No bitrate info"); + } else { + tPCMMeta->setInt32(kKeyBitRate, bitRate); + } + + return tPCMMeta; +} + +bool AVNuUtils::pcmOffloadException(const sp<MetaData> &meta) { + bool decision = false; + const char *mime = {0}; + + if (meta == NULL) { + return true; + } + meta->findCString(kKeyMIMEType, &mime); + + if (!mime) { + ALOGV("%s: no audio mime present, ignoring pcm offload", __func__); + return true; + } + + if (!is24bitPCMOffloadEnabled() && !is16bitPCMOffloadEnabled()) { + return true; + } + + const char * const ExceptionTable[] = { + MEDIA_MIMETYPE_AUDIO_AMR_NB, + MEDIA_MIMETYPE_AUDIO_AMR_WB, + MEDIA_MIMETYPE_AUDIO_QCELP, + MEDIA_MIMETYPE_AUDIO_G711_ALAW, + MEDIA_MIMETYPE_AUDIO_G711_MLAW, + MEDIA_MIMETYPE_AUDIO_EVRC + }; + int countException = (sizeof(ExceptionTable) / sizeof(ExceptionTable[0])); + + for(int i = 0; i < countException; i++) { + if (!strcasecmp(mime, ExceptionTable[i])) { + decision = true; + break; + } + } + ALOGI("decision %d mime %s", decision, mime); + return decision; +#if 0 + //if PCM offload flag is disabled, do not offload any sessions + //using pcm offload + decision = true; + ALOGI("decision %d mime %s", decision, mime); + return decision; +#endif +} + +bool AVNuUtils::isRAWFormat(const sp<MetaData> &meta) { + const char *mime = {0}; + if (meta == NULL) { + return false; + } + CHECK(meta->findCString(kKeyMIMEType, &mime)); + if (!strncasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW, 9)) + return true; + else + return false; +} + +bool AVNuUtils::isRAWFormat(const sp<AMessage> &format) { + AString mime; + if (format == NULL) { + return false; + } + CHECK(format->findString("mime", &mime)); + if (!strncasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_RAW, 9)) + return true; + else + return false; + +} + +bool AVNuUtils::isVorbisFormat(const sp<MetaData> &) { + return false; +} + +int AVNuUtils::updateAudioBitWidth(audio_format_t audioFormat, + const sp<AMessage> &format){ + int bits = 16; + if (format.get() && + (audio_is_linear_pcm(audioFormat) || audio_is_offload_pcm(audioFormat))) { + bits = audio_bytes_per_sample(audioFormat) * 8; + format->setInt32("bits-per-sample", bits); + } + return bits; +} + +audio_format_t AVNuUtils::getKeyPCMFormat(const sp<MetaData> &meta) { + audio_format_t pcmFormat = AUDIO_FORMAT_INVALID; + if (meta.get()) + meta->findInt32('pfmt', (int32_t *)&pcmFormat); + return pcmFormat; +} + +void AVNuUtils::setKeyPCMFormat(const sp<MetaData> &meta, audio_format_t audioFormat) { + if (meta.get() && audio_is_linear_pcm(audioFormat)) + meta->setInt32('pfmt', audioFormat); +} + +audio_format_t AVNuUtils::getPCMFormat(const sp<AMessage> &format) { + audio_format_t pcmFormat = AUDIO_FORMAT_INVALID; + if (format.get()) + format->findInt32("pcm-format", (int32_t *)&pcmFormat); + return pcmFormat; +} + +void AVNuUtils::setPCMFormat(const sp<AMessage> &format, audio_format_t audioFormat) { + if (format.get() && + (audio_is_linear_pcm(audioFormat) || audio_is_offload_pcm(audioFormat))) + format->setInt32("pcm-format", audioFormat); +} + +void AVNuUtils::setSourcePCMFormat(const sp<MetaData> &audioMeta) { + if (!audioMeta.get() || !isRAWFormat(audioMeta)) + return; + + audio_format_t pcmFormat = getKeyPCMFormat(audioMeta); + if (pcmFormat == AUDIO_FORMAT_INVALID) { + int32_t bits = 16; + if (audioMeta->findInt32(kKeyBitsPerSample, &bits)) { + if (bits == 8) + pcmFormat = AUDIO_FORMAT_PCM_8_BIT; + else if (bits == 24) + pcmFormat = AUDIO_FORMAT_PCM_32_BIT; + else if (bits == 32) + pcmFormat = AUDIO_FORMAT_PCM_FLOAT; + else + pcmFormat = AUDIO_FORMAT_PCM_16_BIT; + setKeyPCMFormat(audioMeta, pcmFormat); + } + } +} + +void AVNuUtils::setDecodedPCMFormat(const sp<AMessage> &) { + +} + +status_t AVNuUtils::convertToSinkFormatIfNeeded( + const sp<ABuffer> &buffer, sp<ABuffer> &newBuffer, + audio_format_t sinkFormat, bool isOffload) { + + audio_format_t srcFormat = AUDIO_FORMAT_INVALID; + if (!isOffload + || !audio_is_offload_pcm(sinkFormat) + || !buffer->meta()->findInt32("pcm-format", (int32_t *)&srcFormat) + || ((int32_t)srcFormat < 0)) { + newBuffer = buffer; + return OK; + } + + size_t bps = audio_bytes_per_sample(srcFormat); + + if (bps <= 0) { + ALOGE("Invalid pcmformat %x given for conversion", srcFormat); + return INVALID_OPERATION; + } + + size_t frames = buffer->size() / bps; + + if (frames == 0) { + ALOGE("zero sized buffer, nothing to convert"); + return BAD_VALUE; + } + + ALOGV("convert %zu bytes (frames %zu) of format %x", + buffer->size(), frames, srcFormat); + + audio_format_t dstFormat; + switch (sinkFormat) { + case AUDIO_FORMAT_PCM_16_BIT_OFFLOAD: + dstFormat = AUDIO_FORMAT_PCM_16_BIT; + break; + case AUDIO_FORMAT_PCM_24_BIT_OFFLOAD: + if (srcFormat == AUDIO_FORMAT_PCM_32_BIT) + dstFormat = AUDIO_FORMAT_PCM_32_BIT; + else + dstFormat = AUDIO_FORMAT_PCM_24_BIT_OFFLOAD; + break; + case AUDIO_FORMAT_DEFAULT: + ALOGI("OffloadInfo not yet initialized, retry"); + return NO_INIT; + default: + ALOGE("Invalid offload format %x given for conversion", + sinkFormat); + return INVALID_OPERATION; + } + if (srcFormat == dstFormat) { + newBuffer = buffer; + return OK; + } + + size_t dstFrameSize = audio_bytes_per_sample(dstFormat); + size_t dstBytes = frames * dstFrameSize; + + newBuffer = new ABuffer(dstBytes); + + memcpy_by_audio_format(newBuffer->data(), dstFormat, + buffer->data(), srcFormat, frames); + + ALOGV("convert to format %x newBuffer->size() %zu", + dstFormat, newBuffer->size()); + + // copy over some meta info + int64_t timeUs = 0; + buffer->meta()->findInt64("timeUs", &timeUs); + newBuffer->meta()->setInt64("timeUs", timeUs); + + int32_t eos = false; + buffer->meta()->findInt32("eos", &eos); + newBuffer->meta()->setInt32("eos", eos); + + newBuffer->meta()->setInt32("pcm-format", (int32_t)dstFormat); + return OK; +} + +void AVNuUtils::printFileName(int) {} + +void AVNuUtils::checkFormatChange(bool * /*formatChange*/, + const sp<ABuffer> & /*accessUnit*/) { +} + +#ifdef TARGET_8974 +void AVNuUtils::addFlagsInMeta(const sp<ABuffer> & /*buffer*/, + int32_t /*flags*/, bool /*isAudio*/) { +} +#endif + +uint32_t AVNuUtils::getFlags() { + return 0; +} + +bool AVNuUtils::canUseSetBuffers(const sp<MetaData> &/*Meta*/) { + return false; +} + +bool AVNuUtils::dropCorruptFrame() { return false; } + +// ----- NO TRESSPASSING BEYOND THIS LINE ------ +AVNuUtils::AVNuUtils() {} + +AVNuUtils::~AVNuUtils() {} + +//static +AVNuUtils *AVNuUtils::sInst = + ExtensionsLoader<AVNuUtils>::createInstance("createExtendedNuUtils"); + +} //namespace android + diff --git a/media/libavextensions/stagefright/AVExtensions.h b/media/libavextensions/stagefright/AVExtensions.h new file mode 100644 index 0000000..c4c9aae --- /dev/null +++ b/media/libavextensions/stagefright/AVExtensions.h @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2013 - 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _AV_EXTENSIONS_H_ +#define _AV_EXTENSIONS_H_ + +#include <media/stagefright/DataSource.h> +#include <common/AVExtensionsCommon.h> +#include <system/audio.h> +#include <camera/ICamera.h> +#include <media/mediarecorder.h> +#include <media/IOMX.h> +#include <media/AudioParameter.h> +#include <media/stagefright/MetaData.h> + +namespace android { + +class MediaExtractor; +class MPEG4Writer; +struct ABuffer; +struct ACodec; +struct ALooper; +struct IMediaHTTPConnection; +struct MediaCodec; +struct MediaHTTP; +struct NuCachedSource2; +class CameraParameters; +class MediaBuffer; +struct AudioSource; +class CameraSource; +class CameraSourceTimeLapse; +class ICamera; +class ICameraRecordingProxy; +class String16; +class IGraphicBufferProducer; +struct Size; +class MPEG4Writer; + +/* + * Factory to create objects of base-classes in libstagefright + */ +struct AVFactory { + virtual sp<ACodec> createACodec(); + virtual MediaExtractor* createExtendedExtractor( + const sp<DataSource> &source, const char *mime, + const sp<AMessage> &meta, const uint32_t flags); + virtual sp<MediaExtractor> updateExtractor( + sp<MediaExtractor> ext, const sp<DataSource> &source, + const char *mime, const sp<AMessage> &meta, const uint32_t flags); + virtual sp<NuCachedSource2> createCachedSource( + const sp<DataSource> &source, + const char *cacheConfig = NULL, + bool disconnectAtHighwatermark = false); + virtual MediaHTTP* createMediaHTTP( + const sp<IMediaHTTPConnection> &conn); + + virtual AudioSource* createAudioSource( + audio_source_t inputSource, + const String16 &opPackageName, + uint32_t sampleRate, + uint32_t channels, + uint32_t outSampleRate = 0); + + virtual CameraSource *CreateCameraSourceFromCamera( + const sp<ICamera> &camera, + const sp<ICameraRecordingProxy> &proxy, + int32_t cameraId, + const String16& clientName, + uid_t clientUid, + Size videoSize, + int32_t frameRate, + const sp<IGraphicBufferProducer>& surface, + bool storeMetaDataInVideoBuffers = true); + + virtual CameraSourceTimeLapse *CreateCameraSourceTimeLapseFromCamera( + const sp<ICamera> &camera, + const sp<ICameraRecordingProxy> &proxy, + int32_t cameraId, + const String16& clientName, + uid_t clientUid, + Size videoSize, + int32_t videoFrameRate, + const sp<IGraphicBufferProducer>& surface, + int64_t timeBetweenFrameCaptureUs, + bool storeMetaDataInVideoBuffers = true); + + virtual MPEG4Writer *CreateMPEG4Writer(int fd); + // ----- NO TRESSPASSING BEYOND THIS LINE ------ + DECLARE_LOADABLE_SINGLETON(AVFactory); +}; + +/* + * Common delegate to the classes in libstagefright + */ +struct AVUtils { + + virtual status_t convertMetaDataToMessage( + const sp<MetaData> &meta, sp<AMessage> *format); + virtual DataSource::SnifferFunc getExtendedSniffer(); + virtual status_t mapMimeToAudioFormat( audio_format_t& format, const char* mime); + virtual status_t sendMetaDataToHal(const sp<MetaData>& meta, AudioParameter *param); + + virtual sp<MediaCodec> createCustomComponentByName(const sp<ALooper> &looper, + const char* mime, bool encoder, const sp<AMessage> &format); + virtual bool isEnhancedExtension(const char *extension); + + virtual bool is24bitPCMOffloadEnabled(); + virtual bool is16bitPCMOffloadEnabled(); + virtual int getAudioSampleBits(const sp<MetaData> &); + virtual int getAudioSampleBits(const sp<AMessage> &); + virtual void setPcmSampleBits(const sp<MetaData> &, int32_t /*bitWidth*/); + virtual void setPcmSampleBits(const sp<AMessage> &, int32_t /*bitWidth*/); + + virtual audio_format_t updateAudioFormat(audio_format_t audioFormat, + const sp<MetaData> &); + + virtual audio_format_t updateAudioFormat(audio_format_t audioFormat, + const sp<AMessage> &); + + virtual bool canOffloadAPE(const sp<MetaData> &meta); + + virtual int32_t getAudioMaxInputBufferSize(audio_format_t audioFormat, + const sp<AMessage> &); + + virtual bool mapAACProfileToAudioFormat(const sp<MetaData> &, + audio_format_t &, + uint64_t /*eAacProfile*/); + + virtual bool mapAACProfileToAudioFormat(const sp<AMessage> &, + audio_format_t &, + uint64_t /*eAacProfile*/); + + virtual void extractCustomCameraKeys( + const CameraParameters& /*params*/, sp<MetaData> &/*meta*/); + virtual void printFileName(int /*fd*/) {} + virtual void addDecodingTimesFromBatch(MediaBuffer * /*buf*/, + List<int64_t> &/*decodeTimeQueue*/) {} + + virtual bool useQCHWEncoder(const sp<AMessage> &, AString &) { return false; } + + virtual bool canDeferRelease(const sp<MetaData> &meta) { + int32_t deferRelease = false; + return meta->findInt32(kKeyCanDeferRelease, &deferRelease) && deferRelease; + } + + virtual void setDeferRelease(sp<MetaData> &meta) { + meta->setInt32(kKeyCanDeferRelease, true); + } + + struct HEVCMuxer { + + virtual bool reassembleHEVCCSD(const AString &mime, sp<ABuffer> csd0, sp<MetaData> &meta); + + virtual void writeHEVCFtypBox(MPEG4Writer *writer); + + virtual status_t makeHEVCCodecSpecificData(const uint8_t *data, + size_t size, void** codecSpecificData, + size_t *codecSpecificDataSize); + + virtual const char *getFourCCForMime(const char *mime); + + virtual void writeHvccBox(MPEG4Writer *writer, + void* codecSpecificData, size_t codecSpecificDataSize, + bool useNalLengthFour); + + virtual bool isVideoHEVC(const char* mime); + + virtual void getHEVCCodecSpecificDataFromInputFormatIfPossible( + sp<MetaData> meta, void **codecSpecificData, + size_t *codecSpecificDataSize, bool *gotAllCodecSpecificData); + + protected: + HEVCMuxer() {}; + virtual ~HEVCMuxer() {}; + friend struct AVUtils; + + private: + struct HEVCParamSet { + HEVCParamSet(uint16_t length, const uint8_t *data) + : mLength(length), mData(data) {} + + uint16_t mLength; + const uint8_t *mData; + }; + + status_t extractNALRBSPData(const uint8_t *data, size_t size, + uint8_t **header, bool *alreadyFilled); + + status_t parserProfileTierLevel(const uint8_t *data, size_t size, + uint8_t **header, bool *alreadyFilled); + + const uint8_t *parseHEVCParamSet(const uint8_t *data, size_t length, + List<HEVCParamSet> ¶mSetList, size_t *paramSetLen); + + size_t parseHEVCCodecSpecificData(const uint8_t *data, size_t size, + List<HEVCParamSet> &vidParamSet, List<HEVCParamSet> &seqParamSet, + List<HEVCParamSet> &picParamSet ); + }; + + + virtual inline HEVCMuxer& HEVCMuxerUtils() { + return mHEVCMuxer; + } + + virtual bool isAudioMuxFormatSupported(const char *mime); + virtual void cacheCaptureBuffers(sp<ICamera> camera, video_encoder encoder); + virtual const char *getCustomCodecsLocation(); + + virtual void setIntraPeriod( + int nPFrames, int nBFrames, const sp<IOMX> OMXhandle, + IOMX::node_id nodeID); + + /* + * This class is a placeholder for the set of methods used + * to enable HFR (High Frame Rate) Recording + * + * HFR is a slow-motion recording feature where framerate + * is increased at capture, but file is composed to play + * back at normal rate, giving a net result of slow-motion. + * If HFR factor = N + * framerate (at capture and encoder) = N * actual value + * bitrate = N * actual value + * (as the encoder still gets actual timestamps) + * timeStamps (at composition) = actual value + * timeScale (at composition) = actual value / N + * (when parser re-generates timestamps, they will be + * up-scaled by factor N, which results in slow-motion) + * + * HSR is a high-framerate recording variant where timestamps + * are not meddled with, yielding a video mux'ed at captured + * fps + */ + struct HFR { + // set kKeyHFR when 'video-hfr' paramater is enabled + // or set kKeyHSR when 'video-hsr' paramater is enabled + virtual void setHFRIfEnabled( + const CameraParameters& params, sp<MetaData> &meta); + + // recalculate file-duration when HFR is enabled + virtual status_t initializeHFR( + const sp<MetaData> &meta, sp<AMessage> &format, + int64_t &maxFileDurationUs, video_encoder videoEncoder); + + virtual void setHFRRatio( + sp<MetaData> &meta, const int32_t hfrRatio); + + virtual int32_t getHFRRatio( + const sp<MetaData> &meta); + + protected: + HFR() {}; + virtual ~HFR() {}; + friend struct AVUtils; + + private: + // Query supported capabilities from target-specific profiles + virtual int32_t getHFRCapabilities( + video_encoder codec, + int& maxHFRWidth, int& maxHFRHeight, int& maxHFRFps, + int& maxBitrate); + }; + virtual inline HFR& HFRUtils() { + return mHFR; + } + +private: + HEVCMuxer mHEVCMuxer; + HFR mHFR; + // ----- NO TRESSPASSING BEYOND THIS LINE ------ + DECLARE_LOADABLE_SINGLETON(AVUtils); + +}; +} + +#endif // _AV_EXTENSIONS__H_ diff --git a/media/libavextensions/stagefright/AVFactory.cpp b/media/libavextensions/stagefright/AVFactory.cpp new file mode 100644 index 0000000..7420d12 --- /dev/null +++ b/media/libavextensions/stagefright/AVFactory.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2013 - 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "AVFactory" +#include <utils/Log.h> + +#include <media/stagefright/foundation/ADebug.h> +#include <media/stagefright/foundation/AMessage.h> +#include <media/stagefright/foundation/ABuffer.h> +#include <media/stagefright/MediaDefs.h> +#include <media/stagefright/MediaCodecList.h> +#include <media/stagefright/MetaData.h> +#include <media/stagefright/ACodec.h> +#include <media/stagefright/DataSource.h> +#include <media/stagefright/MediaDefs.h> +#include <media/stagefright/MediaExtractor.h> +#include <media/stagefright/MediaHTTP.h> +#include <media/stagefright/AudioSource.h> +#include <media/stagefright/CameraSource.h> +#include <media/stagefright/CameraSourceTimeLapse.h> +#include <camera/CameraParameters.h> +#include <media/stagefright/MPEG4Writer.h> + +#include "common/ExtensionsLoader.hpp" +#include "stagefright/AVExtensions.h" +#include "include/NuCachedSource2.h" + +namespace android { + +sp<ACodec> AVFactory::createACodec() { + return new ACodec; +} + +MediaExtractor* AVFactory::createExtendedExtractor( + const sp<DataSource> &, const char *, const sp<AMessage> &, + const uint32_t) { + return NULL; +} + +sp<MediaExtractor> AVFactory::updateExtractor( + sp<MediaExtractor> ext, const sp<DataSource> &, + const char *, const sp<AMessage> &, const uint32_t) { + return ext; +} + +sp<NuCachedSource2> AVFactory::createCachedSource( + const sp<DataSource> &source, + const char *cacheConfig, + bool disconnectAtHighwatermark) { + return NuCachedSource2::Create(source, cacheConfig, disconnectAtHighwatermark); +} + +MediaHTTP* AVFactory::createMediaHTTP( + const sp<IMediaHTTPConnection> &conn) { + return new MediaHTTP(conn); +} + +AudioSource* AVFactory::createAudioSource( + audio_source_t inputSource, + const String16 &opPackageName, + uint32_t sampleRate, + uint32_t channels, + uint32_t outSampleRate) { + return new AudioSource(inputSource, opPackageName, sampleRate, + channels, outSampleRate); +} + +CameraSource* AVFactory::CreateCameraSourceFromCamera( + const sp<ICamera> &camera, + const sp<ICameraRecordingProxy> &proxy, + int32_t cameraId, + const String16& clientName, + uid_t clientUid, + Size videoSize, + int32_t frameRate, + const sp<IGraphicBufferProducer>& surface, + bool storeMetaDataInVideoBuffers) { + return CameraSource::CreateFromCamera(camera, proxy, cameraId, + clientName, clientUid, videoSize, frameRate, surface, + storeMetaDataInVideoBuffers); +} + +CameraSourceTimeLapse* AVFactory::CreateCameraSourceTimeLapseFromCamera( + const sp<ICamera> &camera, + const sp<ICameraRecordingProxy> &proxy, + int32_t cameraId, + const String16& clientName, + uid_t clientUid, + Size videoSize, + int32_t videoFrameRate, + const sp<IGraphicBufferProducer>& surface, + int64_t timeBetweenFrameCaptureUs, + bool storeMetaDataInVideoBuffers) { + return CameraSourceTimeLapse::CreateFromCamera(camera, proxy, cameraId, + clientName, clientUid, videoSize, videoFrameRate, surface, + timeBetweenFrameCaptureUs, storeMetaDataInVideoBuffers); +} + +MPEG4Writer* AVFactory::CreateMPEG4Writer(int fd) { + return new MPEG4Writer(fd); +} + +// ----- NO TRESSPASSING BEYOND THIS LINE ------ +AVFactory::AVFactory() { +} + +AVFactory::~AVFactory() { +} + +//static +AVFactory *AVFactory::sInst = + ExtensionsLoader<AVFactory>::createInstance("createExtendedFactory"); + +} //namespace android + diff --git a/media/libavextensions/stagefright/AVUtils.cpp b/media/libavextensions/stagefright/AVUtils.cpp new file mode 100644 index 0000000..a9cd4b2 --- /dev/null +++ b/media/libavextensions/stagefright/AVUtils.cpp @@ -0,0 +1,1139 @@ +/* + * Copyright (c) 2013 - 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "AVUtils" +#include <utils/Log.h> +#include <utils/StrongPointer.h> + +#include <media/stagefright/foundation/ADebug.h> +#include <media/stagefright/foundation/AMessage.h> +#include <media/stagefright/foundation/ABuffer.h> +#include <media/stagefright/MediaDefs.h> +#include <media/stagefright/MediaCodecList.h> +#include <media/stagefright/MetaData.h> +#include <media/stagefright/ACodec.h> +#include <media/stagefright/MediaCodec.h> +#include <media/stagefright/MPEG4Writer.h> +#include <media/stagefright/Utils.h> +#include <media/MediaProfiles.h> + +#if defined(QCOM_HARDWARE) || defined(FLAC_OFFLOAD_ENABLED) +#include "QCMediaDefs.h" +#include "QCMetaData.h" +#ifdef FLAC_OFFLOAD_ENABLED +#include "audio_defs.h" +#endif +#endif + +#include <binder/IPCThreadState.h> +#include <camera/CameraParameters.h> + +#include "common/ExtensionsLoader.hpp" +#include "stagefright/AVExtensions.h" + +namespace android { + +static const uint8_t kHEVCNalUnitTypeVidParamSet = 0x20; +static const uint8_t kHEVCNalUnitTypeSeqParamSet = 0x21; +static const uint8_t kHEVCNalUnitTypePicParamSet = 0x22; + +enum MetaKeyType{ + INT32, INT64, STRING, DATA, CSD +}; + +struct MetaKeyEntry{ + int MetaKey; + const char* MsgKey; + MetaKeyType KeyType; +}; + +static const MetaKeyEntry MetaKeyTable[] { +#ifdef QCOM_HARDWARE + {kKeyAacCodecSpecificData , "aac-codec-specific-data", CSD}, + {kKeyDivXVersion , "divx-version" , INT32}, // int32_t + {kKeyDivXDrm , "divx-drm" , DATA}, // void * + {kKeyWMAEncodeOpt , "wma-encode-opt" , INT32}, // int32_t + {kKeyWMABlockAlign , "wma-block-align" , INT32}, // int32_t + {kKeyWMAAdvEncOpt1 , "wma-adv-enc-opt1" , INT32}, // int16_t + {kKeyWMAAdvEncOpt2 , "wma-adv-enc-opt2" , INT32}, // int32_t + {kKeyWMAFormatTag , "wma-format-tag" , INT32}, // int32_t + {kKeyWMABitspersample , "wma-bits-per-sample" , INT32}, // int32_t + {kKeyWMAVirPktSize , "wma-vir-pkt-size" , INT32}, // int32_t + {kKeyWMAChannelMask , "wma-channel-mask" , INT32}, // int32_t + {kKeyFileFormat , "file-format" , STRING}, // cstring + + {kkeyAacFormatAdif , "aac-format-adif" , INT32}, // bool (int32_t) + {kkeyAacFormatLtp , "aac-format-ltp" , INT32}, + + //DTS subtype + {kKeyDTSSubtype , "dts-subtype" , INT32}, //int32_t + + //Extractor sets this + {kKeyUseArbitraryMode , "use-arbitrary-mode" , INT32}, //bool (int32_t) + {kKeySmoothStreaming , "smooth-streaming" , INT32}, //bool (int32_t) + {kKeyHFR , "hfr" , INT32}, // int32_t +#endif +#ifdef FLAC_OFFLOAD_ENABLED + {kKeyMinBlkSize , "min-block-size" , INT32}, + {kKeyMaxBlkSize , "max-block-size" , INT32}, + {kKeyMinFrmSize , "min-frame-size" , INT32}, + {kKeyMaxFrmSize , "max-frame-size" , INT32}, +#endif + + + {kKeyBitRate , "bitrate" , INT32}, + {kKeySampleRate , "sample-rate" , INT32}, + {kKeyChannelCount , "channel-count" , INT32}, + {kKeyRawCodecSpecificData , "raw-codec-specific-data", CSD}, + + {kKeyBitsPerSample , "bits-per-sample" , INT32}, + {kKeyCodecId , "codec-id" , INT32}, + {kKeySampleFormat , "sample-format" , INT32}, + {kKeyBlockAlign , "block-align" , INT32}, + {kKeyCodedSampleBits , "coded-sample-bits" , INT32}, + {kKeyAACAOT , "aac-profile" , INT32}, + {kKeyRVVersion , "rv-version" , INT32}, + {kKeyWMAVersion , "wma-version" , INT32}, // int32_t + {kKeyWMVVersion , "wmv-version" , INT32}, +}; + +status_t AVUtils::convertMetaDataToMessage( + const sp<MetaData> &meta, sp<AMessage> *format) { + const char * str_val; + int32_t int32_val; + int64_t int64_val; + uint32_t data_type; + const void * data; + size_t size; + static const size_t numMetaKeys = + sizeof(MetaKeyTable) / sizeof(MetaKeyTable[0]); + size_t i; + for (i = 0; i < numMetaKeys; ++i) { + if (MetaKeyTable[i].KeyType == INT32 && + meta->findInt32(MetaKeyTable[i].MetaKey, &int32_val)) { + ALOGV("found metakey %s of type int32", MetaKeyTable[i].MsgKey); + format->get()->setInt32(MetaKeyTable[i].MsgKey, int32_val); + } else if (MetaKeyTable[i].KeyType == INT64 && + meta->findInt64(MetaKeyTable[i].MetaKey, &int64_val)) { + ALOGV("found metakey %s of type int64", MetaKeyTable[i].MsgKey); + format->get()->setInt64(MetaKeyTable[i].MsgKey, int64_val); + } else if (MetaKeyTable[i].KeyType == STRING && + meta->findCString(MetaKeyTable[i].MetaKey, &str_val)) { + ALOGV("found metakey %s of type string", MetaKeyTable[i].MsgKey); + format->get()->setString(MetaKeyTable[i].MsgKey, str_val); + } else if ( (MetaKeyTable[i].KeyType == DATA || + MetaKeyTable[i].KeyType == CSD) && + meta->findData(MetaKeyTable[i].MetaKey, &data_type, &data, &size)) { + ALOGV("found metakey %s of type data", MetaKeyTable[i].MsgKey); + if (MetaKeyTable[i].KeyType == CSD) { + const char *mime; + CHECK(meta->findCString(kKeyMIMEType, &mime)); + if (strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { + sp<ABuffer> buffer = new ABuffer(size); + memcpy(buffer->data(), data, size); + buffer->meta()->setInt32("csd", true); + buffer->meta()->setInt64("timeUs", 0); + format->get()->setBuffer("csd-0", buffer); + } else { + const uint8_t *ptr = (const uint8_t *)data; + CHECK(size >= 8); + int seqLength = 0, picLength = 0; + for (size_t i = 4; i < (size - 4); i++) + { + if ((*(ptr + i) == 0) && (*(ptr + i + 1) == 0) && + (*(ptr + i + 2) == 0) && (*(ptr + i + 3) == 1)) + seqLength = i; + } + sp<ABuffer> buffer = new ABuffer(seqLength); + memcpy(buffer->data(), data, seqLength); + buffer->meta()->setInt32("csd", true); + buffer->meta()->setInt64("timeUs", 0); + format->get()->setBuffer("csd-0", buffer); + picLength=size-seqLength; + sp<ABuffer> buffer1 = new ABuffer(picLength); + memcpy(buffer1->data(), (const uint8_t *)data + seqLength, picLength); + buffer1->meta()->setInt32("csd", true); + buffer1->meta()->setInt64("timeUs", 0); + format->get()->setBuffer("csd-1", buffer1); + } + } else { + sp<ABuffer> buffer = new ABuffer(size); + memcpy(buffer->data(), data, size); + format->get()->setBuffer(MetaKeyTable[i].MsgKey, buffer); + } + } + } + return OK; +} + +struct mime_conv_t { + const char* mime; + audio_format_t format; +}; + +static const struct mime_conv_t mimeLookup[] = { + { MEDIA_MIMETYPE_AUDIO_MPEG, AUDIO_FORMAT_MP3 }, + { MEDIA_MIMETYPE_AUDIO_RAW, AUDIO_FORMAT_PCM_16_BIT }, + { MEDIA_MIMETYPE_AUDIO_AMR_NB, AUDIO_FORMAT_AMR_NB }, + { MEDIA_MIMETYPE_AUDIO_AMR_WB, AUDIO_FORMAT_AMR_WB }, + { MEDIA_MIMETYPE_AUDIO_AAC, AUDIO_FORMAT_AAC }, + { MEDIA_MIMETYPE_AUDIO_VORBIS, AUDIO_FORMAT_VORBIS }, + { MEDIA_MIMETYPE_AUDIO_OPUS, AUDIO_FORMAT_OPUS}, +#ifdef QCOM_HARDWARE + { MEDIA_MIMETYPE_AUDIO_AC3, AUDIO_FORMAT_AC3 }, + { MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS, AUDIO_FORMAT_AMR_WB_PLUS }, + { MEDIA_MIMETYPE_AUDIO_DTS, AUDIO_FORMAT_DTS }, + { MEDIA_MIMETYPE_AUDIO_EAC3, AUDIO_FORMAT_E_AC3 }, + { MEDIA_MIMETYPE_AUDIO_EVRC, AUDIO_FORMAT_EVRC }, + { MEDIA_MIMETYPE_AUDIO_QCELP, AUDIO_FORMAT_QCELP }, + { MEDIA_MIMETYPE_AUDIO_WMA, AUDIO_FORMAT_WMA }, + { MEDIA_MIMETYPE_AUDIO_FLAC, AUDIO_FORMAT_FLAC }, + { MEDIA_MIMETYPE_CONTAINER_QTIFLAC, AUDIO_FORMAT_FLAC }, +#ifdef DOLBY_UDC + { MEDIA_MIMETYPE_AUDIO_EAC3_JOC, AUDIO_FORMAT_E_AC3_JOC }, +#endif +#endif + { 0, AUDIO_FORMAT_INVALID } +}; + +status_t AVUtils::mapMimeToAudioFormat( + audio_format_t& format, const char* mime) { + const struct mime_conv_t* p = &mimeLookup[0]; + while (p->mime != NULL) { + if (0 == strcasecmp(mime, p->mime)) { + format = p->format; + return OK; + } + ++p; + } + + return BAD_VALUE; +} + +status_t AVUtils::sendMetaDataToHal( + const sp<MetaData>& meta, AudioParameter *param){ +#ifdef FLAC_OFFLOAD_ENABLED + int32_t minBlkSize, maxBlkSize, minFrmSize, maxFrmSize; //FLAC params + if (meta->findInt32(kKeyMinBlkSize, &minBlkSize)) { + param->addInt(String8(AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE), minBlkSize); + } + if (meta->findInt32(kKeyMaxBlkSize, &maxBlkSize)) { + param->addInt(String8(AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE), maxBlkSize); + } + if (meta->findInt32(kKeyMinFrmSize, &minFrmSize)) { + param->addInt(String8(AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE), minFrmSize); + } + if (meta->findInt32(kKeyMaxFrmSize, &maxFrmSize)) { + param->addInt(String8(AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE), maxFrmSize); + } +#else + (void)meta; + (void)param; +#endif + return OK; +} + +bool AVUtils::is24bitPCMOffloadEnabled() { + char propPCMOfload[PROPERTY_VALUE_MAX] = {0}; + property_get("audio.offload.pcm.24bit.enable", propPCMOfload, "0"); + if (!strncmp(propPCMOfload, "true", 4) || atoi(propPCMOfload)) + return true; + else + return false; +} + +bool AVUtils::is16bitPCMOffloadEnabled() { + char propPCMOfload[PROPERTY_VALUE_MAX] = {0}; + property_get("audio.offload.pcm.16bit.enable", propPCMOfload, "0"); + if (!strncmp(propPCMOfload, "true", 4) || atoi(propPCMOfload)) + return true; + else + return false; +} + + +int AVUtils::getAudioSampleBits(const sp<MetaData> &meta) { + int32_t bits = 16; + audio_format_t audioFormat = AUDIO_FORMAT_INVALID; + if (meta->findInt32('pfmt', (int32_t *)&audioFormat)) { + bits = audio_bytes_per_sample(audioFormat) * 8; + } else if (meta->findInt32(kKeyBitsPerSample, &bits)) { + return bits; + } + return bits; +} + +int AVUtils::getAudioSampleBits(const sp<AMessage> &format) { + int32_t bits = 16; + audio_format_t audioFormat = AUDIO_FORMAT_INVALID; + if (format->findInt32("pcm-format", (int32_t *)&audioFormat)) { + bits = audio_bytes_per_sample(audioFormat) * 8; + } else if (format->findInt32("bits-per-sample", &bits)) { + return bits; + } + return bits; +} + +void AVUtils::setPcmSampleBits(const sp<AMessage> &format, int32_t bitWidth) { + format->setInt32("bits-per-sample", bitWidth); +} + +void AVUtils::setPcmSampleBits(const sp<MetaData> &meta, int32_t bitWidth) { + meta->setInt32(kKeyBitsPerSample, bitWidth); +} + +audio_format_t AVUtils::updateAudioFormat(audio_format_t audioFormat, + const sp<MetaData> &meta){ + int32_t bits = getAudioSampleBits(meta); + + ALOGV("updateAudioFormat %x %d", audioFormat, bits); + meta->dumpToLog(); + + // Override audio format for PCM offload + if (audio_is_linear_pcm(audioFormat)) { + if (bits > 16 && is24bitPCMOffloadEnabled()) { + audioFormat = AUDIO_FORMAT_PCM_24_BIT_OFFLOAD; + meta->setInt32(kKeyBitsPerSample, 24); + } else if (bits == 16 && is16bitPCMOffloadEnabled()) { + audioFormat = AUDIO_FORMAT_PCM_16_BIT_OFFLOAD; + } + } + + return audioFormat; +} + +audio_format_t AVUtils::updateAudioFormat(audio_format_t audioFormat, + const sp<AMessage> &format){ + int32_t bits = getAudioSampleBits(format); + + ALOGV("updateAudioFormat %x %d %s", audioFormat, bits, format->debugString().c_str()); + + // Override audio format for PCM offload + if (audio_is_linear_pcm(audioFormat)) { + if (bits > 16 && is24bitPCMOffloadEnabled()) { + audioFormat = AUDIO_FORMAT_PCM_24_BIT_OFFLOAD; + format->setInt32("bits-per-sample", 24); + } else if (bits == 16 && is16bitPCMOffloadEnabled()) { + audioFormat = AUDIO_FORMAT_PCM_16_BIT_OFFLOAD; + } + } + + return audioFormat; +} + +static bool dumbSniffer( + const sp<DataSource> &, String8 *, + float *, sp<AMessage> *) { + return false; +} + +DataSource::SnifferFunc AVUtils::getExtendedSniffer() { + return dumbSniffer; +} + +sp<MediaCodec> AVUtils::createCustomComponentByName( + const sp<ALooper> &, const char* , bool, const sp<AMessage> &) { + return NULL; +} + +bool AVUtils::canOffloadAPE(const sp<MetaData> &) { + return true; +} + +int32_t AVUtils::getAudioMaxInputBufferSize(audio_format_t, const sp<AMessage> &) { + return 0; +} + +bool AVUtils::mapAACProfileToAudioFormat(const sp<MetaData> &, audio_format_t &, + uint64_t /*eAacProfile*/) { + return false ; +} + +bool AVUtils::mapAACProfileToAudioFormat(const sp<AMessage> &, audio_format_t &, + uint64_t /*eAacProfile*/) { + return false ; +} + +bool AVUtils::isEnhancedExtension(const char *) { + return false; +} + +bool AVUtils::HEVCMuxer::reassembleHEVCCSD(const AString &mime, sp<ABuffer> csd0, sp<MetaData> &meta) { + if (!isVideoHEVC(mime.c_str())) { + return false; + } + void *csd = NULL; + size_t size = 0; + + if (makeHEVCCodecSpecificData(csd0->data(), csd0->size(), &csd, &size) == OK) { + meta->setData(kKeyHVCC, kTypeHVCC, csd, size); + free(csd); + return true; + } + ALOGE("Failed to reassemble HVCC data"); + return false; +} + +void AVUtils::HEVCMuxer::writeHEVCFtypBox(MPEG4Writer *writer) { + ALOGV("writeHEVCFtypBox called"); + writer->writeFourcc("3gp5"); + writer->writeInt32(0); + writer->writeFourcc("hvc1"); + writer->writeFourcc("hev1"); + writer->writeFourcc("3gp5"); +} + +status_t AVUtils::HEVCMuxer::makeHEVCCodecSpecificData( + const uint8_t *data, size_t size, void** codecSpecificData, + size_t *codecSpecificDataSize) { + ALOGV("makeHEVCCodecSpecificData called"); + + if (*codecSpecificData != NULL) { + ALOGE("Already have codec specific data"); + return ERROR_MALFORMED; + } + + if (size < 4) { + ALOGE("Codec specific data length too short: %zu", size); + return ERROR_MALFORMED; + } + + // Data is in the form of HVCCodecSpecificData + if (memcmp("\x00\x00\x00\x01", data, 4)) { + // 23 byte fixed header + if (size < 23) { + ALOGE("Codec specific data length too short: %zu", size); + return ERROR_MALFORMED; + } + + *codecSpecificData = malloc(size); + + if (*codecSpecificData != NULL) { + *codecSpecificDataSize = size; + memcpy(*codecSpecificData, data, size); + return OK; + } + + return NO_MEMORY; + } + + List<HEVCParamSet> vidParamSets; + List<HEVCParamSet> seqParamSets; + List<HEVCParamSet> picParamSets; + + if ((*codecSpecificDataSize = parseHEVCCodecSpecificData(data, size, + vidParamSets, seqParamSets, picParamSets)) == 0) { + ALOGE("cannot parser codec specific data, bailing out"); + return ERROR_MALFORMED; + } + + size_t numOfNALArray = 0; + bool doneWritingVPS = true, doneWritingSPS = true, doneWritingPPS = true; + + if (!vidParamSets.empty()) { + doneWritingVPS = false; + ++numOfNALArray; + } + + if (!seqParamSets.empty()) { + doneWritingSPS = false; + ++numOfNALArray; + } + + if (!picParamSets.empty()) { + doneWritingPPS = false; + ++numOfNALArray; + } + + //additional 23 bytes needed (22 bytes for hvc1 header + 1 byte for number of arrays) + *codecSpecificDataSize += 23; + //needed 3 bytes per NAL array + *codecSpecificDataSize += 3 * numOfNALArray; + + int count = 0; + void *codecConfigData = malloc(*codecSpecificDataSize); + if (codecSpecificData == NULL) { + ALOGE("Failed to allocate memory, bailing out"); + return NO_MEMORY; + } + + uint8_t *header = (uint8_t *)codecConfigData; + // 8 - bit version + header[0] = 1; + //Profile space 2 bit, tier flag 1 bit and profile IDC 5 bit + header[1] = 0x00; + // 32 - bit compatibility flag + header[2] = 0x00; + header[3] = 0x00; + header[4] = 0x00; + header[5] = 0x00; + // 48 - bit general constraint indicator flag + header[6] = header[7] = header[8] = 0x00; + header[9] = header[10] = header[11] = 0x00; + // 8 - bit general IDC level + header[12] = 0x00; + // 4 - bit reserved '1111' + // 12 - bit spatial segmentation idc + header[13] = 0xf0; + header[14] = 0x00; + // 6 - bit reserved '111111' + // 2 - bit parallelism Type + header[15] = 0xfc; + // 6 - bit reserved '111111' + // 2 - bit chromaFormat + header[16] = 0xfc; + // 5 - bit reserved '11111' + // 3 - bit DepthLumaMinus8 + header[17] = 0xf8; + // 5 - bit reserved '11111' + // 3 - bit DepthChromaMinus8 + header[18] = 0xf8; + // 16 - bit average frame rate + header[19] = header[20] = 0x00; + // 2 - bit constant frame rate + // 3 - bit num temporal layers + // 1 - bit temoral nested + // 2 - bit lengthSizeMinusOne + header[21] = 0x07; + + // 8-bit number of NAL types + header[22] = (uint8_t)numOfNALArray; + + header += 23; + count += 23; + + bool ifProfileIDCAlreadyFilled = false; + + if (!doneWritingVPS) { + doneWritingVPS = true; + ALOGV("Writing VPS"); + //8-bit, last 6 bit for NAL type + header[0] = 0x20; // NAL type is VPS + //16-bit, number of nal Units + uint16_t vidParamSetLength = vidParamSets.size(); + header[1] = vidParamSetLength >> 8; + header[2] = vidParamSetLength & 0xff; + + header += 3; + count += 3; + + for (List<HEVCParamSet>::iterator it = vidParamSets.begin(); + it != vidParamSets.end(); ++it) { + // 16-bit video parameter set length + uint16_t vidParamSetLength = it->mLength; + header[0] = vidParamSetLength >> 8; + header[1] = vidParamSetLength & 0xff; + + extractNALRBSPData(it->mData, it->mLength, + (uint8_t **)&codecConfigData, + &ifProfileIDCAlreadyFilled); + + // VPS NAL unit (video parameter length bytes) + memcpy(&header[2], it->mData, vidParamSetLength); + header += (2 + vidParamSetLength); + count += (2 + vidParamSetLength); + } + } + + if (!doneWritingSPS) { + doneWritingSPS = true; + ALOGV("Writting SPS"); + //8-bit, last 6 bit for NAL type + header[0] = 0x21; // NAL type is SPS + //16-bit, number of nal Units + uint16_t seqParamSetLength = seqParamSets.size(); + header[1] = seqParamSetLength >> 8; + header[2] = seqParamSetLength & 0xff; + + header += 3; + count += 3; + + for (List<HEVCParamSet>::iterator it = seqParamSets.begin(); + it != seqParamSets.end(); ++it) { + // 16-bit sequence parameter set length + uint16_t seqParamSetLength = it->mLength; + + // 16-bit number of NAL units of this type + header[0] = seqParamSetLength >> 8; + header[1] = seqParamSetLength & 0xff; + + extractNALRBSPData(it->mData, it->mLength, + (uint8_t **)&codecConfigData, + &ifProfileIDCAlreadyFilled); + + // SPS NAL unit (sequence parameter length bytes) + memcpy(&header[2], it->mData, seqParamSetLength); + header += (2 + seqParamSetLength); + count += (2 + seqParamSetLength); + } + } + + if (!doneWritingPPS) { + doneWritingPPS = true; + ALOGV("writing PPS"); + //8-bit, last 6 bit for NAL type + header[0] = 0x22; // NAL type is PPS + //16-bit, number of nal Units + uint16_t picParamSetLength = picParamSets.size(); + header[1] = picParamSetLength >> 8; + header[2] = picParamSetLength & 0xff; + + header += 3; + count += 3; + + for (List<HEVCParamSet>::iterator it = picParamSets.begin(); + it != picParamSets.end(); ++it) { + // 16-bit picture parameter set length + uint16_t picParamSetLength = it->mLength; + header[0] = picParamSetLength >> 8; + header[1] = picParamSetLength & 0xff; + + // PPS Nal unit (picture parameter set length bytes) + memcpy(&header[2], it->mData, picParamSetLength); + header += (2 + picParamSetLength); + count += (2 + picParamSetLength); + } + } + *codecSpecificData = codecConfigData; + return OK; +} + +const char *AVUtils::HEVCMuxer::getFourCCForMime(const char * mime) { + if (isVideoHEVC(mime)) { + return "hvc1"; + } + return NULL; +} + +void AVUtils::HEVCMuxer::writeHvccBox(MPEG4Writer *writer, + void *codecSpecificData, size_t codecSpecificDataSize, + bool useNalLengthFour) { + ALOGV("writeHvccBox called"); + CHECK(codecSpecificData); + CHECK_GE(codecSpecificDataSize, 23); + + // Patch hvcc's lengthSize field to match the number + // of bytes we use to indicate the size of a nal unit. + uint8_t *ptr = (uint8_t *)codecSpecificData; + ptr[21] = (ptr[21] & 0xfc) | (useNalLengthFour? 3 : 1); + writer->beginBox("hvcC"); + writer->write(codecSpecificData, codecSpecificDataSize); + writer->endBox(); // hvcC +} + +bool AVUtils::HEVCMuxer::isVideoHEVC(const char * mime) { + return (!strncasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC, + strlen(MEDIA_MIMETYPE_VIDEO_HEVC))); +} + +status_t AVUtils::HEVCMuxer::extractNALRBSPData(const uint8_t *data, + size_t size, + uint8_t **header, + bool *alreadyFilled) { + ALOGV("extractNALRBSPData called"); + CHECK_GE(size, 2); + + uint8_t type = data[0] >> 1; + type = 0x3f & type; + + //start parsing here + size_t rbspSize = 0; + uint8_t *rbspData = (uint8_t *) malloc(size); + + if (rbspData == NULL) { + ALOGE("allocation failed"); + return UNKNOWN_ERROR; + } + + //populate rbsp data start from i+2, search for 0x000003, + //and ignore emulation_prevention byte + size_t itt = 2; + while (itt < size) { + if ((itt+2 < size) && (!memcmp("\x00\x00\x03", &data[itt], 3) )) { + rbspData[rbspSize++] = data[itt++]; + rbspData[rbspSize++] = data[itt++]; + itt++; + } else { + rbspData[rbspSize++] = data[itt++]; + } + } + + uint8_t maxSubLayerMinus1 = 0; + + //parser profileTierLevel + if (type == kHEVCNalUnitTypeVidParamSet) { // if VPS + ALOGV("its VPS ... start with 5th byte"); + if (rbspSize < 5) { + free(rbspData); + return ERROR_MALFORMED; + } + + maxSubLayerMinus1 = 0x0E & rbspData[1]; + maxSubLayerMinus1 = maxSubLayerMinus1 >> 1; + parserProfileTierLevel(&rbspData[4], rbspSize - 4, header, alreadyFilled); + + } else if (type == kHEVCNalUnitTypeSeqParamSet) { + ALOGV("its SPS .. start with 2nd byte"); + if (rbspSize < 2) { + free(rbspData); + return ERROR_MALFORMED; + } + + maxSubLayerMinus1 = 0x0E & rbspData[0]; + maxSubLayerMinus1 = maxSubLayerMinus1 >> 1; + + parserProfileTierLevel(&rbspData[1], rbspSize - 1, header, alreadyFilled); + } + free(rbspData); + return OK; +} + +status_t AVUtils::HEVCMuxer::parserProfileTierLevel(const uint8_t *data, size_t size, + uint8_t **header, bool *alreadyFilled) { + CHECK_GE(size, 12); + uint8_t *tmpHeader = *header; + ALOGV("parserProfileTierLevel called"); + uint8_t generalProfileSpace; //2 bit + uint8_t generalTierFlag; //1 bit + uint8_t generalProfileIdc; //5 bit + uint8_t generalProfileCompatibilityFlag[4]; + uint8_t generalConstraintIndicatorFlag[6]; + uint8_t generalLevelIdc; //8 bit + + // Need first 12 bytes + + // First byte will give below info + generalProfileSpace = 0xC0 & data[0]; + generalProfileSpace = generalProfileSpace > 6; + generalTierFlag = 0x20 & data[0]; + generalTierFlag = generalTierFlag > 5; + generalProfileIdc = 0x1F & data[0]; + + // Next 4 bytes is compatibility flag + memcpy(&generalProfileCompatibilityFlag, &data[1], 4); + + // Next 6 bytes is constraint indicator flag + memcpy(&generalConstraintIndicatorFlag, &data[5], 6); + + // Next 1 byte is general Level IDC + generalLevelIdc = data[11]; + + if (*alreadyFilled) { + bool overwriteTierValue = false; + + //find profile space + uint8_t prvGeneralProfileSpace; //2 bit + prvGeneralProfileSpace = 0xC0 & tmpHeader[1]; + prvGeneralProfileSpace = prvGeneralProfileSpace > 6; + //prev needs to be same as current + if (prvGeneralProfileSpace != generalProfileSpace) { + ALOGW("Something wrong!!! profile space mismatch"); + } + + uint8_t prvGeneralTierFlag = 0x20 & tmpHeader[1]; + prvGeneralTierFlag = prvGeneralTierFlag > 5; + + if (prvGeneralTierFlag < generalTierFlag) { + overwriteTierValue = true; + ALOGV("Found higher tier value, replacing old one"); + } + + uint8_t prvGeneralProfileIdc = 0x1F & tmpHeader[1]; + + if (prvGeneralProfileIdc != generalProfileIdc) { + ALOGW("Something is wrong!!! profile space mismatch"); + } + + if (overwriteTierValue) { + tmpHeader[1] = data[0]; + } + + //general level IDC should be set highest among all + if (tmpHeader[12] < data[11]) { + tmpHeader[12] = data[11]; + ALOGV("Found higher level IDC value, replacing old one"); + } + + } else { + *alreadyFilled = true; + tmpHeader[1] = data[0]; + memcpy(&tmpHeader[2], &data[1], 4); + memcpy(&tmpHeader[6], &data[5], 6); + tmpHeader[12] = data[11]; + } + + char printCodecConfig[PROPERTY_VALUE_MAX]; + property_get("hevc.mux.print.codec.config", printCodecConfig, "0"); + + if (atoi(printCodecConfig)) { + //if property enabled, print these values + ALOGI("Start::-----------------"); + ALOGI("generalProfileSpace = %2x", generalProfileSpace); + ALOGI("generalTierFlag = %2x", generalTierFlag); + ALOGI("generalProfileIdc = %2x", generalProfileIdc); + ALOGI("generalLevelIdc = %2x", generalLevelIdc); + ALOGI("generalProfileCompatibilityFlag = %2x %2x %2x %2x", generalProfileCompatibilityFlag[0], + generalProfileCompatibilityFlag[1], generalProfileCompatibilityFlag[2], + generalProfileCompatibilityFlag[3]); + ALOGI("generalConstraintIndicatorFlag = %2x %2x %2x %2x %2x %2x", generalConstraintIndicatorFlag[0], + generalConstraintIndicatorFlag[1], generalConstraintIndicatorFlag[2], + generalConstraintIndicatorFlag[3], generalConstraintIndicatorFlag[4], + generalConstraintIndicatorFlag[5]); + ALOGI("End::-----------------"); + } + + return OK; +} +static const uint8_t *findNextStartCode( + const uint8_t *data, size_t length) { + ALOGV("findNextStartCode: %p %zu", data, length); + + size_t bytesLeft = length; + + while (bytesLeft > 4 && + memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) { + --bytesLeft; + } + + if (bytesLeft <= 4) { + bytesLeft = 0; // Last parameter set + } + + return &data[length - bytesLeft]; +} + +const uint8_t *AVUtils::HEVCMuxer::parseHEVCParamSet( + const uint8_t *data, size_t length, List<HEVCParamSet> ¶mSetList, size_t *paramSetLen) { + ALOGV("parseHEVCParamSet called"); + const uint8_t *nextStartCode = findNextStartCode(data, length); + *paramSetLen = nextStartCode - data; + if (*paramSetLen == 0) { + ALOGE("Param set is malformed, since its length is 0"); + return NULL; + } + + HEVCParamSet paramSet(*paramSetLen, data); + paramSetList.push_back(paramSet); + + return nextStartCode; +} + +static void getHEVCNalUnitType(uint8_t byte, uint8_t* type) { + ALOGV("getNalUnitType: %d", (int)byte); + // nal_unit_type: 6-bit unsigned integer + *type = (byte & 0x7E) >> 1; +} + +size_t AVUtils::HEVCMuxer::parseHEVCCodecSpecificData( + const uint8_t *data, size_t size,List<HEVCParamSet> &vidParamSet, + List<HEVCParamSet> &seqParamSet, List<HEVCParamSet> &picParamSet ) { + ALOGV("parseHEVCCodecSpecificData called"); + // Data starts with a start code. + // VPS, SPS and PPS are separated with start codes. + uint8_t type = kHEVCNalUnitTypeVidParamSet; + bool gotVps = false; + bool gotSps = false; + bool gotPps = false; + const uint8_t *tmp = data; + const uint8_t *nextStartCode = data; + size_t bytesLeft = size; + size_t paramSetLen = 0; + size_t codecSpecificDataSize = 0; + while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) { + getHEVCNalUnitType(*(tmp + 4), &type); + if (type == kHEVCNalUnitTypeVidParamSet) { + nextStartCode = parseHEVCParamSet(tmp + 4, bytesLeft - 4, vidParamSet, ¶mSetLen); + if (!gotVps) { + gotVps = true; + } + } else if (type == kHEVCNalUnitTypeSeqParamSet) { + nextStartCode = parseHEVCParamSet(tmp + 4, bytesLeft - 4, seqParamSet, ¶mSetLen); + if (!gotSps) { + gotSps = true; + } + + } else if (type == kHEVCNalUnitTypePicParamSet) { + nextStartCode = parseHEVCParamSet(tmp + 4, bytesLeft - 4, picParamSet, ¶mSetLen); + if (!gotPps) { + gotPps = true; + } + } else { + ALOGE("Only VPS, SPS and PPS Nal units are expected"); + return 0; + } + + if (nextStartCode == NULL) { + ALOGE("Next start code is NULL"); + return 0; + } + + // Move on to find the next parameter set + bytesLeft -= nextStartCode - tmp; + tmp = nextStartCode; + codecSpecificDataSize += (2 + paramSetLen); + } + +#if 0 +//not adding this check now, but might be needed + if (!gotVps || !gotVps || !gotVps ) { + return 0; + } +#endif + + return codecSpecificDataSize; +} + +void AVUtils::HEVCMuxer::getHEVCCodecSpecificDataFromInputFormatIfPossible( + sp<MetaData> meta, void ** codecSpecificData, + size_t * codecSpecificDataSize, bool * gotAllCodecSpecificData) { + uint32_t type; + const void *data; + size_t size; + //kKeyHVCC needs to be populated + if (meta->findData(kKeyHVCC, &type, &data, &size)) { + *codecSpecificData = malloc(size); + CHECK(*codecSpecificData != NULL); + *codecSpecificDataSize = size; + memcpy(*codecSpecificData, data, size); + *gotAllCodecSpecificData = true; + } else { + ALOGW("getHEVCCodecConfigData:: failed to find kKeyHvcc"); + } +} + +bool AVUtils::isAudioMuxFormatSupported(const char * mime) { + if (mime == NULL) { + ALOGE("NULL audio mime type"); + return false; + } + + if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) + || !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime) + || !strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { + return true; + } + return false; +} + +void AVUtils::cacheCaptureBuffers(sp<ICamera> camera, video_encoder encoder) { + if (camera != NULL) { + char mDeviceName[PROPERTY_VALUE_MAX]; + property_get("ro.board.platform", mDeviceName, "0"); + if (!strncmp(mDeviceName, "msm8909", 7)) { + int64_t token = IPCThreadState::self()->clearCallingIdentity(); + String8 s = camera->getParameters(); + CameraParameters params(s); + const char *enable; + if (encoder == VIDEO_ENCODER_H263 || + encoder == VIDEO_ENCODER_MPEG_4_SP) { + enable = "1"; + } else { + enable = "0"; + } + params.set("cache-video-buffers", enable); + if (camera->setParameters(params.flatten()) != OK) { + ALOGE("Failed to enabled cached camera buffers"); + } + IPCThreadState::self()->restoreCallingIdentity(token); + } + } +} + +const char *AVUtils::getCustomCodecsLocation() { + return "/etc/media_codecs.xml"; +} + +void AVUtils::setIntraPeriod( + int, int, const sp<IOMX>, + IOMX::node_id) { + return; +} + +#ifdef QCOM_HARDWARE +void AVUtils::HFR::setHFRIfEnabled( + const CameraParameters& params, + sp<MetaData> &meta) { + const char *hfrParam = params.get("video-hfr"); + int32_t hfr = -1; + if (hfrParam != NULL) { + hfr = atoi(hfrParam); + if (hfr > 0) { + ALOGI("Enabling HFR @ %d fps", hfr); + meta->setInt32(kKeyHFR, hfr); + return; + } else { + ALOGI("Invalid HFR rate specified : %d", hfr); + } + } + + const char *hsrParam = params.get("video-hsr"); + int32_t hsr = -1; + if (hsrParam != NULL ) { + hsr = atoi(hsrParam); + if (hsr > 0) { + ALOGI("Enabling HSR @ %d fps", hsr); + meta->setInt32(kKeyHSR, hsr); + } else { + ALOGI("Invalid HSR rate specified : %d", hfr); + } + } +} + +status_t AVUtils::HFR::initializeHFR( + const sp<MetaData> &meta, sp<AMessage> &format, + int64_t & /*maxFileDurationUs*/, video_encoder videoEncoder) { + status_t retVal = OK; + + int32_t hsr = 0; + if (meta->findInt32(kKeyHSR, &hsr) && hsr > 0) { + ALOGI("HSR cue found. Override encode fps to %d", hsr); + format->setInt32("frame-rate", hsr); + return retVal; + } + + int32_t hfr = 0; + if (!meta->findInt32(kKeyHFR, &hfr) || (hfr <= 0)) { + ALOGW("Invalid HFR rate specified"); + return retVal; + } + + int32_t width = 0, height = 0; + CHECK(meta->findInt32(kKeyWidth, &width)); + CHECK(meta->findInt32(kKeyHeight, &height)); + + int maxW, maxH, MaxFrameRate, maxBitRate = 0; + if (getHFRCapabilities(videoEncoder, + maxW, maxH, MaxFrameRate, maxBitRate) < 0) { + ALOGE("Failed to query HFR target capabilities"); + return ERROR_UNSUPPORTED; + } + + if ((width * height * hfr) > (maxW * maxH * MaxFrameRate)) { + ALOGE("HFR request [%d x %d @%d fps] exceeds " + "[%d x %d @%d fps]. Will stay disabled", + width, height, hfr, maxW, maxH, MaxFrameRate); + return ERROR_UNSUPPORTED; + } + + int32_t frameRate = 0, bitRate = 0; + CHECK(meta->findInt32(kKeyFrameRate, &frameRate)); + CHECK(format->findInt32("bitrate", &bitRate)); + + if (frameRate) { + // scale the bitrate proportional to the hfr ratio + // to maintain quality, but cap it to max-supported. + bitRate = (hfr * bitRate) / frameRate; + bitRate = bitRate > maxBitRate ? maxBitRate : bitRate; + format->setInt32("bitrate", bitRate); + + int32_t hfrRatio = hfr / frameRate; + format->setInt32("frame-rate", hfr); + format->setInt32("hfr-ratio", hfrRatio); + } else { + ALOGE("HFR: Invalid framerate"); + return BAD_VALUE; + } + + return retVal; +} + +void AVUtils::HFR::setHFRRatio( + sp<MetaData> &meta, const int32_t hfrRatio) { + if (hfrRatio > 0) { + meta->setInt32(kKeyHFR, hfrRatio); + } +} + +int32_t AVUtils::HFR::getHFRRatio( + const sp<MetaData> &meta) { + int32_t hfrRatio = 0; + meta->findInt32(kKeyHFR, &hfrRatio); + return hfrRatio ? hfrRatio : 1; +} + +int32_t AVUtils::HFR::getHFRCapabilities( + video_encoder codec, + int& maxHFRWidth, int& maxHFRHeight, int& maxHFRFps, + int& maxBitRate) { + maxHFRWidth = maxHFRHeight = maxHFRFps = maxBitRate = 0; + MediaProfiles *profiles = MediaProfiles::getInstance(); + + if (profiles) { + maxHFRWidth = profiles->getVideoEncoderParamByName("enc.vid.hfr.width.max", codec); + maxHFRHeight = profiles->getVideoEncoderParamByName("enc.vid.hfr.height.max", codec); + maxHFRFps = profiles->getVideoEncoderParamByName("enc.vid.hfr.mode.max", codec); + maxBitRate = profiles->getVideoEncoderParamByName("enc.vid.bps.max", codec); + } + + return (maxHFRWidth > 0) && (maxHFRHeight > 0) && + (maxHFRFps > 0) && (maxBitRate > 0) ? 1 : -1; +} +#else +void AVUtils::HFR::setHFRIfEnabled( + const CameraParameters& /*params*/, + sp<MetaData> & /*meta*/) {} + +status_t AVUtils::HFR::initializeHFR( + const sp<MetaData> & /*meta*/, sp<AMessage> & /*format*/, + int64_t & /*maxFileDurationUs*/, video_encoder /*videoEncoder*/) { + return OK; +} + +void AVUtils::HFR::setHFRRatio( + sp<MetaData> & /*meta*/, const int32_t /*hfrRatio*/) {} + +int32_t AVUtils::HFR::getHFRRatio( + const sp<MetaData> & /*meta */) { + return 1; +} + +int32_t AVUtils::HFR::getHFRCapabilities( + video_encoder /*codec*/, + int& /*maxHFRWidth*/, int& /*maxHFRHeight*/, int& /*maxHFRFps*/, + int& /*maxBitRate*/) { + return -1; +} +#endif + +void AVUtils::extractCustomCameraKeys( + const CameraParameters& params, sp<MetaData> &meta) { + mHFR.setHFRIfEnabled(params, meta); +} + +// ----- NO TRESSPASSING BEYOND THIS LINE ------ +AVUtils::AVUtils() {} + +AVUtils::~AVUtils() {} + +//static +AVUtils *AVUtils::sInst = + ExtensionsLoader<AVUtils>::createInstance("createAVUtils"); + +} //namespace android + diff --git a/media/libavextensions/stagefright/ExtendedMediaDefs.cpp b/media/libavextensions/stagefright/ExtendedMediaDefs.cpp new file mode 100644 index 0000000..cf2683c --- /dev/null +++ b/media/libavextensions/stagefright/ExtendedMediaDefs.cpp @@ -0,0 +1,68 @@ +/*Copyright (c) 2012 - 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <stagefright/ExtendedMediaDefs.h> + +namespace android { + +const char *MEDIA_MIMETYPE_AUDIO_EVRC = "audio/evrc"; +const char *MEDIA_MIMETYPE_VIDEO_WMV = "video/x-ms-wmv"; +const char *MEDIA_MIMETYPE_VIDEO_WMV_VC1 = "video/wvc1"; +const char *MEDIA_MIMETYPE_AUDIO_WMA = "audio/x-ms-wma"; +const char *MEDIA_MIMETYPE_AUDIO_WMA_PRO = "audio/x-ms-wma-pro"; +const char *MEDIA_MIMETYPE_AUDIO_WMA_LOSSLESS = "audio/x-ms-wma-lossless"; +const char *MEDIA_MIMETYPE_CONTAINER_ASF = "video/x-ms-asf"; +const char *MEDIA_MIMETYPE_VIDEO_DIVX = "video/divx"; +const char *MEDIA_MIMETYPE_CONTAINER_AAC = "audio/aac"; +const char *MEDIA_MIMETYPE_CONTAINER_QCP = "audio/vnd.qcelp"; +const char *MEDIA_MIMETYPE_VIDEO_DIVX311 = "video/divx311"; +const char *MEDIA_MIMETYPE_VIDEO_DIVX4 = "video/divx4"; +const char *MEDIA_MIMETYPE_CONTAINER_MPEG2 = "video/mp2"; +const char *MEDIA_MIMETYPE_CONTAINER_3G2 = "video/3g2"; +const char *MEDIA_MIMETYPE_AUDIO_DTS = "audio/dts"; +const char *MEDIA_MIMETYPE_AUDIO_DTS_LBR = "audio/dts-lbr"; +const char *MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS = "audio/amr-wb-plus"; +const char *MEDIA_MIMETYPE_AUDIO_AIFF = "audio/x-aiff"; +const char *MEDIA_MIMETYPE_AUDIO_ALAC = "audio/alac"; +const char *MEDIA_MIMETYPE_AUDIO_APE = "audio/x-ape"; +const char *MEDIA_MIMETYPE_CONTAINER_QCAMR_NB = "audio/qc-amr"; +const char *MEDIA_MIMETYPE_CONTAINER_QCAMR_WB = "audio/qc-amr-wb"; +const char *MEDIA_MIMETYPE_CONTAINER_QCMPEG = "audio/qc-mpeg"; +const char *MEDIA_MIMETYPE_CONTAINER_QCWAV = "audio/qc-wav"; +const char *MEDIA_MIMETYPE_CONTAINER_QCMPEG2TS = "video/qc-mp2ts"; +const char *MEDIA_MIMETYPE_CONTAINER_QCMPEG2PS = "video/qc-mp2ps"; +const char *MEDIA_MIMETYPE_CONTAINER_QCMPEG4 = "video/qc-mp4"; +const char *MEDIA_MIMETYPE_CONTAINER_QCMATROSKA = "video/qc-matroska"; +const char *MEDIA_MIMETYPE_CONTAINER_QCOGG = "video/qc-ogg"; +const char *MEDIA_MIMETYPE_CONTAINER_QCFLV = "video/qc-flv"; +const char *MEDIA_MIMETYPE_VIDEO_VPX = "video/x-vnd.on2.vp8"; //backward compatibility +const char *MEDIA_MIMETYPE_CONTAINER_QTIFLAC = "audio/qti-flac"; +const char *MEDIA_MIMETYPE_VIDEO_MPEG4_DP = "video/mp4v-esdp"; + +} // namespace android |