diff options
Diffstat (limited to 'media')
-rw-r--r-- | media/libmedia/AudioSystem.cpp | 6 | ||||
-rw-r--r-- | media/libmedia/AudioTrack.cpp | 7 | ||||
-rw-r--r-- | media/libmediaplayerservice/Crypto.cpp | 3 | ||||
-rw-r--r-- | media/libmediaplayerservice/MidiFile.cpp | 2 | ||||
-rw-r--r-- | media/libmediaplayerservice/SharedLibrary.cpp | 6 | ||||
-rw-r--r-- | media/libmediaplayerservice/SharedLibrary.h | 1 | ||||
-rw-r--r-- | media/libstagefright/codecs/on2/enc/Android.mk | 5 | ||||
-rw-r--r-- | media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp | 159 | ||||
-rw-r--r-- | media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h | 15 |
9 files changed, 179 insertions, 25 deletions
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 22d6763..6b9b3be 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -454,7 +454,7 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(int event, audio_io_handle } break; case OUTPUT_CLOSED: { if (gOutputs.indexOfKey(ioHandle) < 0) { - ALOGW("ioConfigChanged() closing unknow output! %d", ioHandle); + ALOGW("ioConfigChanged() closing unknown output! %d", ioHandle); break; } ALOGV("ioConfigChanged() output %d closed", ioHandle); @@ -465,7 +465,7 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(int event, audio_io_handle case OUTPUT_CONFIG_CHANGED: { int index = gOutputs.indexOfKey(ioHandle); if (index < 0) { - ALOGW("ioConfigChanged() modifying unknow output! %d", ioHandle); + ALOGW("ioConfigChanged() modifying unknown output! %d", ioHandle); break; } if (param2 == NULL) break; @@ -537,6 +537,8 @@ const sp<IAudioPolicyService>& AudioSystem::get_audio_policy_service() return gAudioPolicyService; } +// --------------------------------------------------------------------------- + status_t AudioSystem::setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state, const char *device_address) diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 00f4640..7b6b38d 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -585,6 +585,7 @@ void AudioTrack::setLoop_l(uint32_t loopStart, uint32_t loopEnd, int loopCount) status_t AudioTrack::setMarkerPosition(uint32_t marker) { + // The only purpose of setting marker position is to get a callback if (mCbf == NULL) { return INVALID_OPERATION; } @@ -610,6 +611,7 @@ status_t AudioTrack::getMarkerPosition(uint32_t *marker) const status_t AudioTrack::setPositionUpdatePeriod(uint32_t updatePeriod) { + // The only purpose of setting position update period is to get a callback if (mCbf == NULL) { return INVALID_OPERATION; } @@ -1220,6 +1222,11 @@ status_t TimedAudioTrack::setMediaTimeTransform(const LinearTransform& xform, nsecs_t AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) { + // Currently the AudioTrack thread is not created if there are no callbacks. + // Would it ever make sense to run the thread, even without callbacks? + // If so, then replace this by checks at each use for mCbf != NULL. + LOG_ALWAYS_FATAL_IF(mCblk == NULL); + mLock.lock(); if (mAwaitBoost) { mAwaitBoost = false; diff --git a/media/libmediaplayerservice/Crypto.cpp b/media/libmediaplayerservice/Crypto.cpp index ae4d845..62593b2 100644 --- a/media/libmediaplayerservice/Crypto.cpp +++ b/media/libmediaplayerservice/Crypto.cpp @@ -134,7 +134,6 @@ void Crypto::findFactoryForScheme(const uint8_t uuid[16]) { return; } - ALOGE("Failed to find crypto plugin"); mInitCheck = ERROR_UNSUPPORTED; } @@ -151,6 +150,7 @@ bool Crypto::loadLibraryForScheme(const String8 &path, const uint8_t uuid[16]) { if (!mLibrary.get()) { mLibrary = new SharedLibrary(path); if (!*mLibrary) { + ALOGE("loadLibraryForScheme failed:%s", mLibrary->lastError()); return false; } @@ -165,6 +165,7 @@ bool Crypto::loadLibraryForScheme(const String8 &path, const uint8_t uuid[16]) { if (createCryptoFactory == NULL || (mFactory = createCryptoFactory()) == NULL || !mFactory->isCryptoSchemeSupported(uuid)) { + ALOGE("createCryptoFactory failed:%s", mLibrary->lastError()); closeFactory(); return false; } diff --git a/media/libmediaplayerservice/MidiFile.cpp b/media/libmediaplayerservice/MidiFile.cpp index 8db5b9b..270b872 100644 --- a/media/libmediaplayerservice/MidiFile.cpp +++ b/media/libmediaplayerservice/MidiFile.cpp @@ -422,7 +422,7 @@ status_t MidiFile::setLooping(int loop) status_t MidiFile::createOutputTrack() { if (mAudioSink->open(pLibConfig->sampleRate, pLibConfig->numChannels, - CHANNEL_MASK_USE_CHANNEL_ORDER, AUDIO_FORMAT_PCM_16_BIT, 2) != NO_ERROR) { + CHANNEL_MASK_USE_CHANNEL_ORDER, AUDIO_FORMAT_PCM_16_BIT, 2 /*bufferCount*/) != NO_ERROR) { ALOGE("mAudioSink open failed"); return ERROR_OPEN_FAILED; } diff --git a/media/libmediaplayerservice/SharedLibrary.cpp b/media/libmediaplayerservice/SharedLibrary.cpp index 178e15d..34db761 100644 --- a/media/libmediaplayerservice/SharedLibrary.cpp +++ b/media/libmediaplayerservice/SharedLibrary.cpp @@ -46,4 +46,10 @@ namespace android { } return dlsym(mLibHandle, symbol); } + + const char *SharedLibrary::lastError() const { + const char *error = dlerror(); + return error ? error : "No errors or unknown error"; + } + }; diff --git a/media/libmediaplayerservice/SharedLibrary.h b/media/libmediaplayerservice/SharedLibrary.h index 5353642..88451a0 100644 --- a/media/libmediaplayerservice/SharedLibrary.h +++ b/media/libmediaplayerservice/SharedLibrary.h @@ -29,6 +29,7 @@ namespace android { bool operator!() const; void *lookup(const char *symbol) const; + const char *lastError() const; private: void *mLibHandle; diff --git a/media/libstagefright/codecs/on2/enc/Android.mk b/media/libstagefright/codecs/on2/enc/Android.mk index a92d376..4060a0a 100644 --- a/media/libstagefright/codecs/on2/enc/Android.mk +++ b/media/libstagefright/codecs/on2/enc/Android.mk @@ -12,11 +12,16 @@ LOCAL_C_INCLUDES := \ frameworks/av/media/libstagefright/include \ frameworks/native/include/media/openmax \ +ifeq ($(TARGET_DEVICE), manta) + LOCAL_CFLAGS += -DSURFACE_IS_BGR32 +endif + LOCAL_STATIC_LIBRARIES := \ libvpx LOCAL_SHARED_LIBRARIES := \ libstagefright libstagefright_omx libstagefright_foundation libutils liblog \ + libhardware \ LOCAL_MODULE := libstagefright_soft_vpxenc LOCAL_MODULE_TAGS := optional diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp index 74d6df5..d8456fe 100644 --- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp +++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp @@ -20,6 +20,8 @@ #include <utils/Log.h> +#include <media/hardware/HardwareAPI.h> +#include <media/hardware/MetadataBufferType.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/MediaDefs.h> @@ -81,6 +83,52 @@ inline static void ConvertSemiPlanarToPlanar(uint8_t *inyuv, } } +static void ConvertRGB32ToPlanar( + const uint8_t *src, uint8_t *dstY, int32_t width, int32_t height) { + CHECK((width & 1) == 0); + CHECK((height & 1) == 0); + + uint8_t *dstU = dstY + width * height; + uint8_t *dstV = dstU + (width / 2) * (height / 2); + + for (int32_t y = 0; y < height; ++y) { + for (int32_t x = 0; x < width; ++x) { +#ifdef SURFACE_IS_BGR32 + unsigned blue = src[4 * x]; + unsigned green = src[4 * x + 1]; + unsigned red= src[4 * x + 2]; +#else + unsigned red= src[4 * x]; + unsigned green = src[4 * x + 1]; + unsigned blue = src[4 * x + 2]; +#endif + + unsigned luma = + ((red * 66 + green * 129 + blue * 25) >> 8) + 16; + + dstY[x] = luma; + + if ((x & 1) == 0 && (y & 1) == 0) { + unsigned U = + ((-red * 38 - green * 74 + blue * 112) >> 8) + 128; + + unsigned V = + ((red * 112 - green * 94 - blue * 18) >> 8) + 128; + + dstU[x / 2] = U; + dstV[x / 2] = V; + } + } + + if ((y & 1) == 0) { + dstU += width / 2; + dstV += width / 2; + } + + src += 4 * width; + dstY += width; + } +} SoftVPXEncoder::SoftVPXEncoder(const char *name, const OMX_CALLBACKTYPE *callbacks, @@ -99,8 +147,9 @@ SoftVPXEncoder::SoftVPXEncoder(const char *name, mErrorResilience(OMX_FALSE), mColorFormat(OMX_COLOR_FormatYUV420Planar), mLevel(OMX_VIDEO_VP8Level_Version0), - mConversionBuffer(NULL) { - + mConversionBuffer(NULL), + mInputDataIsMeta(false), + mGrallocModule(NULL) { initPorts(); } @@ -247,7 +296,7 @@ status_t SoftVPXEncoder::initEncoder() { return UNKNOWN_ERROR; } - if (mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) { + if (mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar || mInputDataIsMeta) { if (mConversionBuffer == NULL) { mConversionBuffer = (uint8_t *)malloc(mWidth * mHeight * 3 / 2); if (mConversionBuffer == NULL) { @@ -427,9 +476,17 @@ OMX_ERRORTYPE SoftVPXEncoder::internalSetParameter(OMX_INDEXTYPE index, (const OMX_VIDEO_PARAM_BITRATETYPE *)param); case OMX_IndexParamPortDefinition: - return internalSetPortParams( + { + OMX_ERRORTYPE err = internalSetPortParams( (const OMX_PARAM_PORTDEFINITIONTYPE *)param); + if (err != OMX_ErrorNone) { + return err; + } + + return SimpleSoftOMXComponent::internalSetParameter(index, param); + } + case OMX_IndexParamVideoPortFormat: return internalSetFormatParams( (const OMX_VIDEO_PARAM_PORTFORMATTYPE *)param); @@ -442,6 +499,21 @@ OMX_ERRORTYPE SoftVPXEncoder::internalSetParameter(OMX_INDEXTYPE index, return internalSetProfileLevel( (const OMX_VIDEO_PARAM_PROFILELEVELTYPE *)param); + case OMX_IndexVendorStartUnused: + { + // storeMetaDataInBuffers + const StoreMetaDataInBuffersParams *storeParam = + (const StoreMetaDataInBuffersParams *)param; + + if (storeParam->nPortIndex != kInputPortIndex) { + return OMX_ErrorBadPortIndex; + } + + mInputDataIsMeta = (storeParam->bStoreMetaData == OMX_TRUE); + + return OMX_ErrorNone; + } + default: return SimpleSoftOMXComponent::internalSetParameter(index, param); } @@ -507,6 +579,10 @@ OMX_ERRORTYPE SoftVPXEncoder::internalSetFormatParams( format->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar || format->eColorFormat == OMX_COLOR_FormatAndroidOpaque) { mColorFormat = format->eColorFormat; + + OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kInputPortIndex)->mDef; + def->format.video.eColorFormat = mColorFormat; + return OMX_ErrorNone; } else { ALOGE("Unsupported color format %i", format->eColorFormat); @@ -552,11 +628,17 @@ OMX_ERRORTYPE SoftVPXEncoder::internalSetPortParams( if (port->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar || port->format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar || port->format.video.eColorFormat == OMX_COLOR_FormatAndroidOpaque) { - mColorFormat = port->format.video.eColorFormat; + mColorFormat = port->format.video.eColorFormat; } else { return OMX_ErrorUnsupportedSetting; } + OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kInputPortIndex)->mDef; + def->format.video.nFrameWidth = mWidth; + def->format.video.nFrameHeight = mHeight; + def->format.video.xFramerate = port->format.video.xFramerate; + def->format.video.eColorFormat = mColorFormat; + return OMX_ErrorNone; } else if (port->nPortIndex == kOutputPortIndex) { mBitrate = port->format.video.nBitrate; @@ -625,24 +707,56 @@ void SoftVPXEncoder::onQueueFilled(OMX_U32 portIndex) { return; } - uint8_t* source = inputBufferHeader->pBuffer + inputBufferHeader->nOffset; + uint8_t *source = + inputBufferHeader->pBuffer + inputBufferHeader->nOffset; + + if (mInputDataIsMeta) { + CHECK_GE(inputBufferHeader->nFilledLen, + 4 + sizeof(buffer_handle_t)); + + uint32_t bufferType = *(uint32_t *)source; + CHECK_EQ(bufferType, kMetadataBufferTypeGrallocSource); + + if (mGrallocModule == NULL) { + CHECK_EQ(0, hw_get_module( + GRALLOC_HARDWARE_MODULE_ID, &mGrallocModule)); + } + + const gralloc_module_t *grmodule = + (const gralloc_module_t *)mGrallocModule; + + buffer_handle_t handle = *(buffer_handle_t *)(source + 4); + + void *bits; + CHECK_EQ(0, + grmodule->lock( + grmodule, handle, + GRALLOC_USAGE_SW_READ_OFTEN + | GRALLOC_USAGE_SW_WRITE_NEVER, + 0, 0, mWidth, mHeight, &bits)); + + ConvertRGB32ToPlanar( + (const uint8_t *)bits, mConversionBuffer, mWidth, mHeight); + + source = mConversionBuffer; + + CHECK_EQ(0, grmodule->unlock(grmodule, handle)); + } else if (mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) { + ConvertSemiPlanarToPlanar( + source, mConversionBuffer, mWidth, mHeight); - // NOTE: As much as nothing is known about color format - // when it is denoted as AndroidOpaque, it is at least - // assumed to be planar. - if (mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) { - ConvertSemiPlanarToPlanar(source, mConversionBuffer, mWidth, mHeight); source = mConversionBuffer; } vpx_image_t raw_frame; vpx_img_wrap(&raw_frame, VPX_IMG_FMT_I420, mWidth, mHeight, kInputBufferAlignment, source); - codec_return = vpx_codec_encode(mCodecContext, - &raw_frame, - inputBufferHeader->nTimeStamp, // in timebase units - mFrameDurationUs, // frame duration in timebase units - 0, // frame flags - VPX_DL_REALTIME); // encoding deadline + codec_return = vpx_codec_encode( + mCodecContext, + &raw_frame, + inputBufferHeader->nTimeStamp, // in timebase units + mFrameDurationUs, // frame duration in timebase units + 0, // frame flags + VPX_DL_REALTIME); // encoding deadline if (codec_return != VPX_CODEC_OK) { ALOGE("vpx encoder failed to encode frame"); notify(OMX_EventError, @@ -676,6 +790,17 @@ void SoftVPXEncoder::onQueueFilled(OMX_U32 portIndex) { notifyEmptyBufferDone(inputBufferHeader); } } + +OMX_ERRORTYPE SoftVPXEncoder::getExtensionIndex( + const char *name, OMX_INDEXTYPE *index) { + if (!strcmp(name, "OMX.google.android.index.storeMetaDataInBuffers")) { + *index = OMX_IndexVendorStartUnused; + return OMX_ErrorNone; + } + + return SimpleSoftOMXComponent::getExtensionIndex(name, index); +} + } // namespace android diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h index a0a8ee6..d570154 100644 --- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h +++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h @@ -23,6 +23,8 @@ #include <OMX_VideoExt.h> #include <OMX_IndexExt.h> +#include <hardware/gralloc.h> + #include "vpx/vpx_encoder.h" #include "vpx/vpx_codec.h" #include "vpx/vp8cx.h" @@ -57,14 +59,13 @@ namespace android { // - OMX timestamps are in microseconds, therefore // encoder timebase is fixed to 1/1000000 -class SoftVPXEncoder : public SimpleSoftOMXComponent { - public: +struct SoftVPXEncoder : public SimpleSoftOMXComponent { SoftVPXEncoder(const char *name, const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData, OMX_COMPONENTTYPE **component); - protected: +protected: virtual ~SoftVPXEncoder(); // Returns current values for requested OMX @@ -83,7 +84,10 @@ class SoftVPXEncoder : public SimpleSoftOMXComponent { // encoding of the frame virtual void onQueueFilled(OMX_U32 portIndex); - private: + virtual OMX_ERRORTYPE getExtensionIndex( + const char *name, OMX_INDEXTYPE *index); + +private: // number of buffers allocated per port static const uint32_t kNumBuffers = 4; @@ -156,6 +160,9 @@ class SoftVPXEncoder : public SimpleSoftOMXComponent { // indeed YUV420SemiPlanar. uint8_t* mConversionBuffer; + bool mInputDataIsMeta; + const hw_module_t *mGrallocModule; + // Initializes input and output OMX ports with sensible // default values. void initPorts(); |