diff options
Diffstat (limited to 'media/libstagefright')
-rw-r--r-- | media/libstagefright/ACodec.cpp | 1 | ||||
-rw-r--r-- | media/libstagefright/Android.mk | 3 | ||||
-rw-r--r-- | media/libstagefright/MPEG4Extractor.cpp | 26 | ||||
-rw-r--r-- | media/libstagefright/MediaCodec.cpp | 15 | ||||
-rw-r--r-- | media/libstagefright/OMXCodec.cpp | 1 | ||||
-rw-r--r-- | media/libstagefright/StagefrightMetadataRetriever.cpp | 59 | ||||
-rw-r--r-- | media/libstagefright/TimedEventQueue.cpp | 4 | ||||
-rw-r--r-- | media/libstagefright/codecs/on2/dec/SoftVPX.cpp | 107 | ||||
-rw-r--r-- | media/libstagefright/codecs/on2/dec/SoftVPX.h | 6 | ||||
-rw-r--r-- | media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp | 81 | ||||
-rw-r--r-- | media/libstagefright/codecs/on2/h264dec/SoftAVC.h | 5 | ||||
-rw-r--r-- | media/libstagefright/foundation/ALooper.cpp | 8 | ||||
-rw-r--r-- | media/libstagefright/foundation/ALooperRoster.cpp | 41 | ||||
-rw-r--r-- | media/libstagefright/foundation/AMessage.cpp | 123 | ||||
-rw-r--r-- | media/libstagefright/httplive/PlaylistFetcher.cpp | 10 | ||||
-rw-r--r-- | media/libstagefright/include/SoftVideoDecoderOMXComponent.h | 9 | ||||
-rw-r--r-- | media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp | 79 |
17 files changed, 354 insertions, 224 deletions
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index 19a5908..9b03b71 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -2313,7 +2313,6 @@ static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) { return 0; } OMX_U32 ret = frameRate * iFramesInterval; - CHECK(ret > 1); return ret; } diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk index be9af5e..193f8a7 100644 --- a/media/libstagefright/Android.mk +++ b/media/libstagefright/Android.mk @@ -62,6 +62,7 @@ LOCAL_SRC_FILES:= \ avc_utils.cpp \ LOCAL_C_INCLUDES:= \ + $(TOP)/frameworks/av/include/media/ \ $(TOP)/frameworks/av/include/media/stagefright/timedtext \ $(TOP)/frameworks/native/include/media/hardware \ $(TOP)/frameworks/native/include/media/openmax \ @@ -70,6 +71,8 @@ LOCAL_C_INCLUDES:= \ $(TOP)/external/openssl/include \ $(TOP)/external/libvpx/libwebm \ $(TOP)/system/netd/include \ + $(TOP)/external/icu/icu4c/source/common \ + $(TOP)/external/icu/icu4c/source/i18n \ LOCAL_SHARED_LIBRARIES := \ libbinder \ diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index 0064293..1729f93 100644 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -2810,7 +2810,6 @@ status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( { if (objectType == AOT_SBR || objectType == AOT_PS) { - const int32_t extensionSamplingFrequency = br.getBits(4); objectType = br.getBits(5); if (objectType == AOT_ESCAPE) { @@ -2828,9 +2827,30 @@ status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( const int32_t coreCoderDelay = br.getBits(14); } - const int32_t extensionFlag = br.getBits(1); + int32_t extensionFlag = -1; + if (br.numBitsLeft() > 0) { + extensionFlag = br.getBits(1); + } else { + switch (objectType) { + // 14496-3 4.5.1.1 extensionFlag + case AOT_AAC_LC: + extensionFlag = 0; + break; + case AOT_ER_AAC_LC: + case AOT_ER_AAC_SCAL: + case AOT_ER_BSAC: + case AOT_ER_AAC_LD: + extensionFlag = 1; + break; + default: + TRESPASS(); + break; + } + ALOGW("csd missing extension flag; assuming %d for object type %u.", + extensionFlag, objectType); + } - if (numChannels == 0 ) { + if (numChannels == 0) { int32_t channelsEffectiveNum = 0; int32_t channelsNum = 0; const int32_t ElementInstanceTag = br.getBits(4); diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index fc2dd30..0bfc6e4 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -270,7 +270,20 @@ status_t MediaCodec::configure( } sp<AMessage> response; - return PostAndAwaitResponse(msg, &response); + status_t err = PostAndAwaitResponse(msg, &response); + + if (err != OK && err != INVALID_OPERATION) { + // MediaCodec now set state to UNINITIALIZED upon any fatal error. + // To maintain backward-compatibility, do a reset() to put codec + // back into INITIALIZED state. + // But don't reset if the err is INVALID_OPERATION, which means + // the configure failure is due to wrong state. + + ALOGE("configure failed with err 0x%08x, resetting...", err); + reset(); + } + + return err; } status_t MediaCodec::createInputSurface( diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index 78758da..a8806c8 100644 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -994,7 +994,6 @@ static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) { return 0; } OMX_U32 ret = frameRate * iFramesInterval - 1; - CHECK(ret > 1); return ret; } diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp index 8cc41e7..101fc8a 100644 --- a/media/libstagefright/StagefrightMetadataRetriever.cpp +++ b/media/libstagefright/StagefrightMetadataRetriever.cpp @@ -32,6 +32,7 @@ #include <media/stagefright/MetaData.h> #include <media/stagefright/OMXCodec.h> #include <media/stagefright/MediaDefs.h> +#include <CharacterEncodingDetector.h> namespace android { @@ -450,32 +451,58 @@ void StagefrightMetadataRetriever::parseMetaData() { struct Map { int from; int to; + const char *name; }; static const Map kMap[] = { - { kKeyMIMEType, METADATA_KEY_MIMETYPE }, - { kKeyCDTrackNumber, METADATA_KEY_CD_TRACK_NUMBER }, - { kKeyDiscNumber, METADATA_KEY_DISC_NUMBER }, - { kKeyAlbum, METADATA_KEY_ALBUM }, - { kKeyArtist, METADATA_KEY_ARTIST }, - { kKeyAlbumArtist, METADATA_KEY_ALBUMARTIST }, - { kKeyAuthor, METADATA_KEY_AUTHOR }, - { kKeyComposer, METADATA_KEY_COMPOSER }, - { kKeyDate, METADATA_KEY_DATE }, - { kKeyGenre, METADATA_KEY_GENRE }, - { kKeyTitle, METADATA_KEY_TITLE }, - { kKeyYear, METADATA_KEY_YEAR }, - { kKeyWriter, METADATA_KEY_WRITER }, - { kKeyCompilation, METADATA_KEY_COMPILATION }, - { kKeyLocation, METADATA_KEY_LOCATION }, + { kKeyMIMEType, METADATA_KEY_MIMETYPE, NULL }, + { kKeyCDTrackNumber, METADATA_KEY_CD_TRACK_NUMBER, "tracknumber" }, + { kKeyDiscNumber, METADATA_KEY_DISC_NUMBER, "discnumber" }, + { kKeyAlbum, METADATA_KEY_ALBUM, "album" }, + { kKeyArtist, METADATA_KEY_ARTIST, "artist" }, + { kKeyAlbumArtist, METADATA_KEY_ALBUMARTIST, "albumartist" }, + { kKeyAuthor, METADATA_KEY_AUTHOR, NULL }, + { kKeyComposer, METADATA_KEY_COMPOSER, "composer" }, + { kKeyDate, METADATA_KEY_DATE, NULL }, + { kKeyGenre, METADATA_KEY_GENRE, "genre" }, + { kKeyTitle, METADATA_KEY_TITLE, "title" }, + { kKeyYear, METADATA_KEY_YEAR, "year" }, + { kKeyWriter, METADATA_KEY_WRITER, "writer" }, + { kKeyCompilation, METADATA_KEY_COMPILATION, "compilation" }, + { kKeyLocation, METADATA_KEY_LOCATION, NULL }, }; + static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]); + CharacterEncodingDetector *detector = new CharacterEncodingDetector(); + for (size_t i = 0; i < kNumMapEntries; ++i) { const char *value; if (meta->findCString(kMap[i].from, &value)) { - mMetaData.add(kMap[i].to, String8(value)); + if (kMap[i].name) { + // add to charset detector + detector->addTag(kMap[i].name, value); + } else { + // directly add to output list + mMetaData.add(kMap[i].to, String8(value)); + } + } + } + + detector->detectAndConvert(); + int size = detector->size(); + if (size) { + for (int i = 0; i < size; i++) { + const char *name; + const char *value; + detector->getTag(i, &name, &value); + for (size_t j = 0; j < kNumMapEntries; ++j) { + if (kMap[j].name && !strcmp(kMap[j].name, name)) { + mMetaData.add(kMap[j].to, String8(value)); + } + } } } + delete detector; const void *data; uint32_t type; diff --git a/media/libstagefright/TimedEventQueue.cpp b/media/libstagefright/TimedEventQueue.cpp index da50c56..1fdb244 100644 --- a/media/libstagefright/TimedEventQueue.cpp +++ b/media/libstagefright/TimedEventQueue.cpp @@ -338,7 +338,7 @@ void TimedEventQueue::acquireWakeLock_l() status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK, binder, String16("TimedEventQueue"), - String16("media")); + String16("media")); // not oneway IPCThreadState::self()->restoreCallingIdentity(token); if (status == NO_ERROR) { mWakeLockToken = binder; @@ -363,7 +363,7 @@ void TimedEventQueue::releaseWakeLock_l(bool force) CHECK(mWakeLockToken != 0); if (mPowerManager != 0) { int64_t token = IPCThreadState::self()->clearCallingIdentity(); - mPowerManager->releaseWakeLock(mWakeLockToken, 0); + mPowerManager->releaseWakeLock(mWakeLockToken, 0); // not oneway IPCThreadState::self()->restoreCallingIdentity(token); } mWakeLockToken.clear(); diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp index a4258dd..828577a 100644 --- a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp +++ b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp @@ -23,9 +23,6 @@ #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/MediaDefs.h> -#include "vpx/vpx_decoder.h" -#include "vpx/vpx_codec.h" -#include "vpx/vp8dx.h" namespace android { @@ -41,7 +38,8 @@ SoftVPX::SoftVPX( NULL /* profileLevels */, 0 /* numProfileLevels */, 320 /* width */, 240 /* height */, callbacks, appData, component), mMode(codingType == OMX_VIDEO_CodingVP8 ? MODE_VP8 : MODE_VP9), - mCtx(NULL) { + mCtx(NULL), + mImg(NULL) { initPorts(kNumBuffers, 768 * 1024 /* inputBufferSize */, kNumBuffers, codingType == OMX_VIDEO_CodingVP8 ? MEDIA_MIMETYPE_VIDEO_VP8 : MEDIA_MIMETYPE_VIDEO_VP9); @@ -118,49 +116,31 @@ void SoftVPX::onQueueFilled(OMX_U32 /* portIndex */) { } } - if (vpx_codec_decode( - (vpx_codec_ctx_t *)mCtx, - inHeader->pBuffer + inHeader->nOffset, - inHeader->nFilledLen, - NULL, - 0)) { - ALOGE("on2 decoder failed to decode frame."); + if (mImg == NULL) { + if (vpx_codec_decode( + (vpx_codec_ctx_t *)mCtx, + inHeader->pBuffer + inHeader->nOffset, + inHeader->nFilledLen, + NULL, + 0)) { + ALOGE("on2 decoder failed to decode frame."); - notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); - return; + notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); + return; + } + vpx_codec_iter_t iter = NULL; + mImg = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter); } - vpx_codec_iter_t iter = NULL; - vpx_image_t *img = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter); - - if (img != NULL) { - CHECK_EQ(img->fmt, IMG_FMT_I420); - - uint32_t width = img->d_w; - uint32_t height = img->d_h; - - if (width != mWidth || height != mHeight) { - mWidth = width; - mHeight = height; - - if (!mIsAdaptive || width > mAdaptiveMaxWidth || height > mAdaptiveMaxHeight) { - if (mIsAdaptive) { - if (width > mAdaptiveMaxWidth) { - mAdaptiveMaxWidth = width; - } - if (height > mAdaptiveMaxHeight) { - mAdaptiveMaxHeight = height; - } - } - updatePortDefinitions(); - notify(OMX_EventPortSettingsChanged, kOutputPortIndex, 0, NULL); - mOutputPortSettingsChange = AWAITING_DISABLED; - return; - } else { - updatePortDefinitions(); - notify(OMX_EventPortSettingsChanged, kOutputPortIndex, - OMX_IndexConfigCommonOutputCrop, NULL); - } + if (mImg != NULL) { + CHECK_EQ(mImg->fmt, IMG_FMT_I420); + + uint32_t width = mImg->d_w; + uint32_t height = mImg->d_h; + bool portWillReset = false; + handlePortSettingsChange(&portWillReset, width, height); + if (portWillReset) { + return; } outHeader->nOffset = 0; @@ -168,37 +148,16 @@ void SoftVPX::onQueueFilled(OMX_U32 /* portIndex */) { outHeader->nFlags = EOSseen ? OMX_BUFFERFLAG_EOS : 0; outHeader->nTimeStamp = inHeader->nTimeStamp; - uint32_t buffer_stride = mIsAdaptive ? mAdaptiveMaxWidth : mWidth; - uint32_t buffer_height = mIsAdaptive ? mAdaptiveMaxHeight : mHeight; - - const uint8_t *srcLine = (const uint8_t *)img->planes[PLANE_Y]; uint8_t *dst = outHeader->pBuffer; - for (size_t i = 0; i < buffer_height; ++i) { - if (i < img->d_h) { - memcpy(dst, srcLine, img->d_w); - srcLine += img->stride[PLANE_Y]; - } - dst += buffer_stride; - } - - srcLine = (const uint8_t *)img->planes[PLANE_U]; - for (size_t i = 0; i < buffer_height / 2; ++i) { - if (i < img->d_h / 2) { - memcpy(dst, srcLine, img->d_w / 2); - srcLine += img->stride[PLANE_U]; - } - dst += buffer_stride / 2; - } - - srcLine = (const uint8_t *)img->planes[PLANE_V]; - for (size_t i = 0; i < buffer_height / 2; ++i) { - if (i < img->d_h / 2) { - memcpy(dst, srcLine, img->d_w / 2); - srcLine += img->stride[PLANE_V]; - } - dst += buffer_stride / 2; - } - + const uint8_t *srcY = (const uint8_t *)mImg->planes[PLANE_Y]; + const uint8_t *srcU = (const uint8_t *)mImg->planes[PLANE_U]; + const uint8_t *srcV = (const uint8_t *)mImg->planes[PLANE_V]; + size_t srcYStride = mImg->stride[PLANE_Y]; + size_t srcUStride = mImg->stride[PLANE_U]; + size_t srcVStride = mImg->stride[PLANE_V]; + copyYV12FrameToOutputBuffer(dst, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride); + + mImg = NULL; outInfo->mOwnedByUs = false; outQueue.erase(outQueue.begin()); outInfo = NULL; diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.h b/media/libstagefright/codecs/on2/dec/SoftVPX.h index cd5eb28..8f68693 100644 --- a/media/libstagefright/codecs/on2/dec/SoftVPX.h +++ b/media/libstagefright/codecs/on2/dec/SoftVPX.h @@ -20,6 +20,10 @@ #include "SoftVideoDecoderOMXComponent.h" +#include "vpx/vpx_decoder.h" +#include "vpx/vpx_codec.h" +#include "vpx/vp8dx.h" + namespace android { struct SoftVPX : public SoftVideoDecoderOMXComponent { @@ -47,6 +51,8 @@ private: void *mCtx; + vpx_image_t *mImg; + status_t initDecoder(); DISALLOW_EVIL_CONSTRUCTORS(SoftVPX); diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp index a7bde97..cf3c3e3 100644 --- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp +++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp @@ -58,7 +58,6 @@ SoftAVC::SoftAVC( 320 /* width */, 240 /* height */, callbacks, appData, component), mHandle(NULL), mInputBufferCount(0), - mPictureSize(mWidth * mHeight * 3 / 2), mFirstPicture(NULL), mFirstPictureId(-1), mPicId(0), @@ -118,7 +117,7 @@ void SoftAVC::onQueueFilled(OMX_U32 /* portIndex */) { } H264SwDecRet ret = H264SWDEC_PIC_RDY; - bool portSettingsChanged = false; + bool portWillReset = false; while ((mEOSStatus != INPUT_DATA_AVAILABLE || !inQueue.empty()) && outQueue.size() == kNumOutputBuffers) { @@ -161,17 +160,13 @@ void SoftAVC::onQueueFilled(OMX_U32 /* portIndex */) { H264SwDecInfo decoderInfo; CHECK(H264SwDecGetInfo(mHandle, &decoderInfo) == H264SWDEC_OK); - if (handlePortSettingChangeEvent(&decoderInfo)) { - portSettingsChanged = true; - } - - if (decoderInfo.croppingFlag && - handleCropRectEvent(&decoderInfo.cropParams)) { - portSettingsChanged = true; - } + bool cropChanged = handleCropChange(decoderInfo); + handlePortSettingsChange( + &portWillReset, decoderInfo.picWidth, decoderInfo.picHeight, + cropChanged); } } else { - if (portSettingsChanged) { + if (portWillReset) { if (H264SwDecNextPicture(mHandle, &decodedPicture, 0) == H264SWDEC_PIC_RDY) { @@ -199,8 +194,7 @@ void SoftAVC::onQueueFilled(OMX_U32 /* portIndex */) { inInfo->mOwnedByUs = false; notifyEmptyBufferDone(inHeader); - if (portSettingsChanged) { - portSettingsChanged = false; + if (portWillReset) { return; } @@ -215,44 +209,33 @@ void SoftAVC::onQueueFilled(OMX_U32 /* portIndex */) { } } -bool SoftAVC::handlePortSettingChangeEvent(const H264SwDecInfo *info) { - if (mWidth != info->picWidth || mHeight != info->picHeight) { - mWidth = info->picWidth; - mHeight = info->picHeight; - mPictureSize = mWidth * mHeight * 3 / 2; - updatePortDefinitions(); - notify(OMX_EventPortSettingsChanged, 1, 0, NULL); - mOutputPortSettingsChange = AWAITING_DISABLED; - return true; +bool SoftAVC::handleCropChange(const H264SwDecInfo& decInfo) { + if (!decInfo.croppingFlag) { + return false; } - return false; -} - -bool SoftAVC::handleCropRectEvent(const CropParams *crop) { - if (mCropLeft != crop->cropLeftOffset || - mCropTop != crop->cropTopOffset || - mCropWidth != crop->cropOutWidth || - mCropHeight != crop->cropOutHeight) { - mCropLeft = crop->cropLeftOffset; - mCropTop = crop->cropTopOffset; - mCropWidth = crop->cropOutWidth; - mCropHeight = crop->cropOutHeight; - - notify(OMX_EventPortSettingsChanged, 1, - OMX_IndexConfigCommonOutputCrop, NULL); - - return true; + const CropParams& crop = decInfo.cropParams; + if (mCropLeft == crop.cropLeftOffset && + mCropTop == crop.cropTopOffset && + mCropWidth == crop.cropOutWidth && + mCropHeight == crop.cropOutHeight) { + return false; } - return false; + + mCropLeft = crop.cropLeftOffset; + mCropTop = crop.cropTopOffset; + mCropWidth = crop.cropOutWidth; + mCropHeight = crop.cropOutHeight; + return true; } void SoftAVC::saveFirstOutputBuffer(int32_t picId, uint8_t *data) { CHECK(mFirstPicture == NULL); mFirstPictureId = picId; - mFirstPicture = new uint8_t[mPictureSize]; - memcpy(mFirstPicture, data, mPictureSize); + uint32_t pictureSize = mWidth * mHeight * 3 / 2; + mFirstPicture = new uint8_t[pictureSize]; + memcpy(mFirstPicture, data, pictureSize); } void SoftAVC::drainOneOutputBuffer(int32_t picId, uint8_t* data) { @@ -263,9 +246,17 @@ void SoftAVC::drainOneOutputBuffer(int32_t picId, uint8_t* data) { OMX_BUFFERHEADERTYPE *header = mPicToHeaderMap.valueFor(picId); outHeader->nTimeStamp = header->nTimeStamp; outHeader->nFlags = header->nFlags; - outHeader->nFilledLen = mPictureSize; - memcpy(outHeader->pBuffer + outHeader->nOffset, - data, mPictureSize); + outHeader->nFilledLen = mWidth * mHeight * 3 / 2; + + uint8_t *dst = outHeader->pBuffer + outHeader->nOffset; + const uint8_t *srcY = data; + const uint8_t *srcU = srcY + mWidth * mHeight; + const uint8_t *srcV = srcU + mWidth * mHeight / 4; + size_t srcYStride = mWidth; + size_t srcUStride = mWidth / 2; + size_t srcVStride = srcUStride; + copyYV12FrameToOutputBuffer(dst, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride); + mPicToHeaderMap.removeItem(picId); delete header; outInfo->mOwnedByUs = false; diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.h b/media/libstagefright/codecs/on2/h264dec/SoftAVC.h index ee69926..253a406 100644 --- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.h +++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.h @@ -55,8 +55,6 @@ private: size_t mInputBufferCount; - uint32_t mPictureSize; - uint8_t *mFirstPicture; int32_t mFirstPictureId; @@ -75,8 +73,7 @@ private: void drainAllOutputBuffers(bool eos); void drainOneOutputBuffer(int32_t picId, uint8_t *data); void saveFirstOutputBuffer(int32_t pidId, uint8_t *data); - bool handleCropRectEvent(const CropParams* crop); - bool handlePortSettingChangeEvent(const H264SwDecInfo *info); + bool handleCropChange(const H264SwDecInfo& decInfo); DISALLOW_EVIL_CONSTRUCTORS(SoftAVC); }; diff --git a/media/libstagefright/foundation/ALooper.cpp b/media/libstagefright/foundation/ALooper.cpp index ebf9d8d..88b1c92 100644 --- a/media/libstagefright/foundation/ALooper.cpp +++ b/media/libstagefright/foundation/ALooper.cpp @@ -68,14 +68,14 @@ int64_t ALooper::GetNowUs() { ALooper::ALooper() : mRunningLocally(false) { + // clean up stale AHandlers. Doing it here instead of in the destructor avoids + // the side effect of objects being deleted from the unregister function recursively. + gLooperRoster.unregisterStaleHandlers(); } ALooper::~ALooper() { stop(); - - // Since this looper is "dead" (or as good as dead by now), - // have ALooperRoster unregister any handlers still registered for it. - gLooperRoster.unregisterStaleHandlers(); + // stale AHandlers are now cleaned up in the constructor of the next ALooper to come along } void ALooper::setName(const char *name) { diff --git a/media/libstagefright/foundation/ALooperRoster.cpp b/media/libstagefright/foundation/ALooperRoster.cpp index 0f44b52..e0dc768 100644 --- a/media/libstagefright/foundation/ALooperRoster.cpp +++ b/media/libstagefright/foundation/ALooperRoster.cpp @@ -99,35 +99,13 @@ void ALooperRoster::unregisterStaleHandlers() { status_t ALooperRoster::postMessage( const sp<AMessage> &msg, int64_t delayUs) { - Mutex::Autolock autoLock(mLock); - return postMessage_l(msg, delayUs); -} - -status_t ALooperRoster::postMessage_l( - const sp<AMessage> &msg, int64_t delayUs) { - ssize_t index = mHandlers.indexOfKey(msg->target()); - if (index < 0) { - ALOGW("failed to post message '%s'. Target handler not registered.", - msg->debugString().c_str()); - return -ENOENT; - } - - const HandlerInfo &info = mHandlers.valueAt(index); - - sp<ALooper> looper = info.mLooper.promote(); + sp<ALooper> looper = findLooper(msg->target()); if (looper == NULL) { - ALOGW("failed to post message. " - "Target handler %d still registered, but object gone.", - msg->target()); - - mHandlers.removeItemsAt(index); return -ENOENT; } - looper->post(msg, delayUs); - return OK; } @@ -181,18 +159,23 @@ sp<ALooper> ALooperRoster::findLooper(ALooper::handler_id handlerID) { status_t ALooperRoster::postAndAwaitResponse( const sp<AMessage> &msg, sp<AMessage> *response) { + sp<ALooper> looper = findLooper(msg->target()); + + if (looper == NULL) { + ALOGW("failed to post message. " + "Target handler %d still registered, but object gone.", + msg->target()); + response->clear(); + return -ENOENT; + } + Mutex::Autolock autoLock(mLock); uint32_t replyID = mNextReplyID++; msg->setInt32("replyID", replyID); - status_t err = postMessage_l(msg, 0 /* delayUs */); - - if (err != OK) { - response->clear(); - return err; - } + looper->post(msg, 0 /* delayUs */); ssize_t index; while ((index = mReplies.indexOfKey(replyID)) < 0) { diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp index d268aa4..bc3e3fb 100644 --- a/media/libstagefright/foundation/AMessage.cpp +++ b/media/libstagefright/foundation/AMessage.cpp @@ -14,6 +14,11 @@ * limitations under the License. */ +#define LOG_TAG "AMessage" +//#define LOG_NDEBUG 0 +//#define DUMP_STATS +#include <cutils/log.h> + #include "AMessage.h" #include <ctype.h> @@ -60,12 +65,14 @@ ALooper::handler_id AMessage::target() const { void AMessage::clear() { for (size_t i = 0; i < mNumItems; ++i) { Item *item = &mItems[i]; - freeItem(item); + delete[] item->mName; + item->mName = NULL; + freeItemValue(item); } mNumItems = 0; } -void AMessage::freeItem(Item *item) { +void AMessage::freeItemValue(Item *item) { switch (item->mType) { case kTypeString: { @@ -88,25 +95,85 @@ void AMessage::freeItem(Item *item) { } } -AMessage::Item *AMessage::allocateItem(const char *name) { - name = AAtomizer::Atomize(name); +#ifdef DUMP_STATS +#include <utils/Mutex.h> + +Mutex gLock; +static int32_t gFindItemCalls = 1; +static int32_t gDupCalls = 1; +static int32_t gAverageNumItems = 0; +static int32_t gAverageNumChecks = 0; +static int32_t gAverageNumMemChecks = 0; +static int32_t gAverageDupItems = 0; +static int32_t gLastChecked = -1; + +static void reportStats() { + int32_t time = (ALooper::GetNowUs() / 1000); + if (time / 1000 != gLastChecked / 1000) { + gLastChecked = time; + ALOGI("called findItemIx %zu times (for len=%.1f i=%.1f/%.1f mem) dup %zu times (for len=%.1f)", + gFindItemCalls, + gAverageNumItems / (float)gFindItemCalls, + gAverageNumChecks / (float)gFindItemCalls, + gAverageNumMemChecks / (float)gFindItemCalls, + gDupCalls, + gAverageDupItems / (float)gDupCalls); + gFindItemCalls = gDupCalls = 1; + gAverageNumItems = gAverageNumChecks = gAverageNumMemChecks = gAverageDupItems = 0; + gLastChecked = time; + } +} +#endif +inline size_t AMessage::findItemIndex(const char *name, size_t len) const { +#ifdef DUMP_STATS + size_t memchecks = 0; +#endif size_t i = 0; - while (i < mNumItems && mItems[i].mName != name) { - ++i; + for (; i < mNumItems; i++) { + if (len != mItems[i].mNameLength) { + continue; + } +#ifdef DUMP_STATS + ++memchecks; +#endif + if (!memcmp(mItems[i].mName, name, len)) { + break; + } + } +#ifdef DUMP_STATS + { + Mutex::Autolock _l(gLock); + ++gFindItemCalls; + gAverageNumItems += mNumItems; + gAverageNumMemChecks += memchecks; + gAverageNumChecks += i; + reportStats(); } +#endif + return i; +} + +// assumes item's name was uninitialized or NULL +void AMessage::Item::setName(const char *name, size_t len) { + mNameLength = len; + mName = new char[len + 1]; + memcpy((void*)mName, name, len + 1); +} +AMessage::Item *AMessage::allocateItem(const char *name) { + size_t len = strlen(name); + size_t i = findItemIndex(name, len); Item *item; if (i < mNumItems) { item = &mItems[i]; - freeItem(item); + freeItemValue(item); } else { CHECK(mNumItems < kMaxNumItems); i = mNumItems++; item = &mItems[i]; - - item->mName = name; + item->setName(name, len); } return item; @@ -114,31 +181,18 @@ AMessage::Item *AMessage::allocateItem(const char *name) { const AMessage::Item *AMessage::findItem( const char *name, Type type) const { - name = AAtomizer::Atomize(name); - - for (size_t i = 0; i < mNumItems; ++i) { + size_t i = findItemIndex(name, strlen(name)); + if (i < mNumItems) { const Item *item = &mItems[i]; + return item->mType == type ? item : NULL; - if (item->mName == name) { - return item->mType == type ? item : NULL; - } } - return NULL; } bool AMessage::contains(const char *name) const { - name = AAtomizer::Atomize(name); - - for (size_t i = 0; i < mNumItems; ++i) { - const Item *item = &mItems[i]; - - if (item->mName == name) { - return true; - } - } - - return false; + size_t i = findItemIndex(name, strlen(name)); + return i < mNumItems; } #define BASIC_TYPE(NAME,FIELDNAME,TYPENAME) \ @@ -297,11 +351,20 @@ sp<AMessage> AMessage::dup() const { sp<AMessage> msg = new AMessage(mWhat, mTarget); msg->mNumItems = mNumItems; +#ifdef DUMP_STATS + { + Mutex::Autolock _l(gLock); + ++gDupCalls; + gAverageDupItems += mNumItems; + reportStats(); + } +#endif + for (size_t i = 0; i < mNumItems; ++i) { const Item *from = &mItems[i]; Item *to = &msg->mItems[i]; - to->mName = from->mName; + to->setName(from->mName, from->mNameLength); to->mType = from->mType; switch (from->mType) { @@ -472,11 +535,11 @@ sp<AMessage> AMessage::FromParcel(const Parcel &parcel) { sp<AMessage> msg = new AMessage(what); msg->mNumItems = static_cast<size_t>(parcel.readInt32()); - for (size_t i = 0; i < msg->mNumItems; ++i) { Item *item = &msg->mItems[i]; - item->mName = AAtomizer::Atomize(parcel.readCString()); + const char *name = parcel.readCString(); + item->setName(name, strlen(name)); item->mType = static_cast<Type>(parcel.readInt32()); switch (item->mType) { diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp index 4d5d79e..3ef0f06 100644 --- a/media/libstagefright/httplive/PlaylistFetcher.cpp +++ b/media/libstagefright/httplive/PlaylistFetcher.cpp @@ -490,11 +490,11 @@ status_t PlaylistFetcher::onStart(const sp<AMessage> &msg) { mStreamTypeMask = streamTypeMask; - mStartTimeUs = startTimeUs; mSegmentStartTimeUs = segmentStartTimeUs; mDiscontinuitySeq = startDiscontinuitySeq; - if (mStartTimeUs >= 0ll) { + if (startTimeUs >= 0) { + mStartTimeUs = startTimeUs; mSeqNumber = -1; mStartup = true; mPrepared = false; @@ -737,12 +737,6 @@ void PlaylistFetcher::onDownloadNext() { const int32_t lastSeqNumberInPlaylist = firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1; - if (mStartup && mSeqNumber >= 0 - && (mSeqNumber < firstSeqNumberInPlaylist || mSeqNumber > lastSeqNumberInPlaylist)) { - // in case we guessed wrong during reconfiguration, try fetching the latest content. - mSeqNumber = lastSeqNumberInPlaylist; - } - if (mDiscontinuitySeq < 0) { mDiscontinuitySeq = mPlaylist->getDiscontinuitySeq(); } diff --git a/media/libstagefright/include/SoftVideoDecoderOMXComponent.h b/media/libstagefright/include/SoftVideoDecoderOMXComponent.h index ee553d9..4a6ab63 100644 --- a/media/libstagefright/include/SoftVideoDecoderOMXComponent.h +++ b/media/libstagefright/include/SoftVideoDecoderOMXComponent.h @@ -63,7 +63,14 @@ protected: OMX_U32 numOutputBuffers, const char *mimeType); - virtual void updatePortDefinitions(); + virtual void updatePortDefinitions(bool updateCrop = true); + + void handlePortSettingsChange( + bool *portWillReset, uint32_t width, uint32_t height, bool cropChanged = false); + + void copyYV12FrameToOutputBuffer( + uint8_t *dst, const uint8_t *srcY, const uint8_t *srcU, const uint8_t *srcV, + size_t srcYStride, size_t srcUStride, size_t srcVStride); enum { kInputPortIndex = 0, diff --git a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp index 69b572e..e533fdd 100644 --- a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp +++ b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp @@ -123,13 +123,15 @@ void SoftVideoDecoderOMXComponent::initPorts( updatePortDefinitions(); } -void SoftVideoDecoderOMXComponent::updatePortDefinitions() { +void SoftVideoDecoderOMXComponent::updatePortDefinitions(bool updateCrop) { OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kInputPortIndex)->mDef; def->format.video.nFrameWidth = mWidth; def->format.video.nFrameHeight = mHeight; def->format.video.nStride = def->format.video.nFrameWidth; def->format.video.nSliceHeight = def->format.video.nFrameHeight; + def->nBufferSize = def->format.video.nFrameWidth * def->format.video.nFrameHeight * 3 / 2; + def = &editPortInfo(kOutputPortIndex)->mDef; def->format.video.nFrameWidth = mIsAdaptive ? mAdaptiveMaxWidth : mWidth; def->format.video.nFrameHeight = mIsAdaptive ? mAdaptiveMaxHeight : mHeight; @@ -140,10 +142,77 @@ void SoftVideoDecoderOMXComponent::updatePortDefinitions() { (def->format.video.nFrameWidth * def->format.video.nFrameHeight * 3) / 2; - mCropLeft = 0; - mCropTop = 0; - mCropWidth = mWidth; - mCropHeight = mHeight; + if (updateCrop) { + mCropLeft = 0; + mCropTop = 0; + mCropWidth = mWidth; + mCropHeight = mHeight; + } +} + +void SoftVideoDecoderOMXComponent::handlePortSettingsChange( + bool *portWillReset, uint32_t width, uint32_t height, bool cropChanged) { + *portWillReset = false; + bool sizeChanged = (width != mWidth || height != mHeight); + + if (sizeChanged || cropChanged) { + mWidth = width; + mHeight = height; + + bool updateCrop = !cropChanged; + if ((sizeChanged && !mIsAdaptive) + || width > mAdaptiveMaxWidth + || height > mAdaptiveMaxHeight) { + if (mIsAdaptive) { + if (width > mAdaptiveMaxWidth) { + mAdaptiveMaxWidth = width; + } + if (height > mAdaptiveMaxHeight) { + mAdaptiveMaxHeight = height; + } + } + updatePortDefinitions(updateCrop); + notify(OMX_EventPortSettingsChanged, kOutputPortIndex, 0, NULL); + mOutputPortSettingsChange = AWAITING_DISABLED; + *portWillReset = true; + } else { + updatePortDefinitions(updateCrop); + notify(OMX_EventPortSettingsChanged, kOutputPortIndex, + OMX_IndexConfigCommonOutputCrop, NULL); + } + } +} + +void SoftVideoDecoderOMXComponent::copyYV12FrameToOutputBuffer( + uint8_t *dst, const uint8_t *srcY, const uint8_t *srcU, const uint8_t *srcV, + size_t srcYStride, size_t srcUStride, size_t srcVStride) { + size_t dstYStride = mIsAdaptive ? mAdaptiveMaxWidth : mWidth; + size_t dstUVStride = dstYStride / 2; + size_t dstHeight = mIsAdaptive ? mAdaptiveMaxHeight : mHeight; + + for (size_t i = 0; i < dstHeight; ++i) { + if (i < mHeight) { + memcpy(dst, srcY, mWidth); + srcY += srcYStride; + } + dst += dstYStride; + } + + for (size_t i = 0; i < dstHeight / 2; ++i) { + if (i < mHeight / 2) { + memcpy(dst, srcU, mWidth / 2); + srcU += srcUStride; + } + dst += dstUVStride; + } + + for (size_t i = 0; i < dstHeight / 2; ++i) { + if (i < mHeight / 2) { + memcpy(dst, srcV, mWidth / 2); + srcV += srcVStride; + } + dst += dstUVStride; + } } OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalGetParameter( |