diff options
337 files changed, 5697 insertions, 4260 deletions
diff --git a/camera/Android.mk b/camera/Android.mk index e633450..5cedab0 100644 --- a/camera/Android.mk +++ b/camera/Android.mk @@ -8,6 +8,7 @@ LOCAL_SRC_FILES:= \ Camera.cpp \ CameraMetadata.cpp \ CameraParameters.cpp \ + CameraParameters2.cpp \ ICamera.cpp \ ICameraClient.cpp \ ICameraService.cpp \ diff --git a/camera/CameraBase.cpp b/camera/CameraBase.cpp index 55376b0..04694cd 100644 --- a/camera/CameraBase.cpp +++ b/camera/CameraBase.cpp @@ -49,7 +49,7 @@ namespace { DeathNotifier() { } - virtual void binderDied(const wp<IBinder>& who) { + virtual void binderDied(const wp<IBinder>& /*who*/) { ALOGV("binderDied"); Mutex::Autolock _l(gLock); gCameraService.clear(); @@ -153,7 +153,7 @@ status_t CameraBase<TCam, TCamTraits>::getStatus() } template <typename TCam, typename TCamTraits> -void CameraBase<TCam, TCamTraits>::binderDied(const wp<IBinder>& who) { +void CameraBase<TCam, TCamTraits>::binderDied(const wp<IBinder>& /*who*/) { ALOGW("mediaserver's remote binder Camera object died"); notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, /*ext2*/0); } diff --git a/camera/CameraParameters.cpp b/camera/CameraParameters.cpp index c51f265..78eb4d6 100644 --- a/camera/CameraParameters.cpp +++ b/camera/CameraParameters.cpp @@ -456,7 +456,7 @@ const char *CameraParameters::getPictureFormat() const void CameraParameters::dump() const { - ALOGD("dump: mMap.size = %d", mMap.size()); + ALOGD("dump: mMap.size = %zu", mMap.size()); for (size_t i = 0; i < mMap.size(); i++) { String8 k, v; k = mMap.keyAt(i); @@ -465,12 +465,12 @@ void CameraParameters::dump() const } } -status_t CameraParameters::dump(int fd, const Vector<String16>& args) const +status_t CameraParameters::dump(int fd, const Vector<String16>& /*args*/) const { const size_t SIZE = 256; char buffer[SIZE]; String8 result; - snprintf(buffer, 255, "CameraParameters::dump: mMap.size = %d\n", mMap.size()); + snprintf(buffer, 255, "CameraParameters::dump: mMap.size = %zu\n", mMap.size()); result.append(buffer); for (size_t i = 0; i < mMap.size(); i++) { String8 k, v; diff --git a/camera/CameraParameters2.cpp b/camera/CameraParameters2.cpp new file mode 100644 index 0000000..eac79e1 --- /dev/null +++ b/camera/CameraParameters2.cpp @@ -0,0 +1,381 @@ +/* +** +** Copyright 2008, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#define LOG_TAG "CameraParams2" +// #define LOG_NDEBUG 0 +#include <utils/Log.h> + +#include <string.h> +#include <stdlib.h> +#include <camera/CameraParameters2.h> + +namespace android { + +CameraParameters2::CameraParameters2() + : mMap() +{ +} + +CameraParameters2::~CameraParameters2() +{ +} + +String8 CameraParameters2::flatten() const +{ + String8 flattened(""); + size_t size = mMap.size(); + + for (size_t i = 0; i < size; i++) { + String8 k, v; + k = mMap.keyAt(i); + v = mMap.valueAt(i); + + flattened += k; + flattened += "="; + flattened += v; + if (i != size-1) + flattened += ";"; + } + + ALOGV("%s: Flattened params = %s", __FUNCTION__, flattened.string()); + + return flattened; +} + +void CameraParameters2::unflatten(const String8 ¶ms) +{ + const char *a = params.string(); + const char *b; + + mMap.clear(); + + for (;;) { + // Find the bounds of the key name. + b = strchr(a, '='); + if (b == 0) + break; + + // Create the key string. + String8 k(a, (size_t)(b-a)); + + // Find the value. + a = b+1; + b = strchr(a, ';'); + if (b == 0) { + // If there's no semicolon, this is the last item. + String8 v(a); + mMap.add(k, v); + break; + } + + String8 v(a, (size_t)(b-a)); + mMap.add(k, v); + a = b+1; + } +} + + +void CameraParameters2::set(const char *key, const char *value) +{ + // XXX i think i can do this with strspn() + if (strchr(key, '=') || strchr(key, ';')) { + //XXX ALOGE("Key \"%s\"contains invalid character (= or ;)", key); + return; + } + + if (strchr(value, '=') || strchr(value, ';')) { + //XXX ALOGE("Value \"%s\"contains invalid character (= or ;)", value); + return; + } + + // Replacing a value updates the key's order to be the new largest order + ssize_t res = mMap.replaceValueFor(String8(key), String8(value)); + LOG_ALWAYS_FATAL_IF(res < 0, "replaceValueFor(%s,%s) failed", key, value); +} + +void CameraParameters2::set(const char *key, int value) +{ + char str[16]; + sprintf(str, "%d", value); + set(key, str); +} + +void CameraParameters2::setFloat(const char *key, float value) +{ + char str[16]; // 14 should be enough. We overestimate to be safe. + snprintf(str, sizeof(str), "%g", value); + set(key, str); +} + +const char *CameraParameters2::get(const char *key) const +{ + ssize_t idx = mMap.indexOfKey(String8(key)); + if (idx < 0) { + return NULL; + } else { + return mMap.valueAt(idx).string(); + } +} + +int CameraParameters2::getInt(const char *key) const +{ + const char *v = get(key); + if (v == 0) + return -1; + return strtol(v, 0, 0); +} + +float CameraParameters2::getFloat(const char *key) const +{ + const char *v = get(key); + if (v == 0) return -1; + return strtof(v, 0); +} + +status_t CameraParameters2::compareSetOrder(const char *key1, const char *key2, + int *order) const { + if (key1 == NULL) { + ALOGE("%s: key1 must not be NULL", __FUNCTION__); + return BAD_VALUE; + } else if (key2 == NULL) { + ALOGE("%s: key2 must not be NULL", __FUNCTION__); + return BAD_VALUE; + } else if (order == NULL) { + ALOGE("%s: order must not be NULL", __FUNCTION__); + return BAD_VALUE; + } + + ssize_t index1 = mMap.indexOfKey(String8(key1)); + ssize_t index2 = mMap.indexOfKey(String8(key2)); + if (index1 < 0) { + ALOGW("%s: Key1 (%s) was not set", __FUNCTION__, key1); + return NAME_NOT_FOUND; + } else if (index2 < 0) { + ALOGW("%s: Key2 (%s) was not set", __FUNCTION__, key2); + return NAME_NOT_FOUND; + } + + *order = (index1 == index2) ? 0 : + (index1 < index2) ? -1 : + 1; + + return OK; +} + +void CameraParameters2::remove(const char *key) +{ + mMap.removeItem(String8(key)); +} + +// Parse string like "640x480" or "10000,20000" +static int parse_pair(const char *str, int *first, int *second, char delim, + char **endptr = NULL) +{ + // Find the first integer. + char *end; + int w = (int)strtol(str, &end, 10); + // If a delimeter does not immediately follow, give up. + if (*end != delim) { + ALOGE("Cannot find delimeter (%c) in str=%s", delim, str); + return -1; + } + + // Find the second integer, immediately after the delimeter. + int h = (int)strtol(end+1, &end, 10); + + *first = w; + *second = h; + + if (endptr) { + *endptr = end; + } + + return 0; +} + +static void parseSizesList(const char *sizesStr, Vector<Size> &sizes) +{ + if (sizesStr == 0) { + return; + } + + char *sizeStartPtr = (char *)sizesStr; + + while (true) { + int width, height; + int success = parse_pair(sizeStartPtr, &width, &height, 'x', + &sizeStartPtr); + if (success == -1 || (*sizeStartPtr != ',' && *sizeStartPtr != '\0')) { + ALOGE("Picture sizes string \"%s\" contains invalid character.", sizesStr); + return; + } + sizes.push(Size(width, height)); + + if (*sizeStartPtr == '\0') { + return; + } + sizeStartPtr++; + } +} + +void CameraParameters2::setPreviewSize(int width, int height) +{ + char str[32]; + sprintf(str, "%dx%d", width, height); + set(CameraParameters::KEY_PREVIEW_SIZE, str); +} + +void CameraParameters2::getPreviewSize(int *width, int *height) const +{ + *width = *height = -1; + // Get the current string, if it doesn't exist, leave the -1x-1 + const char *p = get(CameraParameters::KEY_PREVIEW_SIZE); + if (p == 0) return; + parse_pair(p, width, height, 'x'); +} + +void CameraParameters2::getPreferredPreviewSizeForVideo(int *width, int *height) const +{ + *width = *height = -1; + const char *p = get(CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO); + if (p == 0) return; + parse_pair(p, width, height, 'x'); +} + +void CameraParameters2::getSupportedPreviewSizes(Vector<Size> &sizes) const +{ + const char *previewSizesStr = get(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES); + parseSizesList(previewSizesStr, sizes); +} + +void CameraParameters2::setVideoSize(int width, int height) +{ + char str[32]; + sprintf(str, "%dx%d", width, height); + set(CameraParameters::KEY_VIDEO_SIZE, str); +} + +void CameraParameters2::getVideoSize(int *width, int *height) const +{ + *width = *height = -1; + const char *p = get(CameraParameters::KEY_VIDEO_SIZE); + if (p == 0) return; + parse_pair(p, width, height, 'x'); +} + +void CameraParameters2::getSupportedVideoSizes(Vector<Size> &sizes) const +{ + const char *videoSizesStr = get(CameraParameters::KEY_SUPPORTED_VIDEO_SIZES); + parseSizesList(videoSizesStr, sizes); +} + +void CameraParameters2::setPreviewFrameRate(int fps) +{ + set(CameraParameters::KEY_PREVIEW_FRAME_RATE, fps); +} + +int CameraParameters2::getPreviewFrameRate() const +{ + return getInt(CameraParameters::KEY_PREVIEW_FRAME_RATE); +} + +void CameraParameters2::getPreviewFpsRange(int *min_fps, int *max_fps) const +{ + *min_fps = *max_fps = -1; + const char *p = get(CameraParameters::KEY_PREVIEW_FPS_RANGE); + if (p == 0) return; + parse_pair(p, min_fps, max_fps, ','); +} + +void CameraParameters2::setPreviewFpsRange(int min_fps, int max_fps) +{ + String8 str = String8::format("%d,%d", min_fps, max_fps); + set(CameraParameters::KEY_PREVIEW_FPS_RANGE, str.string()); +} + +void CameraParameters2::setPreviewFormat(const char *format) +{ + set(CameraParameters::KEY_PREVIEW_FORMAT, format); +} + +const char *CameraParameters2::getPreviewFormat() const +{ + return get(CameraParameters::KEY_PREVIEW_FORMAT); +} + +void CameraParameters2::setPictureSize(int width, int height) +{ + char str[32]; + sprintf(str, "%dx%d", width, height); + set(CameraParameters::KEY_PICTURE_SIZE, str); +} + +void CameraParameters2::getPictureSize(int *width, int *height) const +{ + *width = *height = -1; + // Get the current string, if it doesn't exist, leave the -1x-1 + const char *p = get(CameraParameters::KEY_PICTURE_SIZE); + if (p == 0) return; + parse_pair(p, width, height, 'x'); +} + +void CameraParameters2::getSupportedPictureSizes(Vector<Size> &sizes) const +{ + const char *pictureSizesStr = get(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES); + parseSizesList(pictureSizesStr, sizes); +} + +void CameraParameters2::setPictureFormat(const char *format) +{ + set(CameraParameters::KEY_PICTURE_FORMAT, format); +} + +const char *CameraParameters2::getPictureFormat() const +{ + return get(CameraParameters::KEY_PICTURE_FORMAT); +} + +void CameraParameters2::dump() const +{ + ALOGD("dump: mMap.size = %d", mMap.size()); + for (size_t i = 0; i < mMap.size(); i++) { + String8 k, v; + k = mMap.keyAt(i); + v = mMap.valueAt(i); + ALOGD("%s: %s\n", k.string(), v.string()); + } +} + +status_t CameraParameters2::dump(int fd, const Vector<String16>& args) const +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + snprintf(buffer, 255, "CameraParameters2::dump: mMap.size = %zu\n", mMap.size()); + result.append(buffer); + for (size_t i = 0; i < mMap.size(); i++) { + String8 k, v; + k = mMap.keyAt(i); + v = mMap.valueAt(i); + snprintf(buffer, 255, "\t%s: %s\n", k.string(), v.string()); + result.append(buffer); + } + write(fd, result.string(), result.size()); + return NO_ERROR; +} + +}; // namespace android diff --git a/cmds/screenrecord/Overlay.cpp b/cmds/screenrecord/Overlay.cpp index 96e25b8..35be221 100644 --- a/cmds/screenrecord/Overlay.cpp +++ b/cmds/screenrecord/Overlay.cpp @@ -47,7 +47,7 @@ const char* Overlay::kPropertyNames[] = { "ro.revision", "dalvik.vm.heapgrowthlimit", "dalvik.vm.heapsize", - "persist.sys.dalvik.vm.lib", + "persist.sys.dalvik.vm.lib.2", //"ro.product.cpu.abi", //"ro.bootloader", //"this-never-appears!", diff --git a/cmds/stagefright/codec.cpp b/cmds/stagefright/codec.cpp index fdfefdf..d125ad1 100644 --- a/cmds/stagefright/codec.cpp +++ b/cmds/stagefright/codec.cpp @@ -16,6 +16,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "codec" +#include <inttypes.h> #include <utils/Log.h> #include "SimplePlayer.h" @@ -291,13 +292,13 @@ static int decode( CHECK_EQ((status_t)OK, state->mCodec->release()); if (state->mIsAudio) { - printf("track %d: %lld bytes received. %.2f KB/sec\n", + printf("track %zu: %" PRId64 " bytes received. %.2f KB/sec\n", i, state->mNumBytesDecoded, state->mNumBytesDecoded * 1E6 / 1024 / elapsedTimeUs); } else { - printf("track %d: %lld frames decoded, %.2f fps. %lld bytes " - "received. %.2f KB/sec\n", + printf("track %zu: %" PRId64 " frames decoded, %.2f fps. %" PRId64 + " bytes received. %.2f KB/sec\n", i, state->mNumBuffersDecoded, state->mNumBuffersDecoded * 1E6 / elapsedTimeUs, diff --git a/cmds/stagefright/muxer.cpp b/cmds/stagefright/muxer.cpp index cca33e0..90daea2 100644 --- a/cmds/stagefright/muxer.cpp +++ b/cmds/stagefright/muxer.cpp @@ -16,6 +16,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "muxer" +#include <inttypes.h> #include <utils/Log.h> #include <binder/ProcessState.h> @@ -198,7 +199,7 @@ static int muxing( trackIndexMap.clear(); int64_t elapsedTimeUs = ALooper::GetNowUs() - muxerStartTimeUs; - fprintf(stderr, "SUCCESS: muxer generate the video in %lld ms\n", + fprintf(stderr, "SUCCESS: muxer generate the video in %" PRId64 " ms\n", elapsedTimeUs / 1000); return 0; diff --git a/cmds/stagefright/recordvideo.cpp b/cmds/stagefright/recordvideo.cpp index c30c122..1d267f9 100644 --- a/cmds/stagefright/recordvideo.cpp +++ b/cmds/stagefright/recordvideo.cpp @@ -16,6 +16,7 @@ #include "SineSource.h" +#include <inttypes.h> #include <binder/ProcessState.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/AudioPlayer.h> @@ -312,7 +313,7 @@ int main(int argc, char **argv) { fprintf(stderr, "record failed: %d\n", err); return 1; } - fprintf(stderr, "encoding %d frames in %lld us\n", nFrames, (end-start)/1000); + fprintf(stderr, "encoding %d frames in %" PRId64 " us\n", nFrames, (end-start)/1000); fprintf(stderr, "encoding speed is: %.2f fps\n", (nFrames * 1E9) / (end-start)); return 0; } diff --git a/cmds/stagefright/sf2.cpp b/cmds/stagefright/sf2.cpp index c817443..b2b9ce5 100644 --- a/cmds/stagefright/sf2.cpp +++ b/cmds/stagefright/sf2.cpp @@ -16,6 +16,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "sf2" +#include <inttypes.h> #include <utils/Log.h> #include <binder/ProcessState.h> @@ -183,11 +184,11 @@ protected: int64_t delayUs = ALooper::GetNowUs() - mStartTimeUs; if (mDecodeAudio) { - printf("%lld bytes received. %.2f KB/sec\n", + printf("%" PRId64 " bytes received. %.2f KB/sec\n", mTotalBytesReceived, mTotalBytesReceived * 1E6 / 1024 / delayUs); } else { - printf("%d frames decoded, %.2f fps. %lld bytes " + printf("%d frames decoded, %.2f fps. %" PRId64 " bytes " "received. %.2f KB/sec\n", mNumOutputBuffersReceived, mNumOutputBuffersReceived * 1E6 / delayUs, diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp index 030bf1b..ab2c54b 100644 --- a/cmds/stagefright/stagefright.cpp +++ b/cmds/stagefright/stagefright.cpp @@ -14,15 +14,16 @@ * limitations under the License. */ +#include <inttypes.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <sys/time.h> + //#define LOG_NDEBUG 0 #define LOG_TAG "stagefright" #include <media/stagefright/foundation/ADebug.h> -#include <sys/time.h> - -#include <stdlib.h> -#include <string.h> - #include "jpeg.h" #include "SineSource.h" @@ -49,8 +50,6 @@ #include <private/media/VideoFrame.h> -#include <fcntl.h> - #include <gui/GLConsumer.h> #include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> @@ -89,8 +88,8 @@ static void displayDecodeHistogram(Vector<int64_t> *decodeTimesUs) { int64_t minUs = decodeTimesUs->itemAt(0); int64_t maxUs = decodeTimesUs->itemAt(n - 1); - printf("min decode time %lld us (%.2f secs)\n", minUs, minUs / 1E6); - printf("max decode time %lld us (%.2f secs)\n", maxUs, maxUs / 1E6); + printf("min decode time %" PRId64 " us (%.2f secs)\n", minUs, minUs / 1E6); + printf("max decode time %" PRId64 " us (%.2f secs)\n", maxUs, maxUs / 1E6); size_t counts[100]; for (size_t i = 0; i < 100; ++i) { @@ -110,7 +109,7 @@ static void displayDecodeHistogram(Vector<int64_t> *decodeTimesUs) { int64_t slotUs = minUs + (i * (maxUs - minUs) / 100); double fps = 1E6 / slotUs; - printf("[%.2f fps]: %d\n", fps, counts[i]); + printf("[%.2f fps]: %zu\n", fps, counts[i]); } } @@ -262,7 +261,7 @@ static void playSource(OMXClient *client, sp<MediaSource> &source) { } } - printf("buffer has timestamp %lld us (%.2f secs)\n", + printf("buffer has timestamp %" PRId64 " us (%.2f secs)\n", timestampUs, timestampUs / 1E6); buffer->release(); @@ -285,7 +284,7 @@ static void playSource(OMXClient *client, sp<MediaSource> &source) { seekTimeUs = (rand() * (float)durationUs) / RAND_MAX; options.setSeekTo(seekTimeUs); - printf("seeking to %lld us (%.2f secs)\n", + printf("seeking to %" PRId64 " us (%.2f secs)\n", seekTimeUs, seekTimeUs / 1E6); } } @@ -388,7 +387,7 @@ static void playSource(OMXClient *client, sp<MediaSource> &source) { // sizes may be different across decoders. printf("avg. %.2f KB/sec\n", totalBytes / 1024 * 1E6 / delay); - printf("decoded a total of %lld bytes\n", totalBytes); + printf("decoded a total of %" PRId64 " bytes\n", totalBytes); } } @@ -574,7 +573,8 @@ static void performSeekTest(const sp<MediaSource> &source) { int64_t timeUs; CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs)); - printf("%lld\t%lld\t%lld\n", seekTimeUs, timeUs, seekTimeUs - timeUs); + printf("%" PRId64 "\t%" PRId64 "\t%" PRId64 "\n", + seekTimeUs, timeUs, seekTimeUs - timeUs); buffer->release(); buffer = NULL; @@ -645,7 +645,7 @@ static void dumpCodecProfiles(const sp<IOMX>& omx, bool queryDecoders) { const CodecProfileLevel &profileLevel = results[i].mProfileLevels[j]; - printf("%s%ld/%ld", j > 0 ? ", " : "", + printf("%s%" PRIu32 "/%" PRIu32, j > 0 ? ", " : "", profileLevel.mProfile, profileLevel.mLevel); } @@ -1071,7 +1071,7 @@ int main(int argc, char **argv) { int64_t thumbTimeUs; if (meta->findInt64(kKeyThumbnailTime, &thumbTimeUs)) { - printf("thumbnailTime: %lld us (%.2f secs)\n", + printf("thumbnailTime: %" PRId64 " us (%.2f secs)\n", thumbTimeUs, thumbTimeUs / 1E6); } diff --git a/drm/common/DrmSupportInfo.cpp b/drm/common/DrmSupportInfo.cpp index 5400bdd..584c6a6 100644 --- a/drm/common/DrmSupportInfo.cpp +++ b/drm/common/DrmSupportInfo.cpp @@ -47,7 +47,7 @@ bool DrmSupportInfo::isSupportedMimeType(const String8& mimeType) const { return false; } - for (unsigned int i = 0; i < mMimeTypeVector.size(); i++) { + for (size_t i = 0; i < mMimeTypeVector.size(); i++) { const String8 item = mMimeTypeVector.itemAt(i); if (!strcasecmp(item.string(), mimeType.string())) { @@ -58,7 +58,7 @@ bool DrmSupportInfo::isSupportedMimeType(const String8& mimeType) const { } bool DrmSupportInfo::isSupportedFileSuffix(const String8& fileType) const { - for (unsigned int i = 0; i < mFileSuffixVector.size(); i++) { + for (size_t i = 0; i < mFileSuffixVector.size(); i++) { const String8 item = mFileSuffixVector.itemAt(i); if (!strcasecmp(item.string(), fileType.string())) { diff --git a/drm/drmserver/Android.mk b/drm/drmserver/Android.mk index dc973da..48ea385 100644 --- a/drm/drmserver/Android.mk +++ b/drm/drmserver/Android.mk @@ -26,7 +26,8 @@ LOCAL_SHARED_LIBRARIES := \ libutils \ liblog \ libbinder \ - libdl + libdl \ + libselinux LOCAL_STATIC_LIBRARIES := libdrmframeworkcommon @@ -39,4 +40,6 @@ LOCAL_MODULE:= drmserver LOCAL_MODULE_TAGS := optional +LOCAL_32_BIT_ONLY := true + include $(BUILD_EXECUTABLE) diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp index dccd23d..d8aeb0c 100644 --- a/drm/drmserver/DrmManager.cpp +++ b/drm/drmserver/DrmManager.cpp @@ -101,7 +101,7 @@ status_t DrmManager::loadPlugIns() { status_t DrmManager::loadPlugIns(const String8& plugInDirPath) { mPlugInManager.loadPlugIns(plugInDirPath); Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList(); - for (unsigned int i = 0; i < plugInPathList.size(); ++i) { + for (size_t i = 0; i < plugInPathList.size(); ++i) { String8 plugInPath = plugInPathList[i]; DrmSupportInfo* info = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(0); if (NULL != info) { @@ -138,7 +138,7 @@ void DrmManager::addClient(int uniqueId) { Mutex::Autolock _l(mLock); if (!mSupportInfoToPlugInIdMap.isEmpty()) { Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList(); - for (unsigned int index = 0; index < plugInIdList.size(); index++) { + for (size_t index = 0; index < plugInIdList.size(); index++) { IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index)); rDrmEngine.initialize(uniqueId); rDrmEngine.setOnInfoListener(uniqueId, this); @@ -149,7 +149,7 @@ void DrmManager::addClient(int uniqueId) { void DrmManager::removeClient(int uniqueId) { Mutex::Autolock _l(mLock); Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList(); - for (unsigned int index = 0; index < plugInIdList.size(); index++) { + for (size_t index = 0; index < plugInIdList.size(); index++) { IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index)); rDrmEngine.terminate(uniqueId); } @@ -208,7 +208,7 @@ bool DrmManager::canHandle(int uniqueId, const String8& path) { bool result = false; Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList(); - for (unsigned int i = 0; i < plugInPathList.size(); ++i) { + for (size_t i = 0; i < plugInPathList.size(); ++i) { IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInPathList[i]); result = rDrmEngine.canHandle(uniqueId, path); @@ -318,7 +318,7 @@ status_t DrmManager::removeRights(int uniqueId, const String8& path) { status_t DrmManager::removeAllRights(int uniqueId) { Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList(); status_t result = DRM_ERROR_UNKNOWN; - for (unsigned int index = 0; index < plugInIdList.size(); index++) { + for (size_t index = 0; index < plugInIdList.size(); index++) { IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index)); result = rDrmEngine.removeAllRights(uniqueId); if (DRM_NO_ERROR != result) { @@ -412,7 +412,7 @@ DecryptHandle* DrmManager::openDecryptSession( if (NULL != handle) { handle->decryptId = mDecryptSessionId + 1; - for (unsigned int index = 0; index < plugInIdList.size(); index++) { + for (size_t index = 0; index < plugInIdList.size(); index++) { String8 plugInId = plugInIdList.itemAt(index); IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); result = rDrmEngine.openDecryptSession(uniqueId, handle, fd, offset, length, mime); @@ -440,7 +440,7 @@ DecryptHandle* DrmManager::openDecryptSession( if (NULL != handle) { handle->decryptId = mDecryptSessionId + 1; - for (unsigned int index = 0; index < plugInIdList.size(); index++) { + for (size_t index = 0; index < plugInIdList.size(); index++) { String8 plugInId = plugInIdList.itemAt(index); IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); result = rDrmEngine.openDecryptSession(uniqueId, handle, uri, mime); @@ -565,7 +565,7 @@ String8 DrmManager::getSupportedPlugInId(const String8& mimeType) { String8 plugInId(""); if (EMPTY_STRING != mimeType) { - for (unsigned int index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) { + for (size_t index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) { const DrmSupportInfo& drmSupportInfo = mSupportInfoToPlugInIdMap.keyAt(index); if (drmSupportInfo.isSupportedMimeType(mimeType)) { @@ -581,7 +581,7 @@ String8 DrmManager::getSupportedPlugInIdFromPath(int uniqueId, const String8& pa String8 plugInId(""); const String8 fileSuffix = path.getPathExtension(); - for (unsigned int index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) { + for (size_t index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) { const DrmSupportInfo& drmSupportInfo = mSupportInfoToPlugInIdMap.keyAt(index); if (drmSupportInfo.isSupportedFileSuffix(fileSuffix)) { @@ -599,7 +599,7 @@ String8 DrmManager::getSupportedPlugInIdFromPath(int uniqueId, const String8& pa void DrmManager::onInfo(const DrmInfoEvent& event) { Mutex::Autolock _l(mListenerLock); - for (unsigned int index = 0; index < mServiceListeners.size(); index++) { + for (size_t index = 0; index < mServiceListeners.size(); index++) { int uniqueId = mServiceListeners.keyAt(index); if (uniqueId == event.getUniqueId()) { diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp index 2b71904..857d73e 100644 --- a/drm/drmserver/DrmManagerService.cpp +++ b/drm/drmserver/DrmManagerService.cpp @@ -29,12 +29,71 @@ #include "DrmManagerService.h" #include "DrmManager.h" +#include <selinux/android.h> + using namespace android; +static int selinux_enabled; +static char *drmserver_context; static Vector<uid_t> trustedUids; -static bool isProtectedCallAllowed() { - return true; +const char *const DrmManagerService::drm_perm_labels[] = { + "consumeRights", + "setPlaybackStatus", + "openDecryptSession", + "closeDecryptSession", + "initializeDecryptUnit", + "decrypt", + "finalizeDecryptUnit", + "pread" +}; + +const char *DrmManagerService::get_perm_label(drm_perm_t perm) { + unsigned int index = perm; + + if (index < 0 || + index >= (sizeof(drm_perm_labels) / sizeof(drm_perm_labels[0]))) { + ALOGE("SELinux: Failed to retrieve permission label(perm=%d).\n", perm); + abort(); + } + return drm_perm_labels[index]; +} + +bool DrmManagerService::selinuxIsProtectedCallAllowed(pid_t spid, drm_perm_t perm) { + if (selinux_enabled <= 0) { + return true; + } + + char *sctx; + const char *selinux_class = "drmservice"; + const char *str_perm = get_perm_label(perm); + + if (getpidcon(spid, &sctx) != 0) { + ALOGE("SELinux: getpidcon(pid=%d) failed.\n", spid); + return false; + } + + bool allowed = (selinux_check_access(sctx, drmserver_context, selinux_class, + str_perm, NULL) == 0); + freecon(sctx); + + return allowed; +} + +bool DrmManagerService::isProtectedCallAllowed(drm_perm_t perm) { + // TODO + // Following implementation is just for reference. + // Each OEM manufacturer should implement/replace with their own solutions. + IPCThreadState* ipcState = IPCThreadState::self(); + uid_t uid = ipcState->getCallingUid(); + pid_t spid = ipcState->getCallingPid(); + + for (unsigned int i = 0; i < trustedUids.size(); ++i) { + if (trustedUids[i] == uid) { + return selinuxIsProtectedCallAllowed(spid, perm); + } + } + return false; } void DrmManagerService::instantiate() { @@ -49,6 +108,16 @@ void DrmManagerService::instantiate() { // Add trusted uids here trustedUids.push(AID_MEDIA); } + + selinux_enabled = is_selinux_enabled(); + if (selinux_enabled > 0 && getcon(&drmserver_context) != 0) { + ALOGE("SELinux: DrmManagerService failed to get context for DrmManagerService. Aborting.\n"); + abort(); + } + + union selinux_callback cb; + cb.func_log = selinux_log_callback; + selinux_set_callback(SELINUX_CB_LOG, cb); } DrmManagerService::DrmManagerService() : @@ -140,7 +209,7 @@ int DrmManagerService::checkRightsStatus( status_t DrmManagerService::consumeRights( int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) { ALOGV("Entering consumeRights"); - if (!isProtectedCallAllowed()) { + if (!isProtectedCallAllowed(CONSUME_RIGHTS)) { return DRM_ERROR_NO_PERMISSION; } return mDrmManager->consumeRights(uniqueId, decryptHandle, action, reserve); @@ -149,7 +218,7 @@ status_t DrmManagerService::consumeRights( status_t DrmManagerService::setPlaybackStatus( int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) { ALOGV("Entering setPlaybackStatus"); - if (!isProtectedCallAllowed()) { + if (!isProtectedCallAllowed(SET_PLAYBACK_STATUS)) { return DRM_ERROR_NO_PERMISSION; } return mDrmManager->setPlaybackStatus(uniqueId, decryptHandle, playbackStatus, position); @@ -197,7 +266,7 @@ status_t DrmManagerService::getAllSupportInfo( DecryptHandle* DrmManagerService::openDecryptSession( int uniqueId, int fd, off64_t offset, off64_t length, const char* mime) { ALOGV("Entering DrmManagerService::openDecryptSession"); - if (isProtectedCallAllowed()) { + if (isProtectedCallAllowed(OPEN_DECRYPT_SESSION)) { return mDrmManager->openDecryptSession(uniqueId, fd, offset, length, mime); } @@ -207,7 +276,7 @@ DecryptHandle* DrmManagerService::openDecryptSession( DecryptHandle* DrmManagerService::openDecryptSession( int uniqueId, const char* uri, const char* mime) { ALOGV("Entering DrmManagerService::openDecryptSession with uri"); - if (isProtectedCallAllowed()) { + if (isProtectedCallAllowed(OPEN_DECRYPT_SESSION)) { return mDrmManager->openDecryptSession(uniqueId, uri, mime); } @@ -217,7 +286,7 @@ DecryptHandle* DrmManagerService::openDecryptSession( DecryptHandle* DrmManagerService::openDecryptSession( int uniqueId, const DrmBuffer& buf, const String8& mimeType) { ALOGV("Entering DrmManagerService::openDecryptSession for streaming"); - if (isProtectedCallAllowed()) { + if (isProtectedCallAllowed(OPEN_DECRYPT_SESSION)) { return mDrmManager->openDecryptSession(uniqueId, buf, mimeType); } @@ -226,7 +295,7 @@ DecryptHandle* DrmManagerService::openDecryptSession( status_t DrmManagerService::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) { ALOGV("Entering closeDecryptSession"); - if (!isProtectedCallAllowed()) { + if (!isProtectedCallAllowed(CLOSE_DECRYPT_SESSION)) { return DRM_ERROR_NO_PERMISSION; } return mDrmManager->closeDecryptSession(uniqueId, decryptHandle); @@ -235,7 +304,7 @@ status_t DrmManagerService::closeDecryptSession(int uniqueId, DecryptHandle* dec status_t DrmManagerService::initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) { ALOGV("Entering initializeDecryptUnit"); - if (!isProtectedCallAllowed()) { + if (!isProtectedCallAllowed(INITIALIZE_DECRYPT_UNIT)) { return DRM_ERROR_NO_PERMISSION; } return mDrmManager->initializeDecryptUnit(uniqueId,decryptHandle, decryptUnitId, headerInfo); @@ -245,7 +314,7 @@ status_t DrmManagerService::decrypt( int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) { ALOGV("Entering decrypt"); - if (!isProtectedCallAllowed()) { + if (!isProtectedCallAllowed(DECRYPT)) { return DRM_ERROR_NO_PERMISSION; } return mDrmManager->decrypt(uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV); @@ -254,7 +323,7 @@ status_t DrmManagerService::decrypt( status_t DrmManagerService::finalizeDecryptUnit( int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) { ALOGV("Entering finalizeDecryptUnit"); - if (!isProtectedCallAllowed()) { + if (!isProtectedCallAllowed(FINALIZE_DECRYPT_UNIT)) { return DRM_ERROR_NO_PERMISSION; } return mDrmManager->finalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId); @@ -263,7 +332,7 @@ status_t DrmManagerService::finalizeDecryptUnit( ssize_t DrmManagerService::pread(int uniqueId, DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off64_t offset) { ALOGV("Entering pread"); - if (!isProtectedCallAllowed()) { + if (!isProtectedCallAllowed(PREAD)) { return DRM_ERROR_NO_PERMISSION; } return mDrmManager->pread(uniqueId, decryptHandle, buffer, numBytes, offset); diff --git a/drm/libdrmframework/include/DrmManagerService.h b/drm/libdrmframework/include/DrmManagerService.h index 8bc59b4..45cee2e 100644 --- a/drm/libdrmframework/include/DrmManagerService.h +++ b/drm/libdrmframework/include/DrmManagerService.h @@ -42,9 +42,28 @@ public: static void instantiate(); private: + enum drm_perm_t { + CONSUME_RIGHTS = 0, + SET_PLAYBACK_STATUS = 1, + OPEN_DECRYPT_SESSION = 2, + CLOSE_DECRYPT_SESSION = 3, + INITIALIZE_DECRYPT_UNIT = 4, + DECRYPT = 5, + FINALIZE_DECRYPT_UNIT = 6, + PREAD = 7, + }; + + static const char *const drm_perm_labels[]; + DrmManagerService(); virtual ~DrmManagerService(); + static const char *get_perm_label(drm_perm_t perm); + + static bool selinuxIsProtectedCallAllowed(pid_t spid, drm_perm_t perm); + + static bool isProtectedCallAllowed(drm_perm_t perm); + public: int addUniqueId(bool isNative); diff --git a/drm/libdrmframework/include/PlugInManager.h b/drm/libdrmframework/include/PlugInManager.h index 7bb143f..c1d019a 100644 --- a/drm/libdrmframework/include/PlugInManager.h +++ b/drm/libdrmframework/include/PlugInManager.h @@ -80,7 +80,7 @@ public: Vector<String8> plugInFileList = getPlugInPathList(rsPlugInDirPath); if (!plugInFileList.isEmpty()) { - for (unsigned int i = 0; i < plugInFileList.size(); ++i) { + for (size_t i = 0; i < plugInFileList.size(); ++i) { loadPlugIn(plugInFileList[i]); } } @@ -91,7 +91,7 @@ public: * */ void unloadPlugIns() { - for (unsigned int i = 0; i < m_plugInIdList.size(); ++i) { + for (size_t i = 0; i < m_plugInIdList.size(); ++i) { unloadPlugIn(m_plugInIdList[i]); } m_plugInIdList.clear(); diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk index e251f82..48b0afe 100644 --- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk +++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk @@ -61,7 +61,7 @@ LOCAL_C_INCLUDES += \ $(LOCAL_PATH)/include \ external/openssl/include -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/drm +LOCAL_MODULE_RELATIVE_PATH := drm LOCAL_MODULE_TAGS := optional diff --git a/drm/mediadrm/plugins/mock/Android.mk b/drm/mediadrm/plugins/mock/Android.mk index ada23a2..26c245b 100644 --- a/drm/mediadrm/plugins/mock/Android.mk +++ b/drm/mediadrm/plugins/mock/Android.mk @@ -21,7 +21,8 @@ LOCAL_SRC_FILES:= \ LOCAL_MODULE := libmockdrmcryptoplugin -LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_SHARED_LIBRARIES)/mediadrm +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE_RELATIVE_PATH := mediadrm LOCAL_SHARED_LIBRARIES := \ libutils liblog diff --git a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp index f2cadf7..69fa7a0 100644 --- a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp +++ b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp @@ -695,7 +695,7 @@ namespace android { { String8 result; for (size_t i = 0; i < numSubSamples; i++) { - result.appendFormat("[%d] {clear:%d, encrypted:%d} ", i, + result.appendFormat("[%zu] {clear:%zu, encrypted:%zu} ", i, subSamples[i].mNumBytesOfClearData, subSamples[i].mNumBytesOfEncryptedData); } diff --git a/include/camera/CameraParameters2.h b/include/camera/CameraParameters2.h new file mode 100644 index 0000000..88ad812 --- /dev/null +++ b/include/camera/CameraParameters2.h @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_CAMERA_PARAMETERS2_H +#define ANDROID_HARDWARE_CAMERA_PARAMETERS2_H + +#include <utils/Vector.h> +#include <utils/String8.h> +#include "CameraParameters.h" + +namespace android { + +/** + * A copy of CameraParameters plus ABI-breaking changes. Needed + * because some camera HALs directly link to CameraParameters and cannot + * tolerate an ABI change. + */ +class CameraParameters2 +{ +public: + CameraParameters2(); + CameraParameters2(const String8 ¶ms) { unflatten(params); } + ~CameraParameters2(); + + String8 flatten() const; + void unflatten(const String8 ¶ms); + + void set(const char *key, const char *value); + void set(const char *key, int value); + void setFloat(const char *key, float value); + // Look up string value by key. + // -- The string remains valid until the next set/remove of the same key, + // or until the map gets cleared. + const char *get(const char *key) const; + int getInt(const char *key) const; + float getFloat(const char *key) const; + + // Compare the order that key1 was set vs the order that key2 was set. + // + // Sets the order parameter to an integer less than, equal to, or greater + // than zero if key1's set order was respectively, to be less than, to + // match, or to be greater than key2's set order. + // + // Error codes: + // * NAME_NOT_FOUND - if either key has not been set previously + // * BAD_VALUE - if any of the parameters are NULL + status_t compareSetOrder(const char *key1, const char *key2, + /*out*/ + int *order) const; + + void remove(const char *key); + + void setPreviewSize(int width, int height); + void getPreviewSize(int *width, int *height) const; + void getSupportedPreviewSizes(Vector<Size> &sizes) const; + + // Set the dimensions in pixels to the given width and height + // for video frames. The given width and height must be one + // of the supported dimensions returned from + // getSupportedVideoSizes(). Must not be called if + // getSupportedVideoSizes() returns an empty Vector of Size. + void setVideoSize(int width, int height); + // Retrieve the current dimensions (width and height) + // in pixels for video frames, which must be one of the + // supported dimensions returned from getSupportedVideoSizes(). + // Must not be called if getSupportedVideoSizes() returns an + // empty Vector of Size. + void getVideoSize(int *width, int *height) const; + // Retrieve a Vector of supported dimensions (width and height) + // in pixels for video frames. If sizes returned from the method + // is empty, the camera does not support calls to setVideoSize() + // or getVideoSize(). In adddition, it also indicates that + // the camera only has a single output, and does not have + // separate output for video frames and preview frame. + void getSupportedVideoSizes(Vector<Size> &sizes) const; + // Retrieve the preferred preview size (width and height) in pixels + // for video recording. The given width and height must be one of + // supported preview sizes returned from getSupportedPreviewSizes(). + // Must not be called if getSupportedVideoSizes() returns an empty + // Vector of Size. If getSupportedVideoSizes() returns an empty + // Vector of Size, the width and height returned from this method + // is invalid, and is "-1x-1". + void getPreferredPreviewSizeForVideo(int *width, int *height) const; + + void setPreviewFrameRate(int fps); + int getPreviewFrameRate() const; + void getPreviewFpsRange(int *min_fps, int *max_fps) const; + void setPreviewFpsRange(int min_fps, int max_fps); + void setPreviewFormat(const char *format); + const char *getPreviewFormat() const; + void setPictureSize(int width, int height); + void getPictureSize(int *width, int *height) const; + void getSupportedPictureSizes(Vector<Size> &sizes) const; + void setPictureFormat(const char *format); + const char *getPictureFormat() const; + + void dump() const; + status_t dump(int fd, const Vector<String16>& args) const; + +private: + + // Quick and dirty map that maintains insertion order + template <typename KeyT, typename ValueT> + struct OrderedKeyedVector { + + ssize_t add(const KeyT& key, const ValueT& value) { + return mList.add(Pair(key, value)); + } + + size_t size() const { + return mList.size(); + } + + const KeyT& keyAt(size_t idx) const { + return mList[idx].mKey; + } + + const ValueT& valueAt(size_t idx) const { + return mList[idx].mValue; + } + + const ValueT& valueFor(const KeyT& key) const { + ssize_t i = indexOfKey(key); + LOG_ALWAYS_FATAL_IF(i<0, "%s: key not found", __PRETTY_FUNCTION__); + + return valueAt(i); + } + + ssize_t indexOfKey(const KeyT& key) const { + size_t vectorIdx = 0; + for (; vectorIdx < mList.size(); ++vectorIdx) { + if (mList[vectorIdx].mKey == key) { + return (ssize_t) vectorIdx; + } + } + + return NAME_NOT_FOUND; + } + + ssize_t removeItem(const KeyT& key) { + size_t vectorIdx = (size_t) indexOfKey(key); + + if (vectorIdx < 0) { + return vectorIdx; + } + + return mList.removeAt(vectorIdx); + } + + void clear() { + mList.clear(); + } + + // Same as removing and re-adding. The key's index changes to max. + ssize_t replaceValueFor(const KeyT& key, const ValueT& value) { + removeItem(key); + return add(key, value); + } + + private: + + struct Pair { + Pair() : mKey(), mValue() {} + Pair(const KeyT& key, const ValueT& value) : + mKey(key), + mValue(value) {} + KeyT mKey; + ValueT mValue; + }; + + Vector<Pair> mList; + }; + + /** + * Order matters: Keys that are set() later are stored later in the map. + * + * If two keys have meaning that conflict, then the later-set key + * wins. + * + * For example, preview FPS and preview FPS range conflict since only + * we only want to use the FPS range if that's the last thing that was set. + * So in that case, only use preview FPS range if it was set later than + * the preview FPS. + */ + OrderedKeyedVector<String8,String8> mMap; +}; + +}; // namespace android + +#endif diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h index 225ef76..4c22412 100644 --- a/include/media/AudioSystem.h +++ b/include/media/AudioSystem.h @@ -127,8 +127,8 @@ public: // NOTE: this feature is not supported on all hardware platforms and it is // necessary to check returned status before using the returned values. static status_t getRenderPosition(audio_io_handle_t output, - size_t *halFrames, - size_t *dspFrames, + uint32_t *halFrames, + uint32_t *dspFrames, audio_stream_type_t stream = AUDIO_STREAM_DEFAULT); // return the number of input frames lost by HAL implementation, or 0 if the handle is invalid diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h index f379ee5..4736369 100644 --- a/include/media/AudioTrack.h +++ b/include/media/AudioTrack.h @@ -661,7 +661,7 @@ protected: sp<AudioTrackThread> mAudioTrackThread; float mVolume[2]; float mSendLevel; - uint32_t mSampleRate; + mutable uint32_t mSampleRate; // mutable because getSampleRate() can update it. size_t mFrameCount; // corresponds to current IAudioTrack size_t mReqFrameCount; // frame count to request the next time a new // IAudioTrack is needed @@ -740,6 +740,7 @@ protected: bool mInUnderrun; // whether track is currently in underrun state String8 mName; // server's name for this IAudioTrack + uint32_t mPausedPosition; private: class DeathNotifier : public IBinder::DeathRecipient { diff --git a/include/media/EffectsFactoryApi.h b/include/media/EffectsFactoryApi.h index b1143b9..b1ed7b0 100644 --- a/include/media/EffectsFactoryApi.h +++ b/include/media/EffectsFactoryApi.h @@ -171,30 +171,6 @@ int EffectGetDescriptor(const effect_uuid_t *pEffectUuid, effect_descriptor_t *p //////////////////////////////////////////////////////////////////////////////// int EffectIsNullUuid(const effect_uuid_t *pEffectUuid); -//////////////////////////////////////////////////////////////////////////////// -// -// Function: EffectGetSubEffects -// -// Description: Returns the descriptors of the sub effects of the effect -// whose uuid is pointed to by first argument. -// -// Input: -// pEffectUuid: pointer to the effect uuid. -// size: size of the buffer pointed by pDescriptor. -// -// Input/Output: -// pDescriptor: address where to return the sub effect descriptors. -// -// Output: -// returned value: 0 successful operation. -// -ENODEV factory failed to initialize -// -EINVAL invalid pEffectUuid or pDescriptor -// -ENOENT no effect with this uuid found -// *pDescriptor: updated with the sub effect descriptors. -// -//////////////////////////////////////////////////////////////////////////////// -int EffectGetSubEffects(const effect_uuid_t *pEffectUuid, effect_descriptor_t *pDescriptors, size_t size); - #if __cplusplus } // extern "C" #endif diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h index 899d79f..282f275 100644 --- a/include/media/IAudioFlinger.h +++ b/include/media/IAudioFlinger.h @@ -167,10 +167,10 @@ public: virtual status_t setVoiceVolume(float volume) = 0; - virtual status_t getRenderPosition(size_t *halFrames, size_t *dspFrames, + virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, audio_io_handle_t output) const = 0; - virtual size_t getInputFramesLost(audio_io_handle_t ioHandle) const = 0; + virtual uint32_t getInputFramesLost(audio_io_handle_t ioHandle) const = 0; virtual int newAudioSessionId() = 0; diff --git a/include/media/IOMX.h b/include/media/IOMX.h index 9c8451c..b74a2c7 100644 --- a/include/media/IOMX.h +++ b/include/media/IOMX.h @@ -38,8 +38,8 @@ class IOMX : public IInterface { public: DECLARE_META_INTERFACE(OMX); - typedef void *buffer_id; - typedef void *node_id; + typedef uint32_t buffer_id; + typedef uint32_t node_id; // Given a node_id and the calling process' pid, returns true iff // the implementation of the OMX interface lives in the same @@ -142,6 +142,7 @@ public: enum InternalOptionType { INTERNAL_OPTION_SUSPEND, // data is a bool INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY, // data is an int64_t + INTERNAL_OPTION_MAX_TIMESTAMP_GAP, // data is int64_t }; virtual status_t setInternalOption( node_id node, diff --git a/include/media/MediaMetadataRetrieverInterface.h b/include/media/MediaMetadataRetrieverInterface.h index ecc3b65..cd5bf88 100644 --- a/include/media/MediaMetadataRetrieverInterface.h +++ b/include/media/MediaMetadataRetrieverInterface.h @@ -20,6 +20,7 @@ #include <utils/RefBase.h> #include <media/mediametadataretriever.h> +#include <media/mediascanner.h> #include <private/media/VideoFrame.h> namespace android { diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h index cc244f0..26d8729 100644 --- a/include/media/MediaPlayerInterface.h +++ b/include/media/MediaPlayerInterface.h @@ -100,6 +100,7 @@ public: virtual status_t getFramesWritten(uint32_t *frameswritten) const = 0; virtual int getSessionId() const = 0; virtual audio_stream_type_t getAudioStreamType() const = 0; + virtual uint32_t getSampleRate() const = 0; // If no callback is specified, use the "write" API below to submit // audio data. diff --git a/include/media/mediascanner.h b/include/media/mediascanner.h index a73403b..37a83c6 100644 --- a/include/media/mediascanner.h +++ b/include/media/mediascanner.h @@ -41,6 +41,31 @@ enum MediaScanResult { MEDIA_SCAN_RESULT_ERROR, }; +struct MediaAlbumArt { +public: + static MediaAlbumArt *fromData(int32_t size, const void* data); + + static void init(MediaAlbumArt* instance, int32_t size, const void* data); + + MediaAlbumArt *clone(); + + const char *data() { + return &mData[0]; + } + + int32_t size() { + return mSize; + } + +private: + int32_t mSize; + char mData[]; + + // You can't construct instances of this class directly because this is a + // variable-sized object passed through the binder. + MediaAlbumArt(); +} __packed; + struct MediaScanner { MediaScanner(); virtual ~MediaScanner(); @@ -53,8 +78,7 @@ struct MediaScanner { void setLocale(const char *locale); - // extracts album art as a block of data - virtual char *extractAlbumArt(int fd) = 0; + virtual MediaAlbumArt *extractAlbumArt(int fd) = 0; protected: const char *locale() const; diff --git a/include/media/nbaio/NBLog.h b/include/media/nbaio/NBLog.h index 6d59ea7..bcbbc04 100644 --- a/include/media/nbaio/NBLog.h +++ b/include/media/nbaio/NBLog.h @@ -25,6 +25,8 @@ namespace android { +class String8; + class NBLog { public: @@ -187,6 +189,10 @@ private: const Shared* const mShared; // raw pointer to shared memory const sp<IMemory> mIMemory; // ref-counted version int32_t mFront; // index of oldest acknowledged Entry + int mFd; // file descriptor + int mIndent; // indentation level + + void dumpLine(const String8& timestamp, String8& body); static const size_t kSquashTimestamp = 5; // squash this many or more adjacent timestamps }; diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h index e796ab3..46c62dc 100644 --- a/include/media/stagefright/ACodec.h +++ b/include/media/stagefright/ACodec.h @@ -67,6 +67,8 @@ struct ACodec : public AHierarchicalStateMachine { void signalRequestIDRFrame(); + bool isConfiguredForAdaptivePlayback() { return mIsConfiguredForAdaptivePlayback; } + struct PortDescription : public RefBase { size_t countBuffers(); IOMX::buffer_id bufferIDAt(size_t index) const; @@ -116,6 +118,7 @@ private: kWhatStart = 'star', kWhatRequestIDRFrame = 'ridr', kWhatSetParameters = 'setP', + kWhatSubmitOutputMetaDataBufferIfEOS = 'subm', }; enum { @@ -186,6 +189,7 @@ private: bool mIsEncoder; bool mUseMetadataOnEncoderOutput; bool mShutdownInProgress; + bool mIsConfiguredForAdaptivePlayback; // If "mKeepComponentAllocated" we only transition back to Loaded state // and do not release the component instance. @@ -199,8 +203,10 @@ private: unsigned mDequeueCounter; bool mStoreMetaDataInOutputBuffers; int32_t mMetaDataBuffersToSubmit; + size_t mNumUndequeuedBuffers; int64_t mRepeatFrameDelayUs; + int64_t mMaxPtsGapUs; status_t setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode); status_t allocateBuffersOnPort(OMX_U32 portIndex); @@ -212,6 +218,7 @@ private: OMX_U32 *nMinUndequeuedBuffers); status_t allocateOutputMetaDataBuffers(); status_t submitOutputMetaDataBuffer(); + void signalSubmitOutputMetaDataBufferIfEOS_workaround(); status_t allocateOutputBuffersFromNativeWindow(); status_t cancelBufferToNativeWindow(BufferInfo *info); status_t freeOutputBuffersNotOwnedByComponent(); diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h index 912a43c..14afb85 100644 --- a/include/media/stagefright/AudioPlayer.h +++ b/include/media/stagefright/AudioPlayer.h @@ -129,7 +129,7 @@ private: void reset(); uint32_t getNumFramesPendingPlayout() const; - int64_t getOutputPlayPositionUs_l() const; + int64_t getOutputPlayPositionUs_l(); bool allowDeepBuffering() const { return (mCreateFlags & ALLOW_DEEP_BUFFERING) != 0; } bool useOffload() const { return (mCreateFlags & USE_OFFLOAD) != 0; } diff --git a/include/media/stagefright/ClockEstimator.h b/include/media/stagefright/ClockEstimator.h new file mode 100644 index 0000000..2fd6e75 --- /dev/null +++ b/include/media/stagefright/ClockEstimator.h @@ -0,0 +1,110 @@ +/* +** +** Copyright 2014, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef CLOCK_ESTIMATOR_H_ + +#define CLOCK_ESTIMATOR_H_ + + +#include <utils/RefBase.h> +#include <utils/Vector.h> + +namespace android { +// --------------------------------------------------------------------------- + +struct ClockEstimator : RefBase { + virtual double estimate(double x, double y) = 0; + virtual void reset() = 0; +}; + +struct WindowedLinearFitEstimator : ClockEstimator { + struct LinearFit { + /** + * Fit y = a * x + b, where each input has a weight + */ + double mX; // sum(w_i * x_i) + double mXX; // sum(w_i * x_i^2) + double mY; // sum(w_i * y_i) + double mYY; // sum(w_i * y_i^2) + double mXY; // sum(w_i * x_i * y_i) + double mW; // sum(w_i) + + LinearFit(); + void reset(); + void combine(const LinearFit &lf); + void add(double x, double y, double w); + void scale(double w); + double interpolate(double x); + double size() const; + + DISALLOW_EVIL_CONSTRUCTORS(LinearFit); + }; + + /** + * Estimator for f(x) = y' where input y' is noisy, but + * theoretically linear: + * + * y' =~ y = a * x + b + * + * It uses linear fit regression over a tapering rolling window + * to get an estimate for y (from the current and past inputs + * (x, y')). + * + * ____________ + * /| |\ + * / | | \ + * / | | \ <--- new data (x, y') + * / | main | \ + * <--><----------><--> + * tail head + * + * weight is 1 under the main window, tapers exponentially by + * the factors given in the head and the tail. + * + * Assuming that x and y' are monotonic, that x is somewhat + * evenly sampled, and that a =~ 1, the estimated y is also + * going to be monotonic. + */ + WindowedLinearFitEstimator( + size_t headLength = 5, double headFactor = 0.5, + size_t mainLength = 0, double tailFactor = 0.99); + + virtual void reset(); + + // add a new sample (x -> y') and return an estimated value for the true y + virtual double estimate(double x, double y); + +private: + Vector<double> mXHistory; // circular buffer + Vector<double> mYHistory; // circular buffer + LinearFit mHead; + LinearFit mMain; + LinearFit mTail; + double mHeadFactorInv; + double mTailFactor; + double mFirstWeight; + size_t mHistoryLength; + size_t mHeadLength; + size_t mNumSamples; + size_t mSampleIx; + + DISALLOW_EVIL_CONSTRUCTORS(WindowedLinearFitEstimator); +}; + +}; // namespace android + +#endif diff --git a/include/media/stagefright/FileSource.h b/include/media/stagefright/FileSource.h index d994cb3..be152e7 100644 --- a/include/media/stagefright/FileSource.h +++ b/include/media/stagefright/FileSource.h @@ -55,7 +55,7 @@ private: sp<DecryptHandle> mDecryptHandle; DrmManagerClient *mDrmManagerClient; int64_t mDrmBufOffset; - int64_t mDrmBufSize; + size_t mDrmBufSize; unsigned char *mDrmBuf; ssize_t readAtDRM(off64_t offset, void *data, size_t size); diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h index 76aa503..1f17efe 100644 --- a/include/media/stagefright/MediaCodec.h +++ b/include/media/stagefright/MediaCodec.h @@ -182,7 +182,7 @@ private: }; struct BufferInfo { - void *mBufferID; + uint32_t mBufferID; sp<ABuffer> mData; sp<ABuffer> mEncryptedData; sp<AMessage> mNotify; diff --git a/include/media/stagefright/MediaSource.h b/include/media/stagefright/MediaSource.h index 3818e63..204d1c6 100644 --- a/include/media/stagefright/MediaSource.h +++ b/include/media/stagefright/MediaSource.h @@ -105,7 +105,7 @@ struct MediaSource : public virtual RefBase { // This will be called after a successful start() and before the // first read() call. // Callee assumes ownership of the buffers if no error is returned. - virtual status_t setBuffers(const Vector<MediaBuffer *> &buffers) { + virtual status_t setBuffers(const Vector<MediaBuffer *> & /* buffers */) { return ERROR_UNSUPPORTED; } diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h index de3fc36..db8216b 100644 --- a/include/media/stagefright/MetaData.h +++ b/include/media/stagefright/MetaData.h @@ -134,6 +134,7 @@ enum { kKeyRequiresSecureBuffers = 'secu', // bool (int32_t) kKeyIsADTS = 'adts', // bool (int32_t) + kKeyAACAOT = 'aaot', // int32_t // If a MediaBuffer's data represents (at least partially) encrypted // data, the following fields aid in decryption. @@ -214,6 +215,8 @@ public: bool findData(uint32_t key, uint32_t *type, const void **data, size_t *size) const; + bool hasData(uint32_t key) const; + void dumpToLog() const; protected: diff --git a/include/media/stagefright/StagefrightMediaScanner.h b/include/media/stagefright/StagefrightMediaScanner.h index 6510a59..eb3accc 100644 --- a/include/media/stagefright/StagefrightMediaScanner.h +++ b/include/media/stagefright/StagefrightMediaScanner.h @@ -30,7 +30,7 @@ struct StagefrightMediaScanner : public MediaScanner { const char *path, const char *mimeType, MediaScannerClient &client); - virtual char *extractAlbumArt(int fd); + virtual MediaAlbumArt *extractAlbumArt(int fd); private: StagefrightMediaScanner(const StagefrightMediaScanner &); diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h index 7fd9379..2d033e6 100644 --- a/include/private/media/AudioTrackShared.h +++ b/include/private/media/AudioTrackShared.h @@ -65,7 +65,9 @@ typedef SingleStateQueue<StaticAudioTrackState> StaticAudioTrackSingleStateQueue struct AudioTrackSharedStatic { StaticAudioTrackSingleStateQueue::Shared mSingleStateQueue; - size_t mBufferPosition; // updated asynchronously by server, + // This field should be a size_t, but since it is located in shared memory we + // force to 32-bit. The client and server may have different typedefs for size_t. + uint32_t mBufferPosition; // updated asynchronously by server, // "for entertainment purposes only" }; @@ -108,7 +110,9 @@ struct audio_track_cblk_t private: - size_t mMinimum; // server wakes up client if available >= mMinimum + // This field should be a size_t, but since it is located in shared memory we + // force to 32-bit. The client and server may have different typedefs for size_t. + uint32_t mMinimum; // server wakes up client if available >= mMinimum // Channel volumes are fixed point U4.12, so 0x1000 means 1.0. // Left channel is in [0:15], right channel is in [16:31]. @@ -245,7 +249,11 @@ public: } void setMinimum(size_t minimum) { - mCblk->mMinimum = minimum; + // This can only happen on a 64-bit client + if (minimum > UINT32_MAX) { + minimum = UINT32_MAX; + } + mCblk->mMinimum = (uint32_t) minimum; } // Return the number of frames that would need to be obtained and released diff --git a/include/private/media/StaticAudioTrackState.h b/include/private/media/StaticAudioTrackState.h index 46a5946..d483061 100644 --- a/include/private/media/StaticAudioTrackState.h +++ b/include/private/media/StaticAudioTrackState.h @@ -25,9 +25,13 @@ namespace android { // state is wrapped by a SingleStateQueue. struct StaticAudioTrackState { // do not define constructors, destructors, or virtual methods - size_t mLoopStart; - size_t mLoopEnd; - int mLoopCount; + + // These fields should both be size_t, but since they are located in shared memory we + // force to 32-bit. The client and server may have different typedefs for size_t. + uint32_t mLoopStart; + uint32_t mLoopEnd; + + int mLoopCount; }; } // namespace android diff --git a/include/private/media/VideoFrame.h b/include/private/media/VideoFrame.h index a211ed9..5dd425b 100644 --- a/include/private/media/VideoFrame.h +++ b/include/private/media/VideoFrame.h @@ -25,64 +25,6 @@ namespace android { -// A simple buffer to hold binary data -class MediaAlbumArt -{ -public: - MediaAlbumArt(): mSize(0), mData(0) {} - - explicit MediaAlbumArt(const char* url) { - mSize = 0; - mData = NULL; - FILE *in = fopen(url, "r"); - if (!in) { - return; - } - fseek(in, 0, SEEK_END); - mSize = ftell(in); // Allocating buffer of size equals to the external file size. - if (mSize == 0 || (mData = new uint8_t[mSize]) == NULL) { - fclose(in); - if (mSize != 0) { - mSize = 0; - } - return; - } - rewind(in); - if (fread(mData, 1, mSize, in) != mSize) { // Read failed. - delete[] mData; - mData = NULL; - mSize = 0; - return; - } - fclose(in); - } - - MediaAlbumArt(const MediaAlbumArt& copy) { - mSize = copy.mSize; - mData = NULL; // initialize it first - if (mSize > 0 && copy.mData != NULL) { - mData = new uint8_t[copy.mSize]; - if (mData != NULL) { - memcpy(mData, copy.mData, mSize); - } else { - mSize = 0; - } - } - } - - ~MediaAlbumArt() { - if (mData != 0) { - delete[] mData; - } - } - - // Intentional public access modifier: - // We have to know the internal structure in order to share it between - // processes? - uint32_t mSize; // Number of bytes in mData - uint8_t* mData; // Actual binary data -}; - // Represents a color converted (RGB-based) video frame // with bitmap pixels stored in FrameBuffer class VideoFrame diff --git a/libvideoeditor/lvpp/Android.mk b/libvideoeditor/lvpp/Android.mk index 2286827..a84ddad 100755 --- a/libvideoeditor/lvpp/Android.mk +++ b/libvideoeditor/lvpp/Android.mk @@ -46,7 +46,7 @@ LOCAL_STATIC_LIBRARIES := \ LOCAL_SHARED_LIBRARIES := \ - libaudioflinger \ + libaudioresampler \ libaudioutils \ libbinder \ libcutils \ @@ -81,15 +81,10 @@ LOCAL_C_INCLUDES += \ $(TOP)/frameworks/av/services/audioflinger \ $(TOP)/frameworks/native/include/media/editor \ $(TOP)/frameworks/native/include/media/openmax \ - $(TOP)/frameworks/native/services/audioflinger LOCAL_SHARED_LIBRARIES += libdl -# All of the shared libraries we link against. -LOCAL_LDLIBS := \ - -lpthread -ldl - LOCAL_CFLAGS += -Wno-multichar \ -DM4_ENABLE_RENDERINGMODE \ -DUSE_STAGEFRIGHT_CODECS \ diff --git a/libvideoeditor/lvpp/DummyVideoSource.cpp b/libvideoeditor/lvpp/DummyVideoSource.cpp index b06f937..6dbcf2a 100755 --- a/libvideoeditor/lvpp/DummyVideoSource.cpp +++ b/libvideoeditor/lvpp/DummyVideoSource.cpp @@ -16,6 +16,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "DummyVideoSource" +#include <inttypes.h> #include <stdlib.h> #include <utils/Log.h> #include <media/stagefright/foundation/ADebug.h> @@ -146,7 +147,7 @@ status_t DummyVideoSource::read( if (mIsFirstImageFrame) { M4OSA_clockGetTime(&mImagePlayStartTime, kTimeScale); mFrameTimeUs = (mImageSeekTime + 1); - ALOGV("read: jpg 1st frame timeUs = %lld, begin cut time = %ld", + ALOGV("read: jpg 1st frame timeUs = %lld, begin cut time = %" PRIu32, mFrameTimeUs, mImageSeekTime); mIsFirstImageFrame = false; diff --git a/libvideoeditor/lvpp/VideoEditorAudioPlayer.cpp b/libvideoeditor/lvpp/VideoEditorAudioPlayer.cpp index 176f8e9..91dc590 100755 --- a/libvideoeditor/lvpp/VideoEditorAudioPlayer.cpp +++ b/libvideoeditor/lvpp/VideoEditorAudioPlayer.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include <inttypes.h> + #define LOG_NDEBUG 1 #define LOG_TAG "VideoEditorAudioPlayer" #include <utils/Log.h> @@ -372,7 +374,7 @@ status_t VideoEditorAudioPlayer::start(bool sourceAlreadyStarted) { // Get the duration in time of the audio BT if ( result == M4NO_ERROR ) { - ALOGV("VEAP: channels = %d freq = %d", + ALOGV("VEAP: channels = %" PRIu32 " freq = %" PRIu32, mAudioMixSettings->uiNbChannels, mAudioMixSettings->uiSamplingFrequency); // No trim @@ -440,7 +442,7 @@ status_t VideoEditorAudioPlayer::start(bool sourceAlreadyStarted) { // do nothing } - ALOGV("VideoEditorAudioPlayer::startTime %d", startTime); + ALOGV("VideoEditorAudioPlayer::startTime %" PRIu32, startTime); seekTimeStamp = 0; if (startTime) { if (startTime >= mBGAudioPCMFileDuration) { @@ -671,8 +673,9 @@ size_t VideoEditorAudioPlayer::fillBuffer(void *data, size_t size) { M4OSA_Void* ptr; - ptr = (M4OSA_Void*)((unsigned int)mInputBuffer->data() + - mInputBuffer->range_offset()); + ptr = reinterpret_cast<M4OSA_Void*>( + reinterpret_cast<uintptr_t>(mInputBuffer->data()) + + mInputBuffer->range_offset()); M4OSA_UInt32 len = mInputBuffer->range_length(); M4OSA_Context fp = M4OSA_NULL; @@ -700,8 +703,8 @@ size_t VideoEditorAudioPlayer::fillBuffer(void *data, size_t size) { mBGAudioPCMFileOriginalSeekPoint <= (mBGAudioPCMFileTrimmedLength - len)) { - ALOGV("Checking mBGAudioPCMFileHandle %d", - (unsigned int)mBGAudioPCMFileHandle); + ALOGV("Checking mBGAudioPCMFileHandle %p", + mBGAudioPCMFileHandle); if (mBGAudioPCMFileHandle != M4OSA_NULL) { ALOGV("fillBuffer seeking file to %lld", diff --git a/libvideoeditor/lvpp/VideoEditorBGAudioProcessing.cpp b/libvideoeditor/lvpp/VideoEditorBGAudioProcessing.cpp index e24fcf4..0c12aac 100755 --- a/libvideoeditor/lvpp/VideoEditorBGAudioProcessing.cpp +++ b/libvideoeditor/lvpp/VideoEditorBGAudioProcessing.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include <inttypes.h> + //#define LOG_NDEBUG 0 #define LOG_TAG "VideoEditorBGAudioProcessing" #include <utils/Log.h> @@ -50,8 +52,8 @@ M4OSA_Int32 VideoEditorBGAudioProcessing::mixAndDuck( void *backgroundTrackBuffer, void *outBuffer) { - ALOGV("mixAndDuck: track buffers (primary: 0x%x and background: 0x%x) " - "and out buffer 0x%x", + ALOGV("mixAndDuck: track buffers (primary: %p and background: %p) " + "and out buffer %p", primaryTrackBuffer, backgroundTrackBuffer, outBuffer); M4AM_Buffer16* pPrimaryTrack = (M4AM_Buffer16*)primaryTrackBuffer; @@ -217,7 +219,7 @@ void VideoEditorBGAudioProcessing::setMixParams( mDoDucking = 0; mDuckingFactor = 1.0; - ALOGV("ducking enable 0x%x lowVolume %f threshold %d " + ALOGV("ducking enable 0x%x lowVolume %f threshold %" PRIu32 " " "fPTVolLevel %f BTVolLevel %f", mDucking_enable, mDucking_lowVolume, mDucking_threshold, mPTVolLevel, mPTVolLevel); diff --git a/libvideoeditor/lvpp/VideoEditorPlayer.cpp b/libvideoeditor/lvpp/VideoEditorPlayer.cpp index 5aeba4f..8d656c4 100755 --- a/libvideoeditor/lvpp/VideoEditorPlayer.cpp +++ b/libvideoeditor/lvpp/VideoEditorPlayer.cpp @@ -585,4 +585,11 @@ int VideoEditorPlayer::VeAudioOutput::getSessionId() const { return mSessionId; } +uint32_t VideoEditorPlayer::VeAudioOutput::getSampleRate() const { + if (mMsecsPerFrame == 0) { + return 0; + } + return (uint32_t)(1.e3 / mMsecsPerFrame); +} + } // namespace android diff --git a/libvideoeditor/lvpp/VideoEditorPlayer.h b/libvideoeditor/lvpp/VideoEditorPlayer.h index 5862c08..b8c1254 100755 --- a/libvideoeditor/lvpp/VideoEditorPlayer.h +++ b/libvideoeditor/lvpp/VideoEditorPlayer.h @@ -48,6 +48,7 @@ class VideoEditorPlayer : public MediaPlayerInterface { virtual status_t getPosition(uint32_t *position) const; virtual status_t getFramesWritten(uint32_t*) const; virtual int getSessionId() const; + virtual uint32_t getSampleRate() const; virtual status_t open( uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask, diff --git a/libvideoeditor/lvpp/VideoEditorPreviewController.cpp b/libvideoeditor/lvpp/VideoEditorPreviewController.cpp index 149c4ea..c3cd3d0 100755 --- a/libvideoeditor/lvpp/VideoEditorPreviewController.cpp +++ b/libvideoeditor/lvpp/VideoEditorPreviewController.cpp @@ -1248,7 +1248,7 @@ void VideoEditorPreviewController::notify( case MEDIA_SET_VIDEO_SIZE: ALOGV("MEDIA_SET_VIDEO_SIZE; New video size %d x %d", ext1, ext2); break; - case 0xAAAAAAAA: + case static_cast<int>(0xAAAAAAAA): ALOGV("VIDEO PLAYBACK ALMOST over, prepare next player"); // Select next player and prepare it // If there is a clip after this one @@ -1268,7 +1268,7 @@ void VideoEditorPreviewController::notify( } } break; - case 0xBBBBBBBB: + case static_cast<int>(0xBBBBBBBB): { ALOGV("VIDEO PLAYBACK, Update Overlay"); int overlayIndex = ext2; diff --git a/libvideoeditor/lvpp/VideoEditorSRC.cpp b/libvideoeditor/lvpp/VideoEditorSRC.cpp index 36d0812..6beabfa 100755 --- a/libvideoeditor/lvpp/VideoEditorSRC.cpp +++ b/libvideoeditor/lvpp/VideoEditorSRC.cpp @@ -284,7 +284,7 @@ status_t VideoEditorSRC::getNextBuffer(AudioBufferProvider::Buffer *pBuffer, int void VideoEditorSRC::releaseBuffer(AudioBufferProvider::Buffer *pBuffer) { - ALOGV("releaseBuffer: %p", pBuffers); + ALOGV("releaseBuffer: %p", pBuffer); free(pBuffer->raw); pBuffer->raw = NULL; pBuffer->frameCount = 0; diff --git a/libvideoeditor/osal/inc/M4OSA_Error.h b/libvideoeditor/osal/inc/M4OSA_Error.h index 4d59529..75c3177 100755 --- a/libvideoeditor/osal/inc/M4OSA_Error.h +++ b/libvideoeditor/osal/inc/M4OSA_Error.h @@ -57,7 +57,7 @@ typedef M4OSA_UInt32 M4OSA_ERR; * @arg coreID: (IN) [M4OSA_UInt32] CoreID to put in the error code * @arg errorID: (IN) [M4OSA_UInt32] ErrorID to put in the error code*/ #define M4OSA_ERR_CREATE(severity, coreID, errorID)\ - (M4OSA_Int32)((((M4OSA_UInt32)severity)<<30)+((((M4OSA_UInt32)coreID)&0x003FFF)<<16)+(((M4OSA_UInt32)errorID)&0x00FFFF)) + (M4OSA_UInt32)((((M4OSA_UInt32)severity)<<30)+((((M4OSA_UInt32)coreID)&0x003FFF)<<16)+(((M4OSA_UInt32)errorID)&0x00FFFF)) /** This macro extracts the 3 fields from the error: * @arg error: (IN) [M4OSA_ERR] Error code diff --git a/libvideoeditor/osal/inc/M4OSA_Types.h b/libvideoeditor/osal/inc/M4OSA_Types.h index 92a68d8..ee258a0 100755 --- a/libvideoeditor/osal/inc/M4OSA_Types.h +++ b/libvideoeditor/osal/inc/M4OSA_Types.h @@ -36,13 +36,13 @@ extern "C" { #endif -typedef signed char M4OSA_Bool; -typedef unsigned char M4OSA_UInt8; -typedef signed char M4OSA_Int8; -typedef unsigned short M4OSA_UInt16; -typedef signed short M4OSA_Int16; -typedef unsigned long M4OSA_UInt32; -typedef signed long M4OSA_Int32; +typedef int8_t M4OSA_Bool; +typedef uint8_t M4OSA_UInt8; +typedef int8_t M4OSA_Int8; +typedef uint16_t M4OSA_UInt16; +typedef int16_t M4OSA_Int16; +typedef uint32_t M4OSA_UInt32; +typedef int32_t M4OSA_Int32; typedef signed char M4OSA_Char; typedef unsigned char M4OSA_UChar; diff --git a/libvideoeditor/osal/src/Android.mk b/libvideoeditor/osal/src/Android.mk index 4f38b0c..b613387 100755 --- a/libvideoeditor/osal/src/Android.mk +++ b/libvideoeditor/osal/src/Android.mk @@ -48,10 +48,6 @@ LOCAL_C_INCLUDES += \ LOCAL_SHARED_LIBRARIES += libdl -# All of the shared libraries we link against. -LOCAL_LDLIBS := \ - -lpthread -ldl - LOCAL_CFLAGS += -Wno-multichar \ -D__ANDROID__ \ -DM4OSA_FILE_BLOCK_WITH_SEMAPHORE \ diff --git a/libvideoeditor/osal/src/M4OSA_Thread.c b/libvideoeditor/osal/src/M4OSA_Thread.c index db54245..3e82fb3 100755 --- a/libvideoeditor/osal/src/M4OSA_Thread.c +++ b/libvideoeditor/osal/src/M4OSA_Thread.c @@ -524,7 +524,7 @@ M4OSA_ERR M4OSA_SetThreadSyncPriority(M4OSA_Context context, M4OSA_TRACE2_2("M4OSA_SetThreadSyncPriority\t\tM4OSA_Context 0x%x\t" "M4OSA_DataOption 0x%x", context, optionValue); - if((M4OSA_UInt32)optionValue>M4OSA_kThreadLowestPriority) + if((M4OSA_UInt32)(uintptr_t)optionValue>M4OSA_kThreadLowestPriority) { return M4ERR_PARAMETER; } @@ -590,7 +590,7 @@ M4OSA_ERR M4OSA_SetThreadSyncStackSize(M4OSA_Context context, M4OSA_TRACE2_2("M4OSA_SetThreadSyncStackSize\t\tM4OSA_Context 0x%x\t" "M4OSA_DataOption 0x%x", context, optionValue); - threadContext->stackSize = (M4OSA_UInt32)optionValue; + threadContext->stackSize = (M4OSA_UInt32)(uintptr_t)optionValue; return M4NO_ERROR; } diff --git a/libvideoeditor/osal/src/M4PSW_DebugTrace.c b/libvideoeditor/osal/src/M4PSW_DebugTrace.c index 0fcba94..850ed91 100755 --- a/libvideoeditor/osal/src/M4PSW_DebugTrace.c +++ b/libvideoeditor/osal/src/M4PSW_DebugTrace.c @@ -25,6 +25,7 @@ */ +#include <inttypes.h> #include <stdio.h> /*for printf */ #include "M4OSA_Types.h" @@ -65,9 +66,9 @@ M4OSAL_TRACE_EXPORT_TYPE void M4OSA_DebugTrace(M4OSA_Int32 line, } #ifdef NO_FILE - printf("Error: %li, on %s: %s\n",err,cond,msg); + printf("Error: %" PRIu32 ", on %s: %s\n",err,cond,msg); #else /* NO_FILE */ - printf("Error: %li, on %s: %s Line %lu in: %s\n",err,cond,msg,line,file); + printf("Error: %" PRIu32 ", on %s: %s Line %" PRIu32 " in: %s\n",err,cond,msg,line,file); #endif /* NO_FILE */ } diff --git a/libvideoeditor/vss/3gpwriter/src/Android.mk b/libvideoeditor/vss/3gpwriter/src/Android.mk index 8ab32ba..b70300f 100755 --- a/libvideoeditor/vss/3gpwriter/src/Android.mk +++ b/libvideoeditor/vss/3gpwriter/src/Android.mk @@ -43,12 +43,7 @@ LOCAL_C_INCLUDES += \ LOCAL_SHARED_LIBRARIES += libdl -# All of the shared libraries we link against. -LOCAL_LDLIBS := \ - -lpthread -ldl - LOCAL_CFLAGS += -Wno-multichar \ -DDUPLICATE_STTS_IN_LAST_AU include $(BUILD_STATIC_LIBRARY) - diff --git a/libvideoeditor/vss/common/inc/marker.h b/libvideoeditor/vss/common/inc/marker.h deleted file mode 100755 index 83cade0..0000000 --- a/libvideoeditor/vss/common/inc/marker.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef MARKER_H -#define MARKER_H - -#define ADD_CODE_MARKER_FUN(m_condition) \ - if ( !(m_condition) ) \ - { \ - __asm__ volatile ( \ - ".word 0x21614062\n\t" /* '!a@b' */ \ - ".word 0x47712543\n\t" /* 'Gq%C' */ \ - ".word 0x5F5F5F43\n\t" /* '___C' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x245F5F5F" /* '$___' */ \ - ); \ - } - -#define ADD_TEXT_MARKER_FUN(m_condition) \ - if ( !(m_condition) ) \ - { \ - __asm__ volatile ( \ - ".word 0x21614062\n\t" /* '!a@b' */ \ - ".word 0x47712543\n\t" /* 'Gq%C' */ \ - ".word 0x5F5F5F54\n\t" /* '___T' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x5F5F5F5F\n\t" /* '____' */ \ - ".word 0x245F5F5F" /* '$___' */ \ - ); \ - } - -#endif diff --git a/libvideoeditor/vss/mcs/src/Android.mk b/libvideoeditor/vss/mcs/src/Android.mk index b470e6b..330aa61 100755 --- a/libvideoeditor/vss/mcs/src/Android.mk +++ b/libvideoeditor/vss/mcs/src/Android.mk @@ -47,12 +47,7 @@ LOCAL_C_INCLUDES += \ LOCAL_SHARED_LIBRARIES += libdl -# All of the shared libraries we link against. -LOCAL_LDLIBS := \ - -lpthread -ldl - LOCAL_CFLAGS += -Wno-multichar \ -DM4MCS_WITH_FAST_OPEN include $(BUILD_STATIC_LIBRARY) - diff --git a/libvideoeditor/vss/src/Android.mk b/libvideoeditor/vss/src/Android.mk index 0caa15b..0a3d64e 100755 --- a/libvideoeditor/vss/src/Android.mk +++ b/libvideoeditor/vss/src/Android.mk @@ -53,7 +53,7 @@ LOCAL_SRC_FILES:= \ LOCAL_MODULE_TAGS := optional LOCAL_SHARED_LIBRARIES := \ - libaudioflinger \ + libaudioresampler \ libaudioutils \ libbinder \ libcutils \ @@ -81,17 +81,12 @@ LOCAL_C_INCLUDES += \ $(TOP)/frameworks/av/libvideoeditor/vss/stagefrightshells/inc \ $(TOP)/frameworks/av/services/audioflinger \ $(TOP)/frameworks/native/include/media/openmax \ - $(TOP)/frameworks/native/services/audioflinger \ $(TOP)/system/media/audio_effects/include \ $(TOP)/system/media/audio_utils/include LOCAL_SHARED_LIBRARIES += libdl -# All of the shared libraries we link against. -LOCAL_LDLIBS := \ - -lpthread -ldl - LOCAL_CFLAGS += -Wno-multichar \ -DM4xVSS_RESERVED_MOOV_DISK_SPACEno \ -DDECODE_GIF_ON_SAVING diff --git a/libvideoeditor/vss/src/M4DECODER_Null.c b/libvideoeditor/vss/src/M4DECODER_Null.c index a0dad30..ce260e5 100755 --- a/libvideoeditor/vss/src/M4DECODER_Null.c +++ b/libvideoeditor/vss/src/M4DECODER_Null.c @@ -210,7 +210,7 @@ M4OSA_ERR M4DECODER_NULL_setOption(M4OSA_Context context, break;
case M4DECODER_kOptionID_EnableYuvWithEffect:
- pStreamContext->bYuvWithEffectSet = (M4OSA_Bool)pValue;
+ pStreamContext->bYuvWithEffectSet = (M4OSA_Bool)(intptr_t)pValue;
break;
case M4DECODER_kOptionID_YuvWithEffectNonContiguous:
diff --git a/libvideoeditor/vss/src/M4PCMR_CoreReader.c b/libvideoeditor/vss/src/M4PCMR_CoreReader.c index 3343254..19f07dd 100755 --- a/libvideoeditor/vss/src/M4PCMR_CoreReader.c +++ b/libvideoeditor/vss/src/M4PCMR_CoreReader.c @@ -690,7 +690,7 @@ M4OSA_ERR M4PCMR_setOption(M4OSA_Context context, M4PCMR_OptionID optionID, M4OS switch(optionID) { case M4PCMR_kPCMblockSize: - c->m_blockSize = (M4OSA_UInt32)Value; + c->m_blockSize = (M4OSA_UInt32)(uintptr_t)Value; break; default: diff --git a/libvideoeditor/vss/src/M4READER_Amr.c b/libvideoeditor/vss/src/M4READER_Amr.c index 0859157..71f0e28 100755 --- a/libvideoeditor/vss/src/M4READER_Amr.c +++ b/libvideoeditor/vss/src/M4READER_Amr.c @@ -303,7 +303,7 @@ M4OSA_ERR M4READER_AMR_getNextStream(M4OSA_Context context, M4READER_MediaFamily pStreamHandler->m_decoderSpecificInfoSize = streamDesc.decoderSpecificInfoSize; pStreamHandler->m_streamId = streamDesc.streamID; pStreamHandler->m_duration = streamDesc.duration; - pStreamHandler->m_pUserData = (void*)streamDesc.timeScale; /*trick to change*/ + pStreamHandler->m_pUserData = (void*)(intptr_t)streamDesc.timeScale; /*trick to change*/ if (streamDesc.duration > pC->m_maxDuration) { @@ -704,7 +704,7 @@ M4OSA_ERR M4READER_AMR_getNextAu(M4OSA_Context context, M4_StreamHandler *pStrea if (err == M4NO_ERROR) { - timeScale = (M4OSA_Float)(M4OSA_Int32)(pStreamHandler->m_pUserData)/1000; + timeScale = (M4OSA_Float)(M4OSA_Int32)(intptr_t)(pStreamHandler->m_pUserData)/1000; pAccessUnit->m_dataAddress = (M4OSA_MemAddr8)pAu->dataAddress; pAccessUnit->m_size = pAu->size; pAccessUnit->m_CTS = (M4_MediaTime)pAu->CTS/*/timeScale*/; diff --git a/libvideoeditor/vss/src/M4READER_Pcm.c b/libvideoeditor/vss/src/M4READER_Pcm.c index 833930b..392367f 100755 --- a/libvideoeditor/vss/src/M4READER_Pcm.c +++ b/libvideoeditor/vss/src/M4READER_Pcm.c @@ -386,7 +386,7 @@ M4OSA_ERR M4READER_PCM_getNextStream(M4OSA_Context context, M4READER_MediaFamily pC->m_pAudioStream->m_decoderSpecificInfoSize = streamDesc.decoderSpecificInfoSize; pC->m_pAudioStream->m_streamId = streamDesc.streamID; pC->m_pAudioStream->m_pUserData = - (void*)streamDesc.timeScale; /*trick to change*/ + (void*)(intptr_t)streamDesc.timeScale; /*trick to change*/ pC->m_pAudioStream->m_averageBitRate = streamDesc.averageBitrate; pC->m_pAudioStream->m_maxAUSize = pAudioStreamHandler->m_byteFrameLength*pAudioStreamHandler->m_byteSampleSize\ diff --git a/libvideoeditor/vss/src/M4VD_EXTERNAL_BitstreamParser.c b/libvideoeditor/vss/src/M4VD_EXTERNAL_BitstreamParser.c index cc67e72..fb83952 100755 --- a/libvideoeditor/vss/src/M4VD_EXTERNAL_BitstreamParser.c +++ b/libvideoeditor/vss/src/M4VD_EXTERNAL_BitstreamParser.c @@ -13,6 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include <inttypes.h> + #include "utils/Log.h" #include "M4OSA_Types.h" #include "M4OSA_Debug.h" @@ -505,7 +507,7 @@ M4OSA_ERR getAVCProfileAndLevel(M4OSA_UInt8* pDSI, M4OSA_Int32 DSISize, } constraintSet3 = (pDSI[index+2] & 0x10); - ALOGV("getAVCProfileAndLevel profile_byte %d, level_byte: %d constrain3flag", + ALOGV("getAVCProfileAndLevel profile_byte %d, level_byte: %d constrain3flag: %d", pDSI[index+1], pDSI[index+3], constraintSet3); switch (pDSI[index+1]) { @@ -586,7 +588,8 @@ M4OSA_ERR getAVCProfileAndLevel(M4OSA_UInt8* pDSI, M4OSA_Int32 DSISize, default: *pLevel = M4VIDEOEDITING_VIDEO_UNKNOWN_LEVEL; } - ALOGV("getAVCProfileAndLevel profile %ld level %ld", *pProfile, *pLevel); + ALOGV("getAVCProfileAndLevel profile %" PRId32 " level %" PRId32, + *pProfile, *pLevel); return M4NO_ERROR; } @@ -606,7 +609,7 @@ M4OSA_ERR getH263ProfileAndLevel(M4OSA_UInt8* pDSI, M4OSA_Int32 DSISize, *pLevel = M4VIDEOEDITING_VIDEO_UNKNOWN_LEVEL; return M4ERR_PARAMETER; } - ALOGV("getH263ProfileAndLevel profile_byte %d, level_byte", + ALOGV("getH263ProfileAndLevel profile_byte %d, level_byte %d", pDSI[6], pDSI[5]); /* get the H263 level */ switch (pDSI[5]) { @@ -670,7 +673,8 @@ M4OSA_ERR getH263ProfileAndLevel(M4OSA_UInt8* pDSI, M4OSA_Int32 DSISize, default: *pProfile = M4VIDEOEDITING_VIDEO_UNKNOWN_PROFILE; } - ALOGV("getH263ProfileAndLevel profile %ld level %ld", *pProfile, *pLevel); + ALOGV("getH263ProfileAndLevel profile %" PRId32 " level %" PRId32, + *pProfile, *pLevel); return M4NO_ERROR; } @@ -693,6 +697,7 @@ M4OSA_ERR getMPEG4ProfileAndLevel(M4OSA_UInt8 profileAndLevel, break; } } - ALOGV("getMPEG4ProfileAndLevel profile %ld level %ld", *pProfile, *pLevel); + ALOGV("getMPEG4ProfileAndLevel profile %" PRId32 " level %" PRId32, + *pProfile, *pLevel); return M4NO_ERROR; } diff --git a/libvideoeditor/vss/src/M4xVSS_internal.c b/libvideoeditor/vss/src/M4xVSS_internal.c index 64a6f40..84959ec 100755 --- a/libvideoeditor/vss/src/M4xVSS_internal.c +++ b/libvideoeditor/vss/src/M4xVSS_internal.c @@ -4156,12 +4156,12 @@ M4OSA_ERR M4VSS3GPP_externalVideoEffectZoom( M4VIFI_ImagePlane boxPlane[3]; - if(M4xVSS_kVideoEffectType_ZoomOut == (M4OSA_UInt32)pFunctionContext) + if((M4OSA_Void *)M4xVSS_kVideoEffectType_ZoomOut == pFunctionContext) { //ratio = 16 - (15 * pProgress->uiProgress)/1000; ratio = 16 - pProgress->uiProgress / 66 ; } - else if(M4xVSS_kVideoEffectType_ZoomIn == (M4OSA_UInt32)pFunctionContext) + else if((M4OSA_Void *)M4xVSS_kVideoEffectType_ZoomIn == pFunctionContext) { //ratio = 1 + (15 * pProgress->uiProgress)/1000; ratio = 1 + pProgress->uiProgress / 66 ; diff --git a/libvideoeditor/vss/src/VideoEditorResampler.cpp b/libvideoeditor/vss/src/VideoEditorResampler.cpp index 1129c3c..53537f0 100755 --- a/libvideoeditor/vss/src/VideoEditorResampler.cpp +++ b/libvideoeditor/vss/src/VideoEditorResampler.cpp @@ -17,7 +17,7 @@ #define LOG_NDEBUG 1 #include <audio_utils/primitives.h> #include <utils/Log.h> -#include "AudioMixer.h" +#include "AudioResampler.h" #include "VideoEditorResampler.h" namespace android { diff --git a/libvideoeditor/vss/stagefrightshells/src/VideoEditor3gpReader.cpp b/libvideoeditor/vss/stagefrightshells/src/VideoEditor3gpReader.cpp index 3c8915a..99cf9ec 100755 --- a/libvideoeditor/vss/stagefrightshells/src/VideoEditor3gpReader.cpp +++ b/libvideoeditor/vss/stagefrightshells/src/VideoEditor3gpReader.cpp @@ -776,16 +776,16 @@ M4OSA_ERR VideoEditor3gpReader_setOption(M4OSA_Context context, case M4READER_kOptionID_SetOsaFileReaderFctsPtr: break; - case M4READER_3GP_kOptionID_AudioOnly: + case static_cast<M4OSA_OptionID>(M4READER_3GP_kOptionID_AudioOnly): break; - case M4READER_3GP_kOptionID_VideoOnly: + case static_cast<M4OSA_OptionID>(M4READER_3GP_kOptionID_VideoOnly): break; - case M4READER_3GP_kOptionID_FastOpenMode: + case static_cast<M4OSA_OptionID>(M4READER_3GP_kOptionID_FastOpenMode): break; - case M4READER_kOptionID_MaxMetadataSize: + case static_cast<M4OSA_OptionID>(M4READER_kOptionID_MaxMetadataSize): break; default: diff --git a/libvideoeditor/vss/stagefrightshells/src/VideoEditorAudioDecoder.cpp b/libvideoeditor/vss/stagefrightshells/src/VideoEditorAudioDecoder.cpp index 9b35d07..e4c7ea1 100755 --- a/libvideoeditor/vss/stagefrightshells/src/VideoEditorAudioDecoder.cpp +++ b/libvideoeditor/vss/stagefrightshells/src/VideoEditorAudioDecoder.cpp @@ -809,7 +809,7 @@ M4OSA_ERR VideoEditorAudioDecoder_setOption(M4AD_Context pContext, pDecoderContext = (VideoEditorAudioDecoder_Context*)pContext; switch( optionID ) { - case M4AD_kOptionID_UserParam: + case static_cast<M4OSA_UInt32>(M4AD_kOptionID_UserParam): ALOGV("VideoEditorAudioDecodersetOption UserParam is not supported"); err = M4ERR_NOT_IMPLEMENTED; break; diff --git a/libvideoeditor/vss/stagefrightshells/src/VideoEditorBuffer.c b/libvideoeditor/vss/stagefrightshells/src/VideoEditorBuffer.c index f4cfa7c..5a7b28e 100755 --- a/libvideoeditor/vss/stagefrightshells/src/VideoEditorBuffer.c +++ b/libvideoeditor/vss/stagefrightshells/src/VideoEditorBuffer.c @@ -22,6 +22,8 @@ #undef M4OSA_TRACE_LEVEL #define M4OSA_TRACE_LEVEL 1 +#include <inttypes.h> + #include "VideoEditorBuffer.h" #include "utils/Log.h" @@ -55,7 +57,7 @@ M4OSA_ERR VIDEOEDITOR_BUFFER_allocatePool(VIDEOEDITOR_BUFFER_Pool** ppool, VIDEOEDITOR_BUFFER_Pool* pool; M4OSA_UInt32 index; - ALOGV("VIDEOEDITOR_BUFFER_allocatePool : ppool = 0x%x nbBuffers = %d ", + ALOGV("VIDEOEDITOR_BUFFER_allocatePool : ppool = %p nbBuffers = %" PRIu32, ppool, nbBuffers); pool = M4OSA_NULL; @@ -131,7 +133,7 @@ M4OSA_ERR VIDEOEDITOR_BUFFER_freePool(VIDEOEDITOR_BUFFER_Pool* ppool) M4OSA_ERR err; M4OSA_UInt32 j = 0; - ALOGV("VIDEOEDITOR_BUFFER_freePool : ppool = 0x%x", ppool); + ALOGV("VIDEOEDITOR_BUFFER_freePool : ppool = %p", ppool); err = M4NO_ERROR; @@ -200,7 +202,7 @@ M4OSA_ERR VIDEOEDITOR_BUFFER_getBuffer(VIDEOEDITOR_BUFFER_Pool* ppool, /* case where a buffer has been found */ *pNXPBuffer = &(ppool->pNXPBuffer[ibuf]); - ALOGV("VIDEOEDITOR_BUFFER_getBuffer: idx = %d", ibuf); + ALOGV("VIDEOEDITOR_BUFFER_getBuffer: idx = %" PRIu32, ibuf); return(err); } diff --git a/libvideoeditor/vss/stagefrightshells/src/VideoEditorMp3Reader.cpp b/libvideoeditor/vss/stagefrightshells/src/VideoEditorMp3Reader.cpp index af53c54..2e0d05d 100755 --- a/libvideoeditor/vss/stagefrightshells/src/VideoEditorMp3Reader.cpp +++ b/libvideoeditor/vss/stagefrightshells/src/VideoEditorMp3Reader.cpp @@ -334,8 +334,8 @@ M4OSA_ERR VideoEditorMp3Reader_setOption(M4OSA_Context context, (VideoEditorMp3Reader_Context*)context; M4OSA_ERR err = M4NO_ERROR; - ALOGV("VideoEditorMp3Reader_Context begin: optionId: %d Value: %d ", - (int)optionId,(int)pValue); + ALOGV("VideoEditorMp3Reader_Context begin: optionId: %u Value: %p ", + optionId, pValue); M4OSA_DEBUG_IF1((M4OSA_NULL == pReaderContext), M4ERR_PARAMETER, "invalid context pointer"); diff --git a/libvideoeditor/vss/stagefrightshells/src/VideoEditorUtils.cpp b/libvideoeditor/vss/stagefrightshells/src/VideoEditorUtils.cpp index 5a7237d..d264a2e 100755 --- a/libvideoeditor/vss/stagefrightshells/src/VideoEditorUtils.cpp +++ b/libvideoeditor/vss/stagefrightshells/src/VideoEditorUtils.cpp @@ -84,17 +84,17 @@ void displayMetaData(const sp<MetaData> meta) { LOG1("displayMetaData kKeyBitRate %d", int32Data); } if (meta->findData(kKeyESDS, &type, &data, &size)) { - LOG1("displayMetaData kKeyESDS type=%d size=%d", type, size); + LOG1("displayMetaData kKeyESDS type=%d size=%zu", type, size); } if (meta->findData(kKeyAVCC, &type, &data, &size)) { - LOG1("displayMetaData kKeyAVCC data=0x%X type=%d size=%d", + LOG1("displayMetaData kKeyAVCC data=0x%X type=%d size=%zu", *((unsigned int*)data), type, size); } if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) { - LOG1("displayMetaData kKeyVorbisInfo type=%d size=%d", type, size); + LOG1("displayMetaData kKeyVorbisInfo type=%d size=%zu", type, size); } if (meta->findData(kKeyVorbisBooks, &type, &data, &size)) { - LOG1("displayMetaData kKeyVorbisBooks type=%d size=%d", type, size); + LOG1("displayMetaData kKeyVorbisBooks type=%d size=%zu", type, size); } if (meta->findInt32(kKeyWantsNALFragments, &int32Data)) { LOG1("displayMetaData kKeyWantsNALFragments %d", int32Data); @@ -115,7 +115,7 @@ void displayMetaData(const sp<MetaData> meta) { LOG1("displayMetaData kKeyColorFormat %d", int32Data); } if (meta->findPointer(kKeyPlatformPrivate, &ptr)) { - LOG1("displayMetaData kKeyPlatformPrivate pointer=0x%x", (int32_t) ptr); + LOG1("displayMetaData kKeyPlatformPrivate pointer=%p", ptr); } if (meta->findCString(kKeyDecoderComponent, &charData)) { LOG1("displayMetaData kKeyDecoderComponent %s", charData); @@ -151,7 +151,7 @@ void displayMetaData(const sp<MetaData> meta) { LOG1("displayMetaData kKeyYear %s", charData); } if (meta->findData(kKeyAlbumArt, &type, &data, &size)) { - LOG1("displayMetaData kKeyAlbumArt type=%d size=%d", type, size); + LOG1("displayMetaData kKeyAlbumArt type=%d size=%zu", type, size); } if (meta->findCString(kKeyAlbumArtMIME, &charData)) { LOG1("displayMetaData kKeyAlbumArtMIME %s", charData); @@ -277,7 +277,7 @@ status_t buildAVCCodecSpecificData(uint8_t **pOutputData, size_t *pOutputSize, } if (size < 4) { - ALOGE("Codec specific data length too short: %d", size); + ALOGE("Codec specific data length too short: %zu", size); return ERROR_MALFORMED; } @@ -286,7 +286,7 @@ status_t buildAVCCodecSpecificData(uint8_t **pOutputData, size_t *pOutputSize, // 2 bytes for each of the parameter set length field // plus the 7 bytes for the header if (size < 4 + 7) { - ALOGE("Codec specific data length too short: %d", size); + ALOGE("Codec specific data length too short: %zu", size); return ERROR_MALFORMED; } @@ -355,7 +355,7 @@ status_t buildAVCCodecSpecificData(uint8_t **pOutputData, size_t *pOutputSize, } if (nSeqParamSets > 0x1F) { - ALOGE("Too many seq parameter sets (%d) found", nSeqParamSets); + ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets); return ERROR_MALFORMED; } } @@ -368,7 +368,7 @@ status_t buildAVCCodecSpecificData(uint8_t **pOutputData, size_t *pOutputSize, return ERROR_MALFORMED; } if (nPicParamSets > 0xFF) { - ALOGE("Too many pic parameter sets (%d) found", nPicParamSets); + ALOGE("Too many pic parameter sets (%zu) found", nPicParamSets); return ERROR_MALFORMED; } } diff --git a/libvideoeditor/vss/stagefrightshells/src/VideoEditorVideoEncoder.cpp b/libvideoeditor/vss/stagefrightshells/src/VideoEditorVideoEncoder.cpp index 4787680..ca7db68 100755 --- a/libvideoeditor/vss/stagefrightshells/src/VideoEditorVideoEncoder.cpp +++ b/libvideoeditor/vss/stagefrightshells/src/VideoEditorVideoEncoder.cpp @@ -857,7 +857,7 @@ M4OSA_ERR VideoEditorVideoEncoder_processOutputBuffer( ALOGV("VideoEditorVideoEncoder_processOutputBuffer : buffer is empty"); goto cleanUp; } - VIDEOEDITOR_CHECK(0 == ((M4OSA_UInt32)buffer->data())%4, M4ERR_PARAMETER); + VIDEOEDITOR_CHECK(0 == (((intptr_t)buffer->data())%4), M4ERR_PARAMETER); VIDEOEDITOR_CHECK(buffer->meta_data().get(), M4ERR_PARAMETER); if ( buffer->meta_data()->findInt32(kKeyIsCodecConfig, &i32Tmp) && i32Tmp ){ { // Display the DSI diff --git a/libvideoeditor/vss/video_filters/src/Android.mk b/libvideoeditor/vss/video_filters/src/Android.mk index 85a530c..88fa974 100755 --- a/libvideoeditor/vss/video_filters/src/Android.mk +++ b/libvideoeditor/vss/video_filters/src/Android.mk @@ -47,11 +47,6 @@ LOCAL_C_INCLUDES += \ LOCAL_SHARED_LIBRARIES += libdl -# All of the shared libraries we link against. -LOCAL_LDLIBS := \ - -lpthread -ldl - LOCAL_CFLAGS += -Wno-multichar include $(BUILD_SHARED_LIBRARY) - diff --git a/media/common_time/utils.cpp b/media/common_time/utils.cpp index 6539171..91cf2fd 100644 --- a/media/common_time/utils.cpp +++ b/media/common_time/utils.cpp @@ -59,7 +59,7 @@ void serializeSockaddr(Parcel* p, const struct sockaddr_storage* addr) { } void deserializeSockaddr(const Parcel* p, struct sockaddr_storage* addr) { - memset(addr, 0, sizeof(addr)); + memset(addr, 0, sizeof(*addr)); addr->ss_family = p->readInt32(); switch(addr->ss_family) { diff --git a/media/libcpustats/Android.mk b/media/libcpustats/Android.mk index b506353..ee283a6 100644 --- a/media/libcpustats/Android.mk +++ b/media/libcpustats/Android.mk @@ -1,4 +1,4 @@ -LOCAL_PATH:= $(call my-dir) +LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) @@ -8,4 +8,6 @@ LOCAL_SRC_FILES := \ LOCAL_MODULE := libcpustats +LOCAL_CFLAGS := -std=gnu++11 -Werror + include $(BUILD_STATIC_LIBRARY) diff --git a/media/libcpustats/ThreadCpuUsage.cpp b/media/libcpustats/ThreadCpuUsage.cpp index 637402a..cfdcb51 100644 --- a/media/libcpustats/ThreadCpuUsage.cpp +++ b/media/libcpustats/ThreadCpuUsage.cpp @@ -21,7 +21,6 @@ #include <stdlib.h> #include <time.h> -#include <utils/Debug.h> #include <utils/Log.h> #include <cpustats/ThreadCpuUsage.h> @@ -218,7 +217,7 @@ uint32_t ThreadCpuUsage::getCpukHz(int cpuNum) #define FREQ_SIZE 64 char freq_path[FREQ_SIZE]; #define FREQ_DIGIT 27 - COMPILE_TIME_ASSERT_FUNCTION_SCOPE(MAX_CPU <= 10); + static_assert(MAX_CPU <= 10, "MAX_CPU too large"); #define FREQ_PATH "/sys/devices/system/cpu/cpu?/cpufreq/scaling_cur_freq" strlcpy(freq_path, FREQ_PATH, sizeof(freq_path)); freq_path[FREQ_DIGIT] = cpuNum + '0'; diff --git a/media/libeffects/downmix/Android.mk b/media/libeffects/downmix/Android.mk index 5d0a87c..2bb6dbe 100644 --- a/media/libeffects/downmix/Android.mk +++ b/media/libeffects/downmix/Android.mk @@ -13,7 +13,7 @@ LOCAL_MODULE:= libdownmix LOCAL_MODULE_TAGS := optional -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true) LOCAL_LDLIBS += -ldl diff --git a/media/libeffects/downmix/EffectDownmix.c b/media/libeffects/downmix/EffectDownmix.c index f779876..1663d47 100644 --- a/media/libeffects/downmix/EffectDownmix.c +++ b/media/libeffects/downmix/EffectDownmix.c @@ -16,7 +16,8 @@ #define LOG_TAG "EffectDownmix" //#define LOG_NDEBUG 0 -#include <cutils/log.h> +#include <log/log.h> +#include <inttypes.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> @@ -99,7 +100,7 @@ const int kNbEffects = sizeof(gDescriptors) / sizeof(const effect_descriptor_t * // strictly for testing, logs the indices of the channels for a given mask, // uses the same code as Downmix_foldGeneric() void Downmix_testIndexComputation(uint32_t mask) { - ALOGI("Testing index computation for 0x%x:", mask); + ALOGI("Testing index computation for 0x%" PRIx32 ":", mask); // check against unsupported channels if (mask & kUnsupported) { ALOGE("Unsupported channels (top or front left/right of center)"); @@ -220,7 +221,7 @@ int32_t DownmixLib_Create(const effect_uuid_t *uuid, *pHandle = (effect_handle_t) module; - ALOGV("DownmixLib_Create() %p , size %d", module, sizeof(downmix_module_t)); + ALOGV("DownmixLib_Create() %p , size %zu", module, sizeof(downmix_module_t)); return 0; } @@ -254,7 +255,7 @@ int32_t DownmixLib_GetDescriptor(const effect_uuid_t *uuid, effect_descriptor_t ALOGV("DownmixLib_GetDescriptor() i=%d", i); if (memcmp(uuid, &gDescriptors[i]->uuid, sizeof(effect_uuid_t)) == 0) { memcpy(pDescriptor, gDescriptors[i], sizeof(effect_descriptor_t)); - ALOGV("EffectGetDescriptor - UUID matched downmix type %d, UUID = %x", + ALOGV("EffectGetDescriptor - UUID matched downmix type %d, UUID = %" PRIx32, i, gDescriptors[i]->uuid.timeLow); return 0; } @@ -328,7 +329,7 @@ static int Downmix_Process(effect_handle_t self, // bypass the optimized downmix routines for the common formats if (!Downmix_foldGeneric( downmixInputChannelMask, pSrc, pDst, numFrames, accumulate)) { - ALOGE("Multichannel configuration 0x%x is not supported", downmixInputChannelMask); + ALOGE("Multichannel configuration 0x%" PRIx32 " is not supported", downmixInputChannelMask); return -EINVAL; } break; @@ -352,7 +353,7 @@ static int Downmix_Process(effect_handle_t self, default: if (!Downmix_foldGeneric( downmixInputChannelMask, pSrc, pDst, numFrames, accumulate)) { - ALOGE("Multichannel configuration 0x%x is not supported", downmixInputChannelMask); + ALOGE("Multichannel configuration 0x%" PRIx32 " is not supported", downmixInputChannelMask); return -EINVAL; } break; @@ -380,7 +381,7 @@ static int Downmix_Command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdS pDownmixer = (downmix_object_t*) &pDwmModule->context; - ALOGV("Downmix_Command command %d cmdSize %d",cmdCode, cmdSize); + ALOGV("Downmix_Command command %" PRIu32 " cmdSize %" PRIu32, cmdCode, cmdSize); switch (cmdCode) { case EFFECT_CMD_INIT: @@ -404,7 +405,7 @@ static int Downmix_Command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdS break; case EFFECT_CMD_GET_PARAM: - ALOGV("Downmix_Command EFFECT_CMD_GET_PARAM pCmdData %p, *replySize %d, pReplyData: %p", + ALOGV("Downmix_Command EFFECT_CMD_GET_PARAM pCmdData %p, *replySize %" PRIu32 ", pReplyData: %p", pCmdData, *replySize, pReplyData); if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) || pReplyData == NULL || @@ -413,7 +414,7 @@ static int Downmix_Command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdS } effect_param_t *rep = (effect_param_t *) pReplyData; memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + sizeof(int32_t)); - ALOGV("Downmix_Command EFFECT_CMD_GET_PARAM param %d, replySize %d", + ALOGV("Downmix_Command EFFECT_CMD_GET_PARAM param %" PRId32 ", replySize %" PRIu32, *(int32_t *)rep->data, rep->vsize); rep->status = Downmix_getParameter(pDownmixer, *(int32_t *)rep->data, &rep->vsize, rep->data + sizeof(int32_t)); @@ -421,8 +422,8 @@ static int Downmix_Command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdS break; case EFFECT_CMD_SET_PARAM: - ALOGV("Downmix_Command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %d, " \ - "pReplyData %p", cmdSize, pCmdData, *replySize, pReplyData); + ALOGV("Downmix_Command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %" PRIu32 + ", pReplyData %p", cmdSize, pCmdData, *replySize, pReplyData); if (pCmdData == NULL || (cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t))) || pReplyData == NULL || *replySize != (int)sizeof(int32_t)) { return -EINVAL; @@ -471,7 +472,7 @@ static int Downmix_Command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdS return -EINVAL; } // FIXME change type if playing on headset vs speaker - ALOGV("Downmix_Command EFFECT_CMD_SET_DEVICE: 0x%08x", *(uint32_t *)pCmdData); + ALOGV("Downmix_Command EFFECT_CMD_SET_DEVICE: 0x%08" PRIx32, *(uint32_t *)pCmdData); break; case EFFECT_CMD_SET_VOLUME: { @@ -491,7 +492,7 @@ static int Downmix_Command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdS if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t)) { return -EINVAL; } - ALOGV("Downmix_Command EFFECT_CMD_SET_AUDIO_MODE: %d", *(uint32_t *)pCmdData); + ALOGV("Downmix_Command EFFECT_CMD_SET_AUDIO_MODE: %" PRIu32, *(uint32_t *)pCmdData); break; case EFFECT_CMD_SET_CONFIG_REVERSE: @@ -500,7 +501,7 @@ static int Downmix_Command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdS break; default: - ALOGW("Downmix_Command invalid command %d",cmdCode); + ALOGW("Downmix_Command invalid command %" PRIu32, cmdCode); return -EINVAL; } @@ -629,7 +630,9 @@ int Downmix_Configure(downmix_module_t *pDwmModule, effect_config_t *pConfig, bo return -EINVAL; } - memcpy(&pDwmModule->config, pConfig, sizeof(effect_config_t)); + if (&pDwmModule->config != pConfig) { + memcpy(&pDwmModule->config, pConfig, sizeof(effect_config_t)); + } if (init) { pDownmixer->type = DOWNMIX_TYPE_FOLD; @@ -697,31 +700,31 @@ int Downmix_Reset(downmix_object_t *pDownmixer, bool init) { * *---------------------------------------------------------------------------- */ -int Downmix_setParameter(downmix_object_t *pDownmixer, int32_t param, size_t size, void *pValue) { +int Downmix_setParameter(downmix_object_t *pDownmixer, int32_t param, uint32_t size, void *pValue) { int16_t value16; - ALOGV("Downmix_setParameter, context %p, param %d, value16 %d, value32 %d", + ALOGV("Downmix_setParameter, context %p, param %" PRId32 ", value16 %" PRId16 ", value32 %" PRId32, pDownmixer, param, *(int16_t *)pValue, *(int32_t *)pValue); switch (param) { case DOWNMIX_PARAM_TYPE: if (size != sizeof(downmix_type_t)) { - ALOGE("Downmix_setParameter(DOWNMIX_PARAM_TYPE) invalid size %d, should be %d", + ALOGE("Downmix_setParameter(DOWNMIX_PARAM_TYPE) invalid size %" PRIu32 ", should be %zu", size, sizeof(downmix_type_t)); return -EINVAL; } value16 = *(int16_t *)pValue; - ALOGV("set DOWNMIX_PARAM_TYPE, type %d", value16); + ALOGV("set DOWNMIX_PARAM_TYPE, type %" PRId16, value16); if (!((value16 > DOWNMIX_TYPE_INVALID) && (value16 <= DOWNMIX_TYPE_LAST))) { - ALOGE("Downmix_setParameter invalid DOWNMIX_PARAM_TYPE value %d", value16); + ALOGE("Downmix_setParameter invalid DOWNMIX_PARAM_TYPE value %" PRId16, value16); return -EINVAL; } else { pDownmixer->type = (downmix_type_t) value16; break; default: - ALOGE("Downmix_setParameter unknown parameter %d", param); + ALOGE("Downmix_setParameter unknown parameter %" PRId32, param); return -EINVAL; } } @@ -753,24 +756,24 @@ int Downmix_setParameter(downmix_object_t *pDownmixer, int32_t param, size_t siz * *---------------------------------------------------------------------------- */ -int Downmix_getParameter(downmix_object_t *pDownmixer, int32_t param, size_t *pSize, void *pValue) { +int Downmix_getParameter(downmix_object_t *pDownmixer, int32_t param, uint32_t *pSize, void *pValue) { int16_t *pValue16; switch (param) { case DOWNMIX_PARAM_TYPE: if (*pSize < sizeof(int16_t)) { - ALOGE("Downmix_getParameter invalid parameter size %d for DOWNMIX_PARAM_TYPE", *pSize); + ALOGE("Downmix_getParameter invalid parameter size %" PRIu32 " for DOWNMIX_PARAM_TYPE", *pSize); return -EINVAL; } pValue16 = (int16_t *)pValue; *pValue16 = (int16_t) pDownmixer->type; *pSize = sizeof(int16_t); - ALOGV("Downmix_getParameter DOWNMIX_PARAM_TYPE is %d", *pValue16); + ALOGV("Downmix_getParameter DOWNMIX_PARAM_TYPE is %" PRId16, *pValue16); break; default: - ALOGE("Downmix_getParameter unknown parameter %d", param); + ALOGE("Downmix_getParameter unknown parameter %" PRId16, param); return -EINVAL; } diff --git a/media/libeffects/downmix/EffectDownmix.h b/media/libeffects/downmix/EffectDownmix.h index cb6b957..fcb3c9e 100644 --- a/media/libeffects/downmix/EffectDownmix.h +++ b/media/libeffects/downmix/EffectDownmix.h @@ -93,8 +93,8 @@ static int Downmix_GetDescriptor(effect_handle_t self, int Downmix_Init(downmix_module_t *pDwmModule); int Downmix_Configure(downmix_module_t *pDwmModule, effect_config_t *pConfig, bool init); int Downmix_Reset(downmix_object_t *pDownmixer, bool init); -int Downmix_setParameter(downmix_object_t *pDownmixer, int32_t param, size_t size, void *pValue); -int Downmix_getParameter(downmix_object_t *pDownmixer, int32_t param, size_t *pSize, void *pValue); +int Downmix_setParameter(downmix_object_t *pDownmixer, int32_t param, uint32_t size, void *pValue); +int Downmix_getParameter(downmix_object_t *pDownmixer, int32_t param, uint32_t *pSize, void *pValue); void Downmix_foldFromQuad(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate); void Downmix_foldFromSurround(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate); diff --git a/media/libeffects/factory/Android.mk b/media/libeffects/factory/Android.mk index 60a6ce5..a932af7 100644 --- a/media/libeffects/factory/Android.mk +++ b/media/libeffects/factory/Android.mk @@ -9,7 +9,6 @@ LOCAL_SRC_FILES:= \ LOCAL_SHARED_LIBRARIES := \ libcutils liblog -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES) LOCAL_MODULE:= libeffects LOCAL_SHARED_LIBRARIES += libdl diff --git a/media/libeffects/factory/EffectsFactory.c b/media/libeffects/factory/EffectsFactory.c index f8d6041..6d30d64 100644 --- a/media/libeffects/factory/EffectsFactory.c +++ b/media/libeffects/factory/EffectsFactory.c @@ -368,27 +368,21 @@ int EffectRelease(effect_handle_t handle) } if (e1 == NULL) { ret = -ENOENT; - pthread_mutex_unlock(&gLibLock); goto exit; } // release effect in library if (fx->lib == NULL) { ALOGW("EffectRelease() fx %p library already unloaded", handle); - pthread_mutex_unlock(&gLibLock); } else { pthread_mutex_lock(&fx->lib->lock); - // Releasing the gLibLock here as the list access is over as the - // effect is removed from the list. - // If the gLibLock is not released, we will have a deadlock situation - // since we call the sub effect release inside the EffectRelease of Proxy - pthread_mutex_unlock(&gLibLock); fx->lib->desc->release_effect(fx->subItfe); pthread_mutex_unlock(&fx->lib->lock); } free(fx); exit: + pthread_mutex_unlock(&gLibLock); return ret; } @@ -404,8 +398,8 @@ int EffectIsNullUuid(const effect_uuid_t *uuid) // is pointed by the first argument. It searches the gSubEffectList for the // matching uuid and then copies the corresponding sub effect descriptors // to the inout param -int EffectGetSubEffects(const effect_uuid_t *uuid, - effect_descriptor_t *pDescriptors, size_t size) +int EffectGetSubEffects(const effect_uuid_t *uuid, sub_effect_entry_t **pSube, + size_t size) { ALOGV("EffectGetSubEffects() UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X" "%02X\n",uuid->timeLow, uuid->timeMid, uuid->timeHiAndVersion, @@ -413,8 +407,7 @@ int EffectGetSubEffects(const effect_uuid_t *uuid, uuid->node[3],uuid->node[4],uuid->node[5]); // Check if the size of the desc buffer is large enough for 2 subeffects - if ((uuid == NULL) || (pDescriptors == NULL) || - (size < 2*sizeof(effect_descriptor_t))) { + if ((uuid == NULL) || (pSube == NULL) || (size < 2)) { ALOGW("NULL pointer or insufficient memory. Cannot query subeffects"); return -EINVAL; } @@ -432,11 +425,10 @@ int EffectGetSubEffects(const effect_uuid_t *uuid, list_elem_t *subefx = e->sub_elem; while (subefx != NULL) { subeffect = (sub_effect_entry_t*)subefx->object; - d = (effect_descriptor_t*)(subeffect->object); - pDescriptors[count++] = *d; + pSube[count++] = subeffect; subefx = subefx->next; } - ALOGV("EffectGetSubEffects end - copied the sub effect descriptors"); + ALOGV("EffectGetSubEffects end - copied the sub effect structures"); return count; } e = e->next; diff --git a/media/libeffects/factory/EffectsFactory.h b/media/libeffects/factory/EffectsFactory.h index 147ff18..560b485 100644 --- a/media/libeffects/factory/EffectsFactory.h +++ b/media/libeffects/factory/EffectsFactory.h @@ -20,7 +20,7 @@ #include <cutils/log.h> #include <pthread.h> #include <dirent.h> -#include <media/EffectsFactoryApi.h> +#include <hardware/audio_effect.h> #if __cplusplus extern "C" { @@ -66,6 +66,32 @@ typedef struct sub_effect_entry_s { void *object; } sub_effect_entry_t; + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectGetSubEffects +// +// Description: Returns the descriptors of the sub effects of the effect +// whose uuid is pointed to by first argument. +// +// Input: +// pEffectUuid: pointer to the effect uuid. +// size: max number of sub_effect_entry_t * in pSube. +// +// Input/Output: +// pSube: address where to return the sub effect structures. +// Output: +// returned value: 0 successful operation. +// -ENODEV factory failed to initialize +// -EINVAL invalid pEffectUuid or pDescriptor +// -ENOENT no effect with this uuid found +// *pDescriptor: updated with the sub effect descriptors. +// +//////////////////////////////////////////////////////////////////////////////// +int EffectGetSubEffects(const effect_uuid_t *pEffectUuid, + sub_effect_entry_t **pSube, + size_t size); + #if __cplusplus } // extern "C" #endif diff --git a/media/libeffects/loudness/Android.mk b/media/libeffects/loudness/Android.mk index dcb7b27..edf964e 100644 --- a/media/libeffects/loudness/Android.mk +++ b/media/libeffects/loudness/Android.mk @@ -14,7 +14,7 @@ LOCAL_SHARED_LIBRARIES := \ liblog \ libstlport -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx LOCAL_MODULE:= libldnhncr LOCAL_C_INCLUDES := \ diff --git a/media/libeffects/loudness/EffectLoudnessEnhancer.cpp b/media/libeffects/loudness/EffectLoudnessEnhancer.cpp index 91ed677..3c2b320 100644 --- a/media/libeffects/loudness/EffectLoudnessEnhancer.cpp +++ b/media/libeffects/loudness/EffectLoudnessEnhancer.cpp @@ -453,13 +453,13 @@ const struct effect_interface_s gLEInterface = { // This is the only symbol that needs to be exported __attribute__ ((visibility ("default"))) audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { - tag : AUDIO_EFFECT_LIBRARY_TAG, - version : EFFECT_LIBRARY_API_VERSION, - name : "Loudness Enhancer Library", - implementor : "The Android Open Source Project", - create_effect : LELib_Create, - release_effect : LELib_Release, - get_descriptor : LELib_GetDescriptor, + .tag = AUDIO_EFFECT_LIBRARY_TAG, + .version = EFFECT_LIBRARY_API_VERSION, + .name = "Loudness Enhancer Library", + .implementor = "The Android Open Source Project", + .create_effect = LELib_Create, + .release_effect = LELib_Release, + .get_descriptor = LELib_GetDescriptor, }; }; // extern "C" diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c index 32c4ce0..35e5bc8 100644 --- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c +++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c @@ -178,7 +178,7 @@ LVDBE_ReturnStatus_en LVDBE_Init(LVDBE_Handle_t *phInstance, { return(LVDBE_NULLADDRESS); } - if (((LVM_UINT32)pMemoryTable->Region[i].pBaseAddress % pMemoryTable->Region[i].Alignment)!=0){ + if (((uintptr_t)pMemoryTable->Region[i].pBaseAddress % pMemoryTable->Region[i].Alignment)!=0){ return(LVDBE_ALIGNMENTERROR); } } diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c index 794271b..f5a01f3 100644 --- a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c +++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c @@ -99,7 +99,7 @@ LVM_ReturnStatus_en LVM_Process(LVM_Handle_t hInstance, /* * Check the buffer alignment */ - if((((LVM_UINT32)pInData % 4) != 0) || (((LVM_UINT32)pOutData % 4) != 0)) + if((((uintptr_t)pInData % 4) != 0) || (((uintptr_t)pOutData % 4) != 0)) { return(LVM_ALIGNMENTERROR); } diff --git a/media/libeffects/lvm/lib/Common/lib/InstAlloc.h b/media/libeffects/lvm/lib/Common/lib/InstAlloc.h index c6954f2..7f725f4 100644 --- a/media/libeffects/lvm/lib/Common/lib/InstAlloc.h +++ b/media/libeffects/lvm/lib/Common/lib/InstAlloc.h @@ -29,7 +29,7 @@ extern "C" { typedef struct { LVM_UINT32 TotalSize; /* Accumulative total memory size */ - LVM_UINT32 pNextMember; /* Pointer to the next instance member to be allocated */ + uintptr_t pNextMember; /* Pointer to the next instance member to be allocated */ } INST_ALLOC; diff --git a/media/libeffects/lvm/lib/Common/lib/LVM_Types.h b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h index 81655dd..0c6fb25 100644 --- a/media/libeffects/lvm/lib/Common/lib/LVM_Types.h +++ b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h @@ -29,6 +29,7 @@ extern "C" { #endif /* __cplusplus */ +#include <stdint.h> /****************************************************************************************/ /* */ @@ -85,14 +86,14 @@ extern "C" { typedef char LVM_CHAR; /* ASCII character */ -typedef char LVM_INT8; /* Signed 8-bit word */ -typedef unsigned char LVM_UINT8; /* Unsigned 8-bit word */ +typedef int8_t LVM_INT8; /* Signed 8-bit word */ +typedef uint8_t LVM_UINT8; /* Unsigned 8-bit word */ -typedef short LVM_INT16; /* Signed 16-bit word */ -typedef unsigned short LVM_UINT16; /* Unsigned 16-bit word */ +typedef int16_t LVM_INT16; /* Signed 16-bit word */ +typedef uint16_t LVM_UINT16; /* Unsigned 16-bit word */ -typedef long LVM_INT32; /* Signed 32-bit word */ -typedef unsigned long LVM_UINT32; /* Unsigned 32-bit word */ +typedef int32_t LVM_INT32; /* Signed 32-bit word */ +typedef uint32_t LVM_UINT32; /* Unsigned 32-bit word */ /****************************************************************************************/ diff --git a/media/libeffects/lvm/lib/Common/src/InstAlloc.c b/media/libeffects/lvm/lib/Common/src/InstAlloc.c index 481df84..a89a5c3 100644 --- a/media/libeffects/lvm/lib/Common/src/InstAlloc.c +++ b/media/libeffects/lvm/lib/Common/src/InstAlloc.c @@ -30,7 +30,7 @@ void InstAlloc_Init( INST_ALLOC *pms, void *StartAddr ) { pms->TotalSize = 3; - pms->pNextMember = (LVM_UINT32)(((LVM_UINT32)StartAddr + 3) & 0xFFFFFFFC);/* This code will fail if the platform address space is more than 32-bits*/ + pms->pNextMember = (((uintptr_t)StartAddr + 3) & (uintptr_t)~3); } @@ -51,7 +51,7 @@ void* InstAlloc_AddMember( INST_ALLOC *pms, void *NewMemberAddress; /* Variable to temporarily store the return value */ NewMemberAddress = (void*)pms->pNextMember; - Size = ((Size + 3) & 0xFFFFFFFC); /* Ceil the size to a multiple of four */ + Size = ((Size + 3) & (LVM_UINT32)~3); /* Ceil the size to a multiple of four */ pms->TotalSize += Size; pms->pNextMember += Size; @@ -84,30 +84,30 @@ LVM_UINT32 InstAlloc_GetTotal( INST_ALLOC *pms) void InstAlloc_InitAll( INST_ALLOC *pms, LVM_MemoryTable_st *pMemoryTable) { - LVM_UINT32 StartAddr; + uintptr_t StartAddr; - StartAddr = (LVM_UINT32)pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress; + StartAddr = (uintptr_t)pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress; pms[0].TotalSize = 3; - pms[0].pNextMember = (LVM_UINT32)(((LVM_UINT32)StartAddr + 3) & 0xFFFFFFFC); + pms[0].pNextMember = ((StartAddr + 3) & (uintptr_t)~3); - StartAddr = (LVM_UINT32)pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress; + StartAddr = (uintptr_t)pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress; pms[1].TotalSize = 3; - pms[1].pNextMember = (LVM_UINT32)(((LVM_UINT32)StartAddr + 3) & 0xFFFFFFFC); + pms[1].pNextMember = ((StartAddr + 3) & (uintptr_t)~3); - StartAddr = (LVM_UINT32)pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress; + StartAddr = (uintptr_t)pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress; pms[2].TotalSize = 3; - pms[2].pNextMember = (LVM_UINT32)(((LVM_UINT32)StartAddr + 3) & 0xFFFFFFFC); + pms[2].pNextMember = ((StartAddr + 3) & (uintptr_t)~3); - StartAddr = (LVM_UINT32)pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress; + StartAddr = (uintptr_t)pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress; pms[3].TotalSize = 3; - pms[3].pNextMember = (LVM_UINT32)(((LVM_UINT32)StartAddr + 3) & 0xFFFFFFFC); + pms[3].pNextMember = ((StartAddr + 3) & (uintptr_t)~3); } diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c index c4767a8..e01c1c5 100644 --- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c +++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c @@ -25,6 +25,7 @@ #include "LVEQNB.h" #include "LVEQNB_Private.h" #include "InstAlloc.h" +#include <string.h> /* For memset */ /****************************************************************************************/ /* */ diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c index ac3c740..58f58ed 100644 --- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c +++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c @@ -77,7 +77,7 @@ LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t hInstance, } /* Check if the input and output data buffers are 32-bit aligned */ - if ((((LVM_INT32)pInData % 4) != 0) || (((LVM_INT32)pOutData % 4) != 0)) + if ((((uintptr_t)pInData % 4) != 0) || (((uintptr_t)pOutData % 4) != 0)) { return LVEQNB_ALIGNMENTERROR; } diff --git a/media/libeffects/lvm/wrapper/Android.mk b/media/libeffects/lvm/wrapper/Android.mk index f1af389..68ba34c 100644 --- a/media/libeffects/lvm/wrapper/Android.mk +++ b/media/libeffects/lvm/wrapper/Android.mk @@ -13,7 +13,7 @@ LOCAL_CFLAGS += -fvisibility=hidden LOCAL_MODULE:= libbundlewrapper -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx LOCAL_STATIC_LIBRARIES += libmusicbundle @@ -42,7 +42,7 @@ LOCAL_CFLAGS += -fvisibility=hidden LOCAL_MODULE:= libreverbwrapper -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx LOCAL_STATIC_LIBRARIES += libreverb diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp index 28d239a..db5c78f 100644 --- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp +++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp @@ -138,22 +138,22 @@ void Effect_getConfig (EffectContext *pContext, effect_config_t *pConfi int BassBoost_setParameter (EffectContext *pContext, void *pParam, void *pValue); int BassBoost_getParameter (EffectContext *pContext, void *pParam, - size_t *pValueSize, + uint32_t *pValueSize, void *pValue); int Virtualizer_setParameter (EffectContext *pContext, void *pParam, void *pValue); int Virtualizer_getParameter (EffectContext *pContext, void *pParam, - size_t *pValueSize, + uint32_t *pValueSize, void *pValue); int Equalizer_setParameter (EffectContext *pContext, void *pParam, void *pValue); int Equalizer_getParameter (EffectContext *pContext, void *pParam, - size_t *pValueSize, + uint32_t *pValueSize, void *pValue); int Volume_setParameter (EffectContext *pContext, void *pParam, void *pValue); int Volume_getParameter (EffectContext *pContext, void *pParam, - size_t *pValueSize, + uint32_t *pValueSize, void *pValue); int Effect_setEnabled(EffectContext *pContext, bool enabled); @@ -1758,7 +1758,7 @@ int32_t VolumeEnableStereoPosition(EffectContext *pContext, uint32_t enabled){ int BassBoost_getParameter(EffectContext *pContext, void *pParam, - size_t *pValueSize, + uint32_t *pValueSize, void *pValue){ int status = 0; int32_t *pParamTemp = (int32_t *)pParam; @@ -1876,7 +1876,7 @@ int BassBoost_setParameter (EffectContext *pContext, void *pParam, void *pValue) int Virtualizer_getParameter(EffectContext *pContext, void *pParam, - size_t *pValueSize, + uint32_t *pValueSize, void *pValue){ int status = 0; int32_t *pParamTemp = (int32_t *)pParam; @@ -1994,7 +1994,7 @@ int Virtualizer_setParameter (EffectContext *pContext, void *pParam, void *pValu //---------------------------------------------------------------------------- int Equalizer_getParameter(EffectContext *pContext, void *pParam, - size_t *pValueSize, + uint32_t *pValueSize, void *pValue){ int status = 0; int bMute = 0; @@ -2252,7 +2252,7 @@ int Equalizer_setParameter (EffectContext *pContext, void *pParam, void *pValue) int Volume_getParameter(EffectContext *pContext, void *pParam, - size_t *pValueSize, + uint32_t *pValueSize, void *pValue){ int status = 0; int bMute = 0; @@ -2813,9 +2813,9 @@ int Effect_command(effect_handle_t self, if(pContext->EffectType == LVM_BASS_BOOST){ if (pCmdData == NULL || - cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) || + cmdSize < (sizeof(effect_param_t) + sizeof(int32_t)) || pReplyData == NULL || - *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))){ + *replySize < (sizeof(effect_param_t) + sizeof(int32_t))){ ALOGV("\tLVM_ERROR : BassBoost_command cmdCode Case: " "EFFECT_CMD_GET_PARAM: ERROR"); return -EINVAL; @@ -2830,7 +2830,7 @@ int Effect_command(effect_handle_t self, p->status = android::BassBoost_getParameter(pContext, p->data, - (size_t *)&p->vsize, + &p->vsize, p->data + voffset); *replySize = sizeof(effect_param_t) + voffset + p->vsize; @@ -2844,9 +2844,9 @@ int Effect_command(effect_handle_t self, if(pContext->EffectType == LVM_VIRTUALIZER){ if (pCmdData == NULL || - cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) || + cmdSize < (sizeof(effect_param_t) + sizeof(int32_t)) || pReplyData == NULL || - *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))){ + *replySize < (sizeof(effect_param_t) + sizeof(int32_t))){ ALOGV("\tLVM_ERROR : Virtualizer_command cmdCode Case: " "EFFECT_CMD_GET_PARAM: ERROR"); return -EINVAL; @@ -2860,8 +2860,8 @@ int Effect_command(effect_handle_t self, int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t); p->status = android::Virtualizer_getParameter(pContext, - (void *)p->data, - (size_t *)&p->vsize, + (void *)p->data, + &p->vsize, p->data + voffset); *replySize = sizeof(effect_param_t) + voffset + p->vsize; @@ -2876,7 +2876,7 @@ int Effect_command(effect_handle_t self, //ALOGV("\tEqualizer_command cmdCode Case: " // "EFFECT_CMD_GET_PARAM start"); if (pCmdData == NULL || - cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) || + cmdSize < (sizeof(effect_param_t) + sizeof(int32_t)) || pReplyData == NULL || *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))) { ALOGV("\tLVM_ERROR : Equalizer_command cmdCode Case: " @@ -2908,7 +2908,7 @@ int Effect_command(effect_handle_t self, if(pContext->EffectType == LVM_VOLUME){ //ALOGV("\tVolume_command cmdCode Case: EFFECT_CMD_GET_PARAM start"); if (pCmdData == NULL || - cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) || + cmdSize < (sizeof(effect_param_t) + sizeof(int32_t)) || pReplyData == NULL || *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))){ ALOGV("\tLVM_ERROR : Volume_command cmdCode Case: " @@ -2925,7 +2925,7 @@ int Effect_command(effect_handle_t self, p->status = android::Volume_getParameter(pContext, (void *)p->data, - (size_t *)&p->vsize, + &p->vsize, p->data + voffset); *replySize = sizeof(effect_param_t) + voffset + p->vsize; @@ -2947,7 +2947,7 @@ int Effect_command(effect_handle_t self, // *(int16_t *)((char *)pCmdData + sizeof(effect_param_t) + sizeof(int32_t))); if (pCmdData == NULL|| - cmdSize != (int)(sizeof(effect_param_t) + sizeof(int32_t) +sizeof(int16_t))|| + cmdSize != (sizeof(effect_param_t) + sizeof(int32_t) +sizeof(int16_t))|| pReplyData == NULL|| *replySize != sizeof(int32_t)){ ALOGV("\tLVM_ERROR : BassBoost_command cmdCode Case: " @@ -2980,7 +2980,7 @@ int Effect_command(effect_handle_t self, // *(int16_t *)((char *)pCmdData + sizeof(effect_param_t) + sizeof(int32_t))); if (pCmdData == NULL|| - cmdSize != (int)(sizeof(effect_param_t) + sizeof(int32_t) +sizeof(int16_t))|| + cmdSize != (sizeof(effect_param_t) + sizeof(int32_t) +sizeof(int16_t))|| pReplyData == NULL|| *replySize != sizeof(int32_t)){ ALOGV("\tLVM_ERROR : Virtualizer_command cmdCode Case: " @@ -3014,7 +3014,7 @@ int Effect_command(effect_handle_t self, // *replySize, // *(int16_t *)((char *)pCmdData + sizeof(effect_param_t) + sizeof(int32_t))); - if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) || + if (pCmdData == NULL || cmdSize < (sizeof(effect_param_t) + sizeof(int32_t)) || pReplyData == NULL || *replySize != sizeof(int32_t)) { ALOGV("\tLVM_ERROR : Equalizer_command cmdCode Case: " "EFFECT_CMD_SET_PARAM: ERROR"); @@ -3034,7 +3034,7 @@ int Effect_command(effect_handle_t self, // *(int16_t *)((char *)pCmdData + sizeof(effect_param_t) +sizeof(int32_t))); if ( pCmdData == NULL|| - cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t))|| + cmdSize < (sizeof(effect_param_t) + sizeof(int32_t))|| pReplyData == NULL|| *replySize != sizeof(int32_t)){ ALOGV("\tLVM_ERROR : Volume_command cmdCode Case: " diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp index 0367302..c6d3759 100644 --- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp +++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp @@ -181,7 +181,7 @@ void Reverb_getConfig (ReverbContext *pContext, effect_config_t *pConfig); int Reverb_setParameter (ReverbContext *pContext, void *pParam, void *pValue); int Reverb_getParameter (ReverbContext *pContext, void *pParam, - size_t *pValueSize, + uint32_t *pValueSize, void *pValue); int Reverb_LoadPreset (ReverbContext *pContext); @@ -1534,7 +1534,7 @@ int Reverb_LoadPreset(ReverbContext *pContext) int Reverb_getParameter(ReverbContext *pContext, void *pParam, - size_t *pValueSize, + uint32_t *pValueSize, void *pValue){ int status = 0; int32_t *pParamTemp = (int32_t *)pParam; @@ -1956,9 +1956,9 @@ int Reverb_command(effect_handle_t self, //ALOGV("\tReverb_command cmdCode Case: " // "EFFECT_CMD_GET_PARAM start"); if (pCmdData == NULL || - cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) || + cmdSize < (sizeof(effect_param_t) + sizeof(int32_t)) || pReplyData == NULL || - *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))){ + *replySize < (sizeof(effect_param_t) + sizeof(int32_t))){ ALOGV("\tLVM_ERROR : Reverb_command cmdCode Case: " "EFFECT_CMD_GET_PARAM: ERROR"); return -EINVAL; @@ -1973,7 +1973,7 @@ int Reverb_command(effect_handle_t self, p->status = android::Reverb_getParameter(pContext, (void *)p->data, - (size_t *)&p->vsize, + &p->vsize, p->data + voffset); *replySize = sizeof(effect_param_t) + voffset + p->vsize; @@ -1994,8 +1994,8 @@ int Reverb_command(effect_handle_t self, // *replySize, // *(int16_t *)((char *)pCmdData + sizeof(effect_param_t) + sizeof(int32_t))); - if (pCmdData == NULL || (cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t))) - || pReplyData == NULL || *replySize != (int)sizeof(int32_t)) { + if (pCmdData == NULL || (cmdSize < (sizeof(effect_param_t) + sizeof(int32_t))) + || pReplyData == NULL || *replySize != sizeof(int32_t)) { ALOGV("\tLVM_ERROR : Reverb_command cmdCode Case: " "EFFECT_CMD_SET_PARAM: ERROR"); return -EINVAL; diff --git a/media/libeffects/preprocessing/Android.mk b/media/libeffects/preprocessing/Android.mk index c344352..9e8cb83 100644 --- a/media/libeffects/preprocessing/Android.mk +++ b/media/libeffects/preprocessing/Android.mk @@ -5,7 +5,7 @@ include $(CLEAR_VARS) LOCAL_MODULE:= libaudiopreprocessing LOCAL_MODULE_TAGS := optional -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx LOCAL_SRC_FILES:= \ PreProcessing.cpp diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp index d72eaf5..a96a703 100644 --- a/media/libeffects/preprocessing/PreProcessing.cpp +++ b/media/libeffects/preprocessing/PreProcessing.cpp @@ -77,7 +77,7 @@ struct preproc_ops_s { void (* enable)(preproc_effect_t *fx); void (* disable)(preproc_effect_t *fx); int (* set_parameter)(preproc_effect_t *fx, void *param, void *value); - int (* get_parameter)(preproc_effect_t *fx, void *param, size_t *size, void *value); + int (* get_parameter)(preproc_effect_t *fx, void *param, uint32_t *size, void *value); int (* set_device)(preproc_effect_t *fx, uint32_t device); }; @@ -291,7 +291,7 @@ int AgcCreate(preproc_effect_t *effect) int AgcGetParameter(preproc_effect_t *effect, void *pParam, - size_t *pValueSize, + uint32_t *pValueSize, void *pValue) { int status = 0; @@ -452,9 +452,9 @@ int AecCreate(preproc_effect_t *effect) return 0; } -int AecGetParameter(preproc_effect_t *effect, +int AecGetParameter(preproc_effect_t *effect, void *pParam, - size_t *pValueSize, + uint32_t *pValueSize, void *pValue) { int status = 0; @@ -575,9 +575,9 @@ int NsCreate(preproc_effect_t *effect) return 0; } -int NsGetParameter(preproc_effect_t *effect, +int NsGetParameter(preproc_effect_t *effect, void *pParam, - size_t *pValueSize, + uint32_t *pValueSize, void *pValue) { int status = 0; @@ -1233,8 +1233,8 @@ int PreProcessingFx_Process(effect_handle_t self, if (session->framesIn < session->frameCount) { return 0; } - size_t frIn = session->framesIn; - size_t frOut = session->apmFrameCount; + spx_uint32_t frIn = session->framesIn; + spx_uint32_t frOut = session->apmFrameCount; if (session->inChannelCount == 1) { speex_resampler_process_int(session->inResampler, 0, @@ -1290,8 +1290,8 @@ int PreProcessingFx_Process(effect_handle_t self, } if (session->outResampler != NULL) { - size_t frIn = session->apmFrameCount; - size_t frOut = session->frameCount; + spx_uint32_t frIn = session->apmFrameCount; + spx_uint32_t frOut = session->frameCount; if (session->inChannelCount == 1) { speex_resampler_process_int(session->outResampler, 0, @@ -1453,7 +1453,7 @@ int PreProcessingFx_Command(effect_handle_t self, if (effect->ops->get_parameter) { p->status = effect->ops->get_parameter(effect, p->data, - (size_t *)&p->vsize, + &p->vsize, p->data + voffset); *replySize = sizeof(effect_param_t) + voffset + p->vsize; } @@ -1754,8 +1754,8 @@ int PreProcessingFx_ProcessReverse(effect_handle_t self, if (session->framesRev < session->frameCount) { return 0; } - size_t frIn = session->framesRev; - size_t frOut = session->apmFrameCount; + spx_uint32_t frIn = session->framesRev; + spx_uint32_t frOut = session->apmFrameCount; if (session->inChannelCount == 1) { speex_resampler_process_int(session->revResampler, 0, diff --git a/media/libeffects/proxy/Android.mk b/media/libeffects/proxy/Android.mk index 01b3be1..b438796 100644 --- a/media/libeffects/proxy/Android.mk +++ b/media/libeffects/proxy/Android.mk @@ -15,7 +15,7 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE:= libeffectproxy -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx LOCAL_MODULE_TAGS := optional @@ -28,7 +28,8 @@ LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libdl libeffects LOCAL_C_INCLUDES := \ system/media/audio_effects/include \ - bionic/libc/include + bionic/libc/include \ + frameworks/av/media/libeffects/factory include $(BUILD_SHARED_LIBRARY) diff --git a/media/libeffects/proxy/EffectProxy.cpp b/media/libeffects/proxy/EffectProxy.cpp index dd4ad08..62d3fd3 100644 --- a/media/libeffects/proxy/EffectProxy.cpp +++ b/media/libeffects/proxy/EffectProxy.cpp @@ -56,6 +56,8 @@ int EffectProxyCreate(const effect_uuid_t *uuid, effect_handle_t *pHandle) { effect_descriptor_t* desc; + audio_effect_library_t** aeli; + sub_effect_entry_t** sube; EffectContext* pContext; if (pHandle == NULL || uuid == NULL) { ALOGE("EffectProxyCreate() called with NULL pointer"); @@ -74,31 +76,52 @@ int EffectProxyCreate(const effect_uuid_t *uuid, // Get the HW and SW sub effect descriptors from the effects factory desc = new effect_descriptor_t[SUB_FX_COUNT]; + aeli = new audio_effect_library_t*[SUB_FX_COUNT]; + sube = new sub_effect_entry_t*[SUB_FX_COUNT]; + pContext->sube = new sub_effect_entry_t*[SUB_FX_COUNT]; pContext->desc = new effect_descriptor_t[SUB_FX_COUNT]; - int retValue = EffectGetSubEffects(uuid, desc, - sizeof(effect_descriptor_t) * SUB_FX_COUNT); + pContext->aeli = new audio_effect_library_t*[SUB_FX_COUNT]; + int retValue = EffectGetSubEffects(uuid, sube, SUB_FX_COUNT); // EffectGetSubEffects returns the number of sub-effects copied. if (retValue != SUB_FX_COUNT) { ALOGE("EffectCreate() could not get the sub effects"); - delete desc; - delete pContext->desc; + delete[] sube; + delete[] desc; + delete[] aeli; + delete[] pContext->sube; + delete[] pContext->desc; + delete[] pContext->aeli; return -EINVAL; } // Check which is the HW descriptor and copy the descriptors // to the Context desc array // Also check if there is only one HW and one SW descriptor. // HW descriptor alone has the HW_TUNNEL flag. + desc[0] = *(effect_descriptor_t*)(sube[0])->object; + desc[1] = *(effect_descriptor_t*)(sube[1])->object; + aeli[0] = sube[0]->lib->desc; + aeli[1] = sube[1]->lib->desc; if ((desc[0].flags & EFFECT_FLAG_HW_ACC_TUNNEL) && !(desc[1].flags & EFFECT_FLAG_HW_ACC_TUNNEL)) { + pContext->sube[SUB_FX_OFFLOAD] = sube[0]; pContext->desc[SUB_FX_OFFLOAD] = desc[0]; + pContext->aeli[SUB_FX_OFFLOAD] = aeli[0]; + pContext->sube[SUB_FX_HOST] = sube[1]; pContext->desc[SUB_FX_HOST] = desc[1]; + pContext->aeli[SUB_FX_HOST] = aeli[1]; } else if ((desc[1].flags & EFFECT_FLAG_HW_ACC_TUNNEL) && !(desc[0].flags & EFFECT_FLAG_HW_ACC_TUNNEL)) { + pContext->sube[SUB_FX_HOST] = sube[0]; pContext->desc[SUB_FX_HOST] = desc[0]; + pContext->aeli[SUB_FX_HOST] = aeli[0]; + pContext->sube[SUB_FX_OFFLOAD] = sube[1]; pContext->desc[SUB_FX_OFFLOAD] = desc[1]; + pContext->aeli[SUB_FX_OFFLOAD] = aeli[1]; } - delete desc; + delete[] desc; + delete[] aeli; + delete[] sube; #if (LOG_NDEBUG == 0) effect_uuid_t uuid_print = pContext->desc[SUB_FX_HOST].uuid; ALOGV("EffectCreate() UUID of HOST: %08X-%04X-%04X-%04X-%02X%02X%02X%02X" @@ -128,13 +151,15 @@ int EffectProxyRelease(effect_handle_t handle) { return -EINVAL; } ALOGV("EffectRelease"); - delete pContext->desc; + delete[] pContext->desc; free(pContext->replyData); if (pContext->eHandle[SUB_FX_HOST]) - EffectRelease(pContext->eHandle[SUB_FX_HOST]); + pContext->aeli[SUB_FX_HOST]->release_effect(pContext->eHandle[SUB_FX_HOST]); if (pContext->eHandle[SUB_FX_OFFLOAD]) - EffectRelease(pContext->eHandle[SUB_FX_OFFLOAD]); + pContext->aeli[SUB_FX_OFFLOAD]->release_effect(pContext->eHandle[SUB_FX_OFFLOAD]); + delete[] pContext->aeli; + delete[] pContext->sube; delete pContext; pContext = NULL; return 0; @@ -187,7 +212,8 @@ int Effect_command(effect_handle_t self, } if (pContext->eHandle[SUB_FX_HOST] == NULL) { ALOGV("Effect_command() Calling HOST EffectCreate"); - status = EffectCreate(&pContext->desc[SUB_FX_HOST].uuid, + status = pContext->aeli[SUB_FX_HOST]->create_effect( + &pContext->desc[SUB_FX_HOST].uuid, pContext->sessionId, pContext->ioId, &(pContext->eHandle[SUB_FX_HOST])); if (status != NO_ERROR || (pContext->eHandle[SUB_FX_HOST] == NULL)) { @@ -197,11 +223,13 @@ int Effect_command(effect_handle_t self, } if (pContext->eHandle[SUB_FX_OFFLOAD] == NULL) { ALOGV("Effect_command() Calling OFFLOAD EffectCreate"); - status = EffectCreate(&pContext->desc[SUB_FX_OFFLOAD].uuid, + status = pContext->aeli[SUB_FX_OFFLOAD]->create_effect( + &pContext->desc[SUB_FX_OFFLOAD].uuid, pContext->sessionId, pContext->ioId, &(pContext->eHandle[SUB_FX_OFFLOAD])); if (status != NO_ERROR || (pContext->eHandle[SUB_FX_OFFLOAD] == NULL)) { ALOGV("Effect_command() Error creating HW effect"); + pContext->eHandle[SUB_FX_OFFLOAD] = NULL; // Do not return error here as SW effect is created // Return error if the CMD_OFFLOAD sends the index as OFFLOAD } @@ -233,11 +261,17 @@ int Effect_command(effect_handle_t self, // Update the DSP wrapper with the new ioHandle. // Pass the OFFLOAD command to the wrapper. // The DSP wrapper needs to handle this CMD - if (pContext->eHandle[SUB_FX_OFFLOAD]) - status = (*pContext->eHandle[SUB_FX_OFFLOAD])->command( - pContext->eHandle[SUB_FX_OFFLOAD], cmdCode, cmdSize, - pCmdData, replySize, pReplyData); - return status; + if (pContext->eHandle[SUB_FX_OFFLOAD]) { + ALOGV("Effect_command: Calling OFFLOAD command"); + return (*pContext->eHandle[SUB_FX_OFFLOAD])->command( + pContext->eHandle[SUB_FX_OFFLOAD], cmdCode, cmdSize, + pCmdData, replySize, pReplyData); + } + *(int*)pReplyData = NO_ERROR; + ALOGV("Effect_command OFFLOAD return 0, replyData %d", + *(int*)pReplyData); + + return NO_ERROR; } int index = pContext->index; @@ -329,11 +363,11 @@ int Effect_getDescriptor(effect_handle_t self, __attribute__ ((visibility ("default"))) audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { - tag : AUDIO_EFFECT_LIBRARY_TAG, - version : EFFECT_LIBRARY_API_VERSION, - name : "Effect Proxy", - implementor : "AOSP", - create_effect : android::EffectProxyCreate, - release_effect : android::EffectProxyRelease, - get_descriptor : android::EffectProxyGetDescriptor, + .tag = AUDIO_EFFECT_LIBRARY_TAG, + .version = EFFECT_LIBRARY_API_VERSION, + .name = "Effect Proxy", + .implementor = "AOSP", + .create_effect = android::EffectProxyCreate, + .release_effect = android::EffectProxyRelease, + .get_descriptor = android::EffectProxyGetDescriptor, }; diff --git a/media/libeffects/proxy/EffectProxy.h b/media/libeffects/proxy/EffectProxy.h index acbe17e..046b93e 100644 --- a/media/libeffects/proxy/EffectProxy.h +++ b/media/libeffects/proxy/EffectProxy.h @@ -16,6 +16,8 @@ #include <hardware/audio.h> #include <hardware/audio_effect.h> +#include "EffectsFactory.h" + namespace android { enum { SUB_FX_HOST, // Index of HOST in the descriptor and handle arrays @@ -62,7 +64,9 @@ const struct effect_interface_s gEffectInterface = { struct EffectContext { const struct effect_interface_s *common_itfe; // Holds the itfe of the Proxy + sub_effect_entry_t** sube; // Points to the sub effects effect_descriptor_t* desc; // Points to the sub effect descriptors + audio_effect_library_t** aeli; // Points to the sub effect aeli effect_handle_t eHandle[SUB_FX_COUNT]; // The effect handles of the sub effects int index; // The index that is currently active - HOST or OFFLOAD int32_t sessionId; // The sessiond in which the effect is created. diff --git a/media/libeffects/testlibs/Android.mk_ b/media/libeffects/testlibs/Android.mk_ index 2954908..672ebba 100644 --- a/media/libeffects/testlibs/Android.mk_ +++ b/media/libeffects/testlibs/Android.mk_ @@ -11,7 +11,7 @@ LOCAL_CFLAGS+= -O2 LOCAL_SHARED_LIBRARIES := \ libcutils -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx LOCAL_MODULE:= libreverbtest ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true) @@ -47,7 +47,7 @@ LOCAL_CFLAGS+= -O2 LOCAL_SHARED_LIBRARIES := \ libcutils -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx LOCAL_MODULE:= libequalizertest ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true) diff --git a/media/libeffects/testlibs/EffectEqualizer.cpp b/media/libeffects/testlibs/EffectEqualizer.cpp index 8d00206..3cb13f2 100644 --- a/media/libeffects/testlibs/EffectEqualizer.cpp +++ b/media/libeffects/testlibs/EffectEqualizer.cpp @@ -115,7 +115,7 @@ struct EqualizerContext { int Equalizer_init(EqualizerContext *pContext); int Equalizer_setConfig(EqualizerContext *pContext, effect_config_t *pConfig); -int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, size_t *pValueSize, void *pValue); +int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, uint32_t *pValueSize, void *pValue); int Equalizer_setParameter(AudioEqualizer * pEqualizer, int32_t *pParam, void *pValue); @@ -360,7 +360,7 @@ int Equalizer_init(EqualizerContext *pContext) // //---------------------------------------------------------------------------- -int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, size_t *pValueSize, void *pValue) +int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, uint32_t *pValueSize, void *pValue) { int status = 0; int32_t param = *pParam++; @@ -662,8 +662,8 @@ extern "C" int Equalizer_command(effect_handle_t self, uint32_t cmdCode, uint32_ Equalizer_setConfig(pContext, &pContext->config); break; case EFFECT_CMD_GET_PARAM: { - if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) || - pReplyData == NULL || *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))) { + if (pCmdData == NULL || cmdSize < (sizeof(effect_param_t) + sizeof(int32_t)) || + pReplyData == NULL || *replySize < (sizeof(effect_param_t) + sizeof(int32_t))) { return -EINVAL; } effect_param_t *p = (effect_param_t *)pCmdData; @@ -682,7 +682,7 @@ extern "C" int Equalizer_command(effect_handle_t self, uint32_t cmdCode, uint32_ case EFFECT_CMD_SET_PARAM: { ALOGV("Equalizer_command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %d, pReplyData %p", cmdSize, pCmdData, *replySize, pReplyData); - if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) || + if (pCmdData == NULL || cmdSize < (sizeof(effect_param_t) + sizeof(int32_t)) || pReplyData == NULL || *replySize != sizeof(int32_t)) { return -EINVAL; } diff --git a/media/libeffects/testlibs/EffectReverb.c b/media/libeffects/testlibs/EffectReverb.c index c37f392..f056d19 100644 --- a/media/libeffects/testlibs/EffectReverb.c +++ b/media/libeffects/testlibs/EffectReverb.c @@ -750,7 +750,7 @@ void Reverb_Reset(reverb_object_t *pReverb, bool init) { * *---------------------------------------------------------------------------- */ -int Reverb_getParameter(reverb_object_t *pReverb, int32_t param, size_t *pSize, +int Reverb_getParameter(reverb_object_t *pReverb, int32_t param, uint32_t *pSize, void *pValue) { int32_t *pValue32; int16_t *pValue16; @@ -758,7 +758,7 @@ int Reverb_getParameter(reverb_object_t *pReverb, int32_t param, size_t *pSize, int32_t i; int32_t temp; int32_t temp2; - size_t size; + uint32_t size; if (pReverb->m_Preset) { if (param != REVERB_PARAM_PRESET || *pSize < sizeof(int16_t)) { @@ -1033,7 +1033,7 @@ int Reverb_getParameter(reverb_object_t *pReverb, int32_t param, size_t *pSize, * *---------------------------------------------------------------------------- */ -int Reverb_setParameter(reverb_object_t *pReverb, int32_t param, size_t size, +int Reverb_setParameter(reverb_object_t *pReverb, int32_t param, uint32_t size, void *pValue) { int32_t value32; int16_t value16; @@ -1044,7 +1044,7 @@ int Reverb_setParameter(reverb_object_t *pReverb, int32_t param, size_t size, reverb_preset_t *pPreset; int maxSamples; int32_t averageDelay; - size_t paramSize; + uint32_t paramSize; ALOGV("Reverb_setParameter, context %p, param %d, value16 %d, value32 %d", pReverb, param, *(int16_t *)pValue, *(int32_t *)pValue); diff --git a/media/libeffects/testlibs/EffectReverb.h b/media/libeffects/testlibs/EffectReverb.h index e5248fe..756c5ea 100644 --- a/media/libeffects/testlibs/EffectReverb.h +++ b/media/libeffects/testlibs/EffectReverb.h @@ -330,8 +330,8 @@ int Reverb_setConfig(reverb_module_t *pRvbModule, effect_config_t *pConfig, bool void Reverb_getConfig(reverb_module_t *pRvbModule, effect_config_t *pConfig); void Reverb_Reset(reverb_object_t *pReverb, bool init); -int Reverb_setParameter (reverb_object_t *pReverb, int32_t param, size_t size, void *pValue); -int Reverb_getParameter(reverb_object_t *pReverb, int32_t param, size_t *pSize, void *pValue); +int Reverb_setParameter (reverb_object_t *pReverb, int32_t param, uint32_t size, void *pValue); +int Reverb_getParameter(reverb_object_t *pReverb, int32_t param, uint32_t *pSize, void *pValue); /*---------------------------------------------------------------------------- * ReverbUpdateXfade diff --git a/media/libeffects/visualizer/Android.mk b/media/libeffects/visualizer/Android.mk index e196eb2..dd2d306 100644 --- a/media/libeffects/visualizer/Android.mk +++ b/media/libeffects/visualizer/Android.mk @@ -13,7 +13,7 @@ LOCAL_SHARED_LIBRARIES := \ liblog \ libdl -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx LOCAL_MODULE:= libvisualizer LOCAL_C_INCLUDES := \ diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp index 2d66eef..47cab62 100644 --- a/media/libeffects/visualizer/EffectVisualizer.cpp +++ b/media/libeffects/visualizer/EffectVisualizer.cpp @@ -16,8 +16,9 @@ #define LOG_TAG "EffectVisualizer" //#define LOG_NDEBUG 0 -#include <cutils/log.h> +#include <log/log.h> #include <assert.h> +#include <inttypes.h> #include <stdlib.h> #include <string.h> #include <new> @@ -226,8 +227,8 @@ int Visualizer_init(VisualizerContext *pContext) // int VisualizerLib_Create(const effect_uuid_t *uuid, - int32_t sessionId, - int32_t ioId, + int32_t /*sessionId*/, + int32_t /*ioId*/, effect_handle_t *pHandle) { int ret; int i; @@ -418,7 +419,7 @@ int Visualizer_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize, return -EINVAL; } -// ALOGV("Visualizer_command command %d cmdSize %d",cmdCode, cmdSize); +// ALOGV("Visualizer_command command %" PRIu32 " cmdSize %" PRIu32, cmdCode, cmdSize); switch (cmdCode) { case EFFECT_CMD_INIT: @@ -484,19 +485,19 @@ int Visualizer_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize, } switch (*(uint32_t *)p->data) { case VISUALIZER_PARAM_CAPTURE_SIZE: - ALOGV("get mCaptureSize = %d", pContext->mCaptureSize); + ALOGV("get mCaptureSize = %" PRIu32, pContext->mCaptureSize); *((uint32_t *)p->data + 1) = pContext->mCaptureSize; p->vsize = sizeof(uint32_t); *replySize += sizeof(uint32_t); break; case VISUALIZER_PARAM_SCALING_MODE: - ALOGV("get mScalingMode = %d", pContext->mScalingMode); + ALOGV("get mScalingMode = %" PRIu32, pContext->mScalingMode); *((uint32_t *)p->data + 1) = pContext->mScalingMode; p->vsize = sizeof(uint32_t); *replySize += sizeof(uint32_t); break; case VISUALIZER_PARAM_MEASUREMENT_MODE: - ALOGV("get mMeasurementMode = %d", pContext->mMeasurementMode); + ALOGV("get mMeasurementMode = %" PRIu32, pContext->mMeasurementMode); *((uint32_t *)p->data + 1) = pContext->mMeasurementMode; p->vsize = sizeof(uint32_t); *replySize += sizeof(uint32_t); @@ -520,19 +521,19 @@ int Visualizer_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize, switch (*(uint32_t *)p->data) { case VISUALIZER_PARAM_CAPTURE_SIZE: pContext->mCaptureSize = *((uint32_t *)p->data + 1); - ALOGV("set mCaptureSize = %d", pContext->mCaptureSize); + ALOGV("set mCaptureSize = %" PRIu32, pContext->mCaptureSize); break; case VISUALIZER_PARAM_SCALING_MODE: pContext->mScalingMode = *((uint32_t *)p->data + 1); - ALOGV("set mScalingMode = %d", pContext->mScalingMode); + ALOGV("set mScalingMode = %" PRIu32, pContext->mScalingMode); break; case VISUALIZER_PARAM_LATENCY: pContext->mLatency = *((uint32_t *)p->data + 1); - ALOGV("set mLatency = %d", pContext->mLatency); + ALOGV("set mLatency = %" PRIu32, pContext->mLatency); break; case VISUALIZER_PARAM_MEASUREMENT_MODE: pContext->mMeasurementMode = *((uint32_t *)p->data + 1); - ALOGV("set mMeasurementMode = %d", pContext->mMeasurementMode); + ALOGV("set mMeasurementMode = %" PRIu32, pContext->mMeasurementMode); break; default: *(int32_t *)pReplyData = -EINVAL; @@ -544,56 +545,57 @@ int Visualizer_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize, break; - case VISUALIZER_CMD_CAPTURE: - if (pReplyData == NULL || *replySize != pContext->mCaptureSize) { - ALOGV("VISUALIZER_CMD_CAPTURE() error *replySize %d pContext->mCaptureSize %d", - *replySize, pContext->mCaptureSize); + case VISUALIZER_CMD_CAPTURE: { + uint32_t captureSize = pContext->mCaptureSize; + if (pReplyData == NULL || *replySize != captureSize) { + ALOGV("VISUALIZER_CMD_CAPTURE() error *replySize %" PRIu32 " captureSize %" PRIu32, + *replySize, captureSize); return -EINVAL; } if (pContext->mState == VISUALIZER_STATE_ACTIVE) { - int32_t latencyMs = pContext->mLatency; const uint32_t deltaMs = Visualizer_getDeltaTimeMsFromUpdatedTime(pContext); - latencyMs -= deltaMs; - if (latencyMs < 0) { - latencyMs = 0; - } - const uint32_t deltaSmpl = pContext->mConfig.inputCfg.samplingRate * latencyMs / 1000; - - int32_t capturePoint = pContext->mCaptureIdx - pContext->mCaptureSize - deltaSmpl; - int32_t captureSize = pContext->mCaptureSize; - if (capturePoint < 0) { - int32_t size = -capturePoint; - if (size > captureSize) { - size = captureSize; - } - memcpy(pReplyData, - pContext->mCaptureBuf + CAPTURE_BUF_SIZE + capturePoint, - size); - pReplyData = (char *)pReplyData + size; - captureSize -= size; - capturePoint = 0; - } - memcpy(pReplyData, - pContext->mCaptureBuf + capturePoint, - captureSize); - // if audio framework has stopped playing audio although the effect is still // active we must clear the capture buffer to return silence if ((pContext->mLastCaptureIdx == pContext->mCaptureIdx) && - (pContext->mBufferUpdateTime.tv_sec != 0)) { - if (deltaMs > MAX_STALL_TIME_MS) { + (pContext->mBufferUpdateTime.tv_sec != 0) && + (deltaMs > MAX_STALL_TIME_MS)) { ALOGV("capture going to idle"); pContext->mBufferUpdateTime.tv_sec = 0; - memset(pReplyData, 0x80, pContext->mCaptureSize); + memset(pReplyData, 0x80, captureSize); + } else { + int32_t latencyMs = pContext->mLatency; + latencyMs -= deltaMs; + if (latencyMs < 0) { + latencyMs = 0; } + const uint32_t deltaSmpl = + pContext->mConfig.inputCfg.samplingRate * latencyMs / 1000; + int32_t capturePoint = pContext->mCaptureIdx - captureSize - deltaSmpl; + + if (capturePoint < 0) { + uint32_t size = -capturePoint; + if (size > captureSize) { + size = captureSize; + } + memcpy(pReplyData, + pContext->mCaptureBuf + CAPTURE_BUF_SIZE + capturePoint, + size); + pReplyData = (char *)pReplyData + size; + captureSize -= size; + capturePoint = 0; + } + memcpy(pReplyData, + pContext->mCaptureBuf + capturePoint, + captureSize); } + pContext->mLastCaptureIdx = pContext->mCaptureIdx; } else { - memset(pReplyData, 0x80, pContext->mCaptureSize); + memset(pReplyData, 0x80, captureSize); } - break; + } break; case VISUALIZER_CMD_MEASURE: { uint16_t peakU16 = 0; @@ -603,7 +605,7 @@ int Visualizer_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize, // measurements aren't relevant anymore and shouldn't bias the new one) const int32_t delayMs = Visualizer_getDeltaTimeMsFromUpdatedTime(pContext); if (delayMs > DISCARD_MEASUREMENTS_TIME_MS) { - ALOGV("Discarding measurements, last measurement is %dms old", delayMs); + ALOGV("Discarding measurements, last measurement is %" PRId32 "ms old", delayMs); for (uint32_t i=0 ; i<pContext->mMeasurementWindowSizeInBuffers ; i++) { pContext->mPastMeasurements[i].mIsValid = false; pContext->mPastMeasurements[i].mPeakU16 = 0; @@ -637,14 +639,14 @@ int Visualizer_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize, } else { pIntReplyData[MEASUREMENT_IDX_PEAK] = (int32_t) (2000 * log10(peakU16 / 32767.0f)); } - ALOGV("VISUALIZER_CMD_MEASURE peak=%d (%dmB), rms=%.1f (%dmB)", + ALOGV("VISUALIZER_CMD_MEASURE peak=%" PRIu16 " (%" PRId32 "mB), rms=%.1f (%" PRId32 "mB)", peakU16, pIntReplyData[MEASUREMENT_IDX_PEAK], rms, pIntReplyData[MEASUREMENT_IDX_RMS]); } break; default: - ALOGW("Visualizer_command invalid command %d",cmdCode); + ALOGW("Visualizer_command invalid command %" PRIu32, cmdCode); return -EINVAL; } diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index 56e7787..1e322f9 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -76,7 +76,7 @@ LOCAL_MODULE:= libmedia LOCAL_C_INCLUDES := \ $(call include-path-for, graphics corecg) \ $(TOP)/frameworks/native/include/media/openmax \ - external/icu4c/common \ + external/icu/icu4c/source/common \ $(call include-path-for, audio-effects) \ $(call include-path-for, audio-utils) diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 666fafa..ccbc5a3 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -545,13 +545,13 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) } const struct timespec *requested; + struct timespec timeout; if (waitCount == -1) { requested = &ClientProxy::kForever; } else if (waitCount == 0) { requested = &ClientProxy::kNonBlocking; } else if (waitCount > 0) { long long ms = WAIT_PERIOD_MS * (long long) waitCount; - struct timespec timeout; timeout.tv_sec = ms / 1000; timeout.tv_nsec = (int) (ms % 1000) * 1000000; requested = &timeout; diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 8033c2c..cc5b810 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -370,8 +370,8 @@ status_t AudioSystem::setVoiceVolume(float value) return af->setVoiceVolume(value); } -status_t AudioSystem::getRenderPosition(audio_io_handle_t output, size_t *halFrames, - size_t *dspFrames, audio_stream_type_t stream) +status_t AudioSystem::getRenderPosition(audio_io_handle_t output, uint32_t *halFrames, + uint32_t *dspFrames, audio_stream_type_t stream) { const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); if (af == 0) return PERMISSION_DENIED; diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index b8a89a0..3f3a88c 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -85,7 +85,8 @@ AudioTrack::AudioTrack() : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), - mPreviousSchedulingGroup(SP_DEFAULT) + mPreviousSchedulingGroup(SP_DEFAULT), + mPausedPosition(0) { } @@ -106,7 +107,8 @@ AudioTrack::AudioTrack( : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), - mPreviousSchedulingGroup(SP_DEFAULT) + mPreviousSchedulingGroup(SP_DEFAULT), + mPausedPosition(0) { mStatus = set(streamType, sampleRate, format, channelMask, frameCount, flags, cbf, user, notificationFrames, @@ -131,7 +133,8 @@ AudioTrack::AudioTrack( : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), - mPreviousSchedulingGroup(SP_DEFAULT) + mPreviousSchedulingGroup(SP_DEFAULT), + mPausedPosition(0) { mStatus = set(streamType, sampleRate, format, channelMask, 0 /*frameCount*/, flags, cbf, user, notificationFrames, @@ -529,6 +532,16 @@ void AudioTrack::pause() } mProxy->interrupt(); mAudioTrack->pause(); + + if (isOffloaded()) { + if (mOutput != 0) { + uint32_t halFrames; + // OffloadThread sends HAL pause in its threadLoop.. time saved + // here can be slightly off + AudioSystem::getRenderPosition(mOutput, &halFrames, &mPausedPosition); + ALOGV("AudioTrack::pause for offload, cache current position %u", mPausedPosition); + } + } } status_t AudioTrack::setVolume(float left, float right) @@ -603,6 +616,19 @@ uint32_t AudioTrack::getSampleRate() const } AutoMutex lock(mLock); + + // sample rate can be updated during playback by the offloaded decoder so we need to + // query the HAL and update if needed. +// FIXME use Proxy return channel to update the rate from server and avoid polling here + if (isOffloaded()) { + if (mOutput != 0) { + uint32_t sampleRate = 0; + status_t status = AudioSystem::getSamplingRate(mOutput, mStreamType, &sampleRate); + if (status == NO_ERROR) { + mSampleRate = sampleRate; + } + } + } return mSampleRate; } @@ -734,6 +760,12 @@ status_t AudioTrack::getPosition(uint32_t *position) const if (isOffloaded()) { uint32_t dspFrames = 0; + if ((mState == STATE_PAUSED) || (mState == STATE_PAUSED_STOPPING)) { + ALOGV("getPosition called in paused state, return cached position %u", mPausedPosition); + *position = mPausedPosition; + return NO_ERROR; + } + if (mOutput != 0) { uint32_t halFrames; AudioSystem::getRenderPosition(mOutput, &halFrames, &dspFrames); @@ -747,7 +779,7 @@ status_t AudioTrack::getPosition(uint32_t *position) const return NO_ERROR; } -status_t AudioTrack::getBufferPosition(size_t *position) +status_t AudioTrack::getBufferPosition(uint32_t *position) { if (mSharedBuffer == 0 || mIsTimed) { return INVALID_OPERATION; @@ -865,8 +897,15 @@ status_t AudioTrack::createTrack_l( } ALOGV("createTrack_l() output %d afLatency %d", output, afLatency); + if ((flags & AUDIO_OUTPUT_FLAG_FAST) && sampleRate != afSampleRate) { + ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by client due to mismatching sample rate (%d vs %d)", + sampleRate, afSampleRate); + flags = (audio_output_flags_t) (flags & ~AUDIO_OUTPUT_FLAG_FAST); + } + // The client's AudioTrack buffer is divided into n parts for purpose of wakeup by server, where - // n = 1 fast track; nBuffering is ignored + // n = 1 fast track with single buffering; nBuffering is ignored + // n = 2 fast track with double buffering // n = 2 normal track, no sample rate conversion // n = 3 normal track, with sample rate conversion // (pessimistic; some non-1:1 conversion ratios don't actually need triple-buffering) @@ -895,7 +934,7 @@ status_t AudioTrack::createTrack_l( // More than 2 channels does not require stronger alignment than stereo alignment <<= 1; } - if (((size_t)sharedBuffer->pointer() & (alignment - 1)) != 0) { + if (((uintptr_t)sharedBuffer->pointer() & (alignment - 1)) != 0) { ALOGE("Invalid buffer alignment: address %p, channel count %u", sharedBuffer->pointer(), mChannelCount); return BAD_VALUE; @@ -1006,9 +1045,11 @@ status_t AudioTrack::createTrack_l( ALOGV("AUDIO_OUTPUT_FLAG_FAST successful; frameCount %u", frameCount); mAwaitBoost = true; if (sharedBuffer == 0) { - // double-buffering is not required for fast tracks, due to tighter scheduling - if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount) { - mNotificationFramesAct = frameCount; + // Theoretically double-buffering is not required for fast tracks, + // due to tighter scheduling. But in practice, to accommodate kernels with + // scheduling jitter, and apps with computation jitter, we use double-buffering. + if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/nBuffering) { + mNotificationFramesAct = frameCount/nBuffering; } } } else { @@ -1091,13 +1132,13 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) } const struct timespec *requested; + struct timespec timeout; if (waitCount == -1) { requested = &ClientProxy::kForever; } else if (waitCount == 0) { requested = &ClientProxy::kNonBlocking; } else if (waitCount > 0) { long long ms = WAIT_PERIOD_MS * (long long) waitCount; - struct timespec timeout; timeout.tv_sec = ms / 1000; timeout.tv_nsec = (int) (ms % 1000) * 1000000; requested = &timeout; @@ -1222,7 +1263,7 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize) if (ssize_t(userSize) < 0 || (buffer == NULL && userSize != 0)) { // Sanity-check: user is most-likely passing an error code, and it would // make the return value ambiguous (actualSize vs error). - ALOGE("AudioTrack::write(buffer=%p, size=%u (%d)", buffer, userSize, userSize); + ALOGE("AudioTrack::write(buffer=%p, size=%zu (%zd)", buffer, userSize, userSize); return BAD_VALUE; } @@ -1429,6 +1470,7 @@ nsecs_t AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) } size_t misalignment = mProxy->getMisalignment(); uint32_t sequence = mSequence; + sp<AudioTrackClientProxy> proxy = mProxy; // These fields don't need to be cached, because they are assigned only by set(): // mTransfer, mCbf, mUserData, mFormat, mFrameSize, mFrameSizeAF, mFlags @@ -1437,35 +1479,32 @@ nsecs_t AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) mLock.unlock(); if (waitStreamEnd) { - AutoMutex lock(mLock); - - sp<AudioTrackClientProxy> proxy = mProxy; - sp<IMemory> iMem = mCblkMemory; - struct timespec timeout; timeout.tv_sec = WAIT_STREAM_END_TIMEOUT_SEC; timeout.tv_nsec = 0; - mLock.unlock(); - status_t status = mProxy->waitStreamEndDone(&timeout); - mLock.lock(); + status_t status = proxy->waitStreamEndDone(&timeout); switch (status) { case NO_ERROR: case DEAD_OBJECT: case TIMED_OUT: - mLock.unlock(); mCbf(EVENT_STREAM_END, mUserData, NULL); - mLock.lock(); - if (mState == STATE_STOPPING) { - mState = STATE_STOPPED; - if (status != DEAD_OBJECT) { - return NS_INACTIVE; + { + AutoMutex lock(mLock); + // The previously assigned value of waitStreamEnd is no longer valid, + // since the mutex has been unlocked and either the callback handler + // or another thread could have re-started the AudioTrack during that time. + waitStreamEnd = mState == STATE_STOPPING; + if (waitStreamEnd) { + mState = STATE_STOPPED; } } - return 0; - default: - return 0; + if (waitStreamEnd && status != DEAD_OBJECT) { + return NS_INACTIVE; + } + break; } + return 0; } // perform callbacks while unlocked @@ -1675,7 +1714,6 @@ status_t AudioTrack::restoreTrack_l(const char *from) // take the frames that will be lost by track recreation into account in saved position size_t position = mProxy->getPosition() + mProxy->getFramesFilled(); - mNewPosition = position + mUpdatePeriod; size_t bufferPosition = mStaticProxy != NULL ? mStaticProxy->getBufferPosition() : 0; result = createTrack_l(mStreamType, mSampleRate, @@ -1766,7 +1804,7 @@ status_t AudioTrack::dump(int fd, const Vector<String16>& args) const snprintf(buffer, 255, " stream type(%d), left - right volume(%f, %f)\n", mStreamType, mVolume[0], mVolume[1]); result.append(buffer); - snprintf(buffer, 255, " format(%d), channel count(%d), frame count(%d)\n", mFormat, + snprintf(buffer, 255, " format(%d), channel count(%d), frame count(%zu)\n", mFormat, mChannelCount, mFrameCount); result.append(buffer); snprintf(buffer, 255, " sample rate(%u), status(%d)\n", mSampleRate, mStatus); diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp index caa7900..d5b0b07 100644 --- a/media/libmedia/AudioTrackShared.cpp +++ b/media/libmedia/AudioTrackShared.cpp @@ -19,9 +19,9 @@ #include <private/media/AudioTrackShared.h> #include <utils/Log.h> -extern "C" { -#include "../private/bionic_futex.h" -} + +#include <linux/futex.h> +#include <sys/syscall.h> namespace android { @@ -206,12 +206,12 @@ status_t ClientProxy::obtainBuffer(Buffer* buffer, const struct timespec *reques } int32_t old = android_atomic_and(~CBLK_FUTEX_WAKE, &cblk->mFutex); if (!(old & CBLK_FUTEX_WAKE)) { - int rc; if (measure && !beforeIsValid) { clock_gettime(CLOCK_MONOTONIC, &before); beforeIsValid = true; } - int ret = __futex_syscall4(&cblk->mFutex, + errno = 0; + (void) syscall(__NR_futex, &cblk->mFutex, mClientInServer ? FUTEX_WAIT_PRIVATE : FUTEX_WAIT, old & ~CBLK_FUTEX_WAKE, ts); // update total elapsed time spent waiting if (measure) { @@ -230,16 +230,16 @@ status_t ClientProxy::obtainBuffer(Buffer* buffer, const struct timespec *reques before = after; beforeIsValid = true; } - switch (ret) { - case 0: // normal wakeup by server, or by binderDied() - case -EWOULDBLOCK: // benign race condition with server - case -EINTR: // wait was interrupted by signal or other spurious wakeup - case -ETIMEDOUT: // time-out expired + switch (errno) { + case 0: // normal wakeup by server, or by binderDied() + case EWOULDBLOCK: // benign race condition with server + case EINTR: // wait was interrupted by signal or other spurious wakeup + case ETIMEDOUT: // time-out expired // FIXME these error/non-0 status are being dropped break; default: - ALOGE("%s unexpected error %d", __func__, ret); - status = -ret; + status = errno; + ALOGE("%s unexpected error %s", __func__, strerror(status)); goto end; } } @@ -295,7 +295,7 @@ void ClientProxy::binderDied() audio_track_cblk_t* cblk = mCblk; if (!(android_atomic_or(CBLK_INVALID, &cblk->mFlags) & CBLK_INVALID)) { // it seems that a FUTEX_WAKE_PRIVATE will not wake a FUTEX_WAIT, even within same process - (void) __futex_syscall3(&cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, + (void) syscall(__NR_futex, &cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1); } } @@ -304,7 +304,7 @@ void ClientProxy::interrupt() { audio_track_cblk_t* cblk = mCblk; if (!(android_atomic_or(CBLK_INTERRUPT, &cblk->mFlags) & CBLK_INTERRUPT)) { - (void) __futex_syscall3(&cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, + (void) syscall(__NR_futex, &cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1); } } @@ -435,18 +435,18 @@ status_t AudioTrackClientProxy::waitStreamEndDone(const struct timespec *request } int32_t old = android_atomic_and(~CBLK_FUTEX_WAKE, &cblk->mFutex); if (!(old & CBLK_FUTEX_WAKE)) { - int rc; - int ret = __futex_syscall4(&cblk->mFutex, + errno = 0; + (void) syscall(__NR_futex, &cblk->mFutex, mClientInServer ? FUTEX_WAIT_PRIVATE : FUTEX_WAIT, old & ~CBLK_FUTEX_WAKE, ts); - switch (ret) { - case 0: // normal wakeup by server, or by binderDied() - case -EWOULDBLOCK: // benign race condition with server - case -EINTR: // wait was interrupted by signal or other spurious wakeup - case -ETIMEDOUT: // time-out expired + switch (errno) { + case 0: // normal wakeup by server, or by binderDied() + case EWOULDBLOCK: // benign race condition with server + case EINTR: // wait was interrupted by signal or other spurious wakeup + case ETIMEDOUT: // time-out expired break; default: - ALOGE("%s unexpected error %d", __func__, ret); - status = -ret; + status = errno; + ALOGE("%s unexpected error %s", __func__, strerror(status)); goto end; } } @@ -475,9 +475,14 @@ void StaticAudioTrackClientProxy::flush() void StaticAudioTrackClientProxy::setLoop(size_t loopStart, size_t loopEnd, int loopCount) { + // This can only happen on a 64-bit client + if (loopStart > UINT32_MAX || loopEnd > UINT32_MAX) { + // FIXME Should return an error status + return; + } StaticAudioTrackState newState; - newState.mLoopStart = loopStart; - newState.mLoopEnd = loopEnd; + newState.mLoopStart = (uint32_t) loopStart; + newState.mLoopEnd = (uint32_t) loopEnd; newState.mLoopCount = loopCount; mBufferPosition = loopStart; (void) mMutator.push(newState); @@ -487,7 +492,7 @@ size_t StaticAudioTrackClientProxy::getBufferPosition() { size_t bufferPosition; if (mMutator.ack()) { - bufferPosition = mCblk->u.mStatic.mBufferPosition; + bufferPosition = (size_t) mCblk->u.mStatic.mBufferPosition; if (bufferPosition > mFrameCount) { bufferPosition = mFrameCount; } @@ -530,7 +535,7 @@ status_t ServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush) if (front != rear) { int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex); if (!(old & CBLK_FUTEX_WAKE)) { - (void) __futex_syscall3(&cblk->mFutex, + (void) syscall(__NR_futex, &cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1); } } @@ -622,7 +627,7 @@ void ServerProxy::releaseBuffer(Buffer* buffer) if (half == 0) { half = 1; } - size_t minimum = cblk->mMinimum; + size_t minimum = (size_t) cblk->mMinimum; if (minimum == 0) { minimum = mIsOut ? half : 1; } else if (minimum > half) { @@ -633,7 +638,7 @@ void ServerProxy::releaseBuffer(Buffer* buffer) ALOGV("mAvailToClient=%u stepCount=%u minimum=%u", mAvailToClient, stepCount, minimum); int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex); if (!(old & CBLK_FUTEX_WAKE)) { - (void) __futex_syscall3(&cblk->mFutex, + (void) syscall(__NR_futex, &cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1); } } @@ -677,7 +682,7 @@ bool AudioTrackServerProxy::setStreamEndDone() { bool old = (android_atomic_or(CBLK_STREAM_END_DONE, &mCblk->mFlags) & CBLK_STREAM_END_DONE) != 0; if (!old) { - (void) __futex_syscall3(&mCblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, + (void) syscall(__NR_futex, &mCblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1); } return old; @@ -760,7 +765,8 @@ ssize_t StaticAudioTrackServerProxy::pollPosition() mIsShutdown = true; return (ssize_t) NO_INIT; } - mCblk->u.mStatic.mBufferPosition = position; + // This may overflow, but client is not supposed to rely on it + mCblk->u.mStatic.mBufferPosition = (uint32_t) position; } return (ssize_t) position; } @@ -836,7 +842,8 @@ void StaticAudioTrackServerProxy::releaseBuffer(Buffer* buffer) mPosition = newPosition; cblk->mServer += stepCount; - cblk->u.mStatic.mBufferPosition = newPosition; + // This may overflow, but client is not supposed to rely on it + cblk->u.mStatic.mBufferPosition = (uint32_t) newPosition; if (setFlags != 0) { (void) android_atomic_or(setFlags, &cblk->mFlags); // this would be a good place to wake a futex diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index acfaea0..e02107f 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -106,7 +106,7 @@ public: data.writeInt32(sampleRate); data.writeInt32(format); data.writeInt32(channelMask); - data.writeInt32(frameCount); + data.writeInt64(frameCount); track_flags_t lFlags = flags != NULL ? *flags : (track_flags_t) TRACK_DEFAULT; data.writeInt32(lFlags); if (sharedBuffer != 0) { @@ -163,7 +163,7 @@ public: data.writeInt32(sampleRate); data.writeInt32(format); data.writeInt32(channelMask); - data.writeInt32(frameCount); + data.writeInt64(frameCount); track_flags_t lFlags = flags != NULL ? *flags : (track_flags_t) TRACK_DEFAULT; data.writeInt32(lFlags); data.writeInt32((int32_t) tid); @@ -228,7 +228,7 @@ public: data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); data.writeInt32((int32_t) output); remote()->transact(FRAME_COUNT, data, &reply); - return reply.readInt32(); + return reply.readInt64(); } virtual uint32_t latency(audio_io_handle_t output) const @@ -378,7 +378,7 @@ public: data.writeInt32(format); data.writeInt32(channelMask); remote()->transact(GET_INPUTBUFFERSIZE, data, &reply); - return reply.readInt32(); + return reply.readInt64(); } virtual audio_io_handle_t openOutput(audio_module_handle_t module, @@ -525,7 +525,7 @@ public: return reply.readInt32(); } - virtual status_t getRenderPosition(size_t *halFrames, size_t *dspFrames, + virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, audio_io_handle_t output) const { Parcel data, reply; @@ -546,7 +546,7 @@ public: return status; } - virtual size_t getInputFramesLost(audio_io_handle_t ioHandle) const + virtual uint32_t getInputFramesLost(audio_io_handle_t ioHandle) const { Parcel data, reply; data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); @@ -726,7 +726,7 @@ public: Parcel data, reply; data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); remote()->transact(GET_PRIMARY_OUTPUT_FRAME_COUNT, data, &reply); - return reply.readInt32(); + return reply.readInt64(); } virtual status_t setLowRamDevice(bool isLowRamDevice) @@ -754,7 +754,7 @@ status_t BnAudioFlinger::onTransact( uint32_t sampleRate = data.readInt32(); audio_format_t format = (audio_format_t) data.readInt32(); audio_channel_mask_t channelMask = data.readInt32(); - size_t frameCount = data.readInt32(); + size_t frameCount = data.readInt64(); track_flags_t flags = (track_flags_t) data.readInt32(); bool haveSharedBuffer = data.readInt32() != 0; sp<IMemory> buffer; @@ -791,7 +791,7 @@ status_t BnAudioFlinger::onTransact( uint32_t sampleRate = data.readInt32(); audio_format_t format = (audio_format_t) data.readInt32(); audio_channel_mask_t channelMask = data.readInt32(); - size_t frameCount = data.readInt32(); + size_t frameCount = data.readInt64(); track_flags_t flags = (track_flags_t) data.readInt32(); pid_t tid = (pid_t) data.readInt32(); int sessionId = data.readInt32(); @@ -817,7 +817,7 @@ status_t BnAudioFlinger::onTransact( } break; case FRAME_COUNT: { CHECK_INTERFACE(IAudioFlinger, data, reply); - reply->writeInt32( frameCount((audio_io_handle_t) data.readInt32()) ); + reply->writeInt64( frameCount((audio_io_handle_t) data.readInt32()) ); return NO_ERROR; } break; case LATENCY: { @@ -916,7 +916,7 @@ status_t BnAudioFlinger::onTransact( uint32_t sampleRate = data.readInt32(); audio_format_t format = (audio_format_t) data.readInt32(); audio_channel_mask_t channelMask = data.readInt32(); - reply->writeInt32( getInputBufferSize(sampleRate, format, channelMask) ); + reply->writeInt64( getInputBufferSize(sampleRate, format, channelMask) ); return NO_ERROR; } break; case OPEN_OUTPUT: { @@ -1013,8 +1013,8 @@ status_t BnAudioFlinger::onTransact( case GET_RENDER_POSITION: { CHECK_INTERFACE(IAudioFlinger, data, reply); audio_io_handle_t output = (audio_io_handle_t) data.readInt32(); - size_t halFrames; - size_t dspFrames; + uint32_t halFrames; + uint32_t dspFrames; status_t status = getRenderPosition(&halFrames, &dspFrames, output); reply->writeInt32(status); if (status == NO_ERROR) { @@ -1119,7 +1119,7 @@ status_t BnAudioFlinger::onTransact( } break; case GET_PRIMARY_OUTPUT_FRAME_COUNT: { CHECK_INTERFACE(IAudioFlinger, data, reply); - reply->writeInt32(getPrimaryOutputFrameCount()); + reply->writeInt64(getPrimaryOutputFrameCount()); return NO_ERROR; } break; case SET_LOW_RAM_DEVICE: { diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp index 3c0d4cf..1c299f7 100644 --- a/media/libmedia/IAudioFlingerClient.cpp +++ b/media/libmedia/IAudioFlingerClient.cpp @@ -55,7 +55,7 @@ public: data.writeInt32(desc->samplingRate); data.writeInt32(desc->format); data.writeInt32(desc->channelMask); - data.writeInt32(desc->frameCount); + data.writeInt64(desc->frameCount); data.writeInt32(desc->latency); } remote()->transact(IO_CONFIG_CHANGED, data, &reply, IBinder::FLAG_ONEWAY); @@ -85,7 +85,7 @@ status_t BnAudioFlingerClient::onTransact( desc.samplingRate = data.readInt32(); desc.format = (audio_format_t) data.readInt32(); desc.channelMask = (audio_channel_mask_t) data.readInt32(); - desc.frameCount = data.readInt32(); + desc.frameCount = data.readInt64(); desc.latency = data.readInt32(); param2 = &desc; } diff --git a/media/libmedia/IAudioTrack.cpp b/media/libmedia/IAudioTrack.cpp index 3cd9cfd..e9df704 100644 --- a/media/libmedia/IAudioTrack.cpp +++ b/media/libmedia/IAudioTrack.cpp @@ -115,7 +115,7 @@ public: virtual status_t allocateTimedBuffer(size_t size, sp<IMemory>* buffer) { Parcel data, reply; data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); - data.writeInt32(size); + data.writeInt64(size); status_t status = remote()->transact(ALLOCATE_TIMED_BUFFER, data, &reply); if (status == NO_ERROR) { @@ -232,7 +232,7 @@ status_t BnAudioTrack::onTransact( case ALLOCATE_TIMED_BUFFER: { CHECK_INTERFACE(IAudioTrack, data, reply); sp<IMemory> buffer; - status_t status = allocateTimedBuffer(data.readInt32(), &buffer); + status_t status = allocateTimedBuffer(data.readInt64(), &buffer); reply->writeInt32(status); if (status == NO_ERROR) { reply->writeStrongBinder(buffer->asBinder()); diff --git a/media/libmedia/ICrypto.cpp b/media/libmedia/ICrypto.cpp index 98b183a..0d5f990 100644 --- a/media/libmedia/ICrypto.cpp +++ b/media/libmedia/ICrypto.cpp @@ -131,7 +131,7 @@ struct BpCrypto : public BpInterface<ICrypto> { data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples); if (secure) { - data.writeIntPtr((intptr_t)dstPtr); + data.writeInt64(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(dstPtr))); } remote()->transact(DECRYPT, data, &reply); @@ -249,7 +249,7 @@ status_t BnCrypto::onTransact( void *dstPtr; if (secure) { - dstPtr = (void *)data.readIntPtr(); + dstPtr = reinterpret_cast<void *>(static_cast<uintptr_t>(data.readInt64())); } else { dstPtr = malloc(totalSize); } diff --git a/media/libmedia/IMediaLogService.cpp b/media/libmedia/IMediaLogService.cpp index 33239a7..8a66c7c 100644 --- a/media/libmedia/IMediaLogService.cpp +++ b/media/libmedia/IMediaLogService.cpp @@ -43,7 +43,7 @@ public: Parcel data, reply; data.writeInterfaceToken(IMediaLogService::getInterfaceDescriptor()); data.writeStrongBinder(shared->asBinder()); - data.writeInt32((int32_t) size); + data.writeInt64((int64_t) size); data.writeCString(name); status_t status = remote()->transact(REGISTER_WRITER, data, &reply); // FIXME ignores status @@ -71,7 +71,7 @@ status_t BnMediaLogService::onTransact( case REGISTER_WRITER: { CHECK_INTERFACE(IMediaLogService, data, reply); sp<IMemory> shared = interface_cast<IMemory>(data.readStrongBinder()); - size_t size = (size_t) data.readInt32(); + size_t size = (size_t) data.readInt64(); const char *name = data.readCString(); registerWriter(shared, size, name); return NO_ERROR; diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp index bb066a0..a91ad49 100644 --- a/media/libmedia/IMediaMetadataRetriever.cpp +++ b/media/libmedia/IMediaMetadataRetriever.cpp @@ -94,7 +94,7 @@ public: data.writeInt32(0); } else { // serialize the headers - data.writeInt32(headers->size()); + data.writeInt64(headers->size()); for (size_t i = 0; i < headers->size(); ++i) { data.writeString8(headers->keyAt(i)); data.writeString8(headers->valueAt(i)); @@ -198,8 +198,8 @@ status_t BnMediaMetadataRetriever::onTransact( const char* srcUrl = data.readCString(); KeyedVector<String8, String8> headers; - int32_t numHeaders = data.readInt32(); - for (int i = 0; i < numHeaders; ++i) { + size_t numHeaders = (size_t) data.readInt64(); + for (size_t i = 0; i < numHeaders; ++i) { String8 key = data.readString8(); String8 value = data.readString8(); headers.add(key, value); diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp index 71ce320..5df232f 100644 --- a/media/libmedia/IOMX.cpp +++ b/media/libmedia/IOMX.cpp @@ -65,7 +65,7 @@ public: virtual bool livesLocally(node_id node, pid_t pid) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(pid); remote()->transact(LIVES_LOCALLY, data, &reply); @@ -104,7 +104,7 @@ public: status_t err = reply.readInt32(); if (err == OK) { - *node = (void*)reply.readIntPtr(); + *node = (node_id)reply.readInt32(); } else { *node = 0; } @@ -115,7 +115,7 @@ public: virtual status_t freeNode(node_id node) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); remote()->transact(FREE_NODE, data, &reply); return reply.readInt32(); @@ -125,7 +125,7 @@ public: node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(cmd); data.writeInt32(param); remote()->transact(SEND_COMMAND, data, &reply); @@ -138,9 +138,9 @@ public: void *params, size_t size) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(index); - data.writeInt32(size); + data.writeInt64(size); data.write(params, size); remote()->transact(GET_PARAMETER, data, &reply); @@ -159,9 +159,9 @@ public: const void *params, size_t size) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(index); - data.writeInt32(size); + data.writeInt64(size); data.write(params, size); remote()->transact(SET_PARAMETER, data, &reply); @@ -173,9 +173,9 @@ public: void *params, size_t size) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(index); - data.writeInt32(size); + data.writeInt64(size); data.write(params, size); remote()->transact(GET_CONFIG, data, &reply); @@ -194,9 +194,9 @@ public: const void *params, size_t size) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(index); - data.writeInt32(size); + data.writeInt64(size); data.write(params, size); remote()->transact(SET_CONFIG, data, &reply); @@ -207,7 +207,7 @@ public: node_id node, OMX_STATETYPE* state) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); remote()->transact(GET_STATE, data, &reply); *state = static_cast<OMX_STATETYPE>(reply.readInt32()); @@ -218,7 +218,7 @@ public: node_id node, OMX_U32 port_index, OMX_BOOL enable) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(port_index); data.writeInt32((uint32_t)enable); remote()->transact(ENABLE_GRAPHIC_BUFFERS, data, &reply); @@ -231,7 +231,7 @@ public: node_id node, OMX_U32 port_index, OMX_U32* usage) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(port_index); remote()->transact(GET_GRAPHIC_BUFFER_USAGE, data, &reply); @@ -245,7 +245,7 @@ public: buffer_id *buffer) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(port_index); data.writeStrongBinder(params->asBinder()); remote()->transact(USE_BUFFER, data, &reply); @@ -257,7 +257,7 @@ public: return err; } - *buffer = (void*)reply.readIntPtr(); + *buffer = (buffer_id)reply.readInt32(); return err; } @@ -268,7 +268,7 @@ public: const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(port_index); data.write(*graphicBuffer); remote()->transact(USE_GRAPHIC_BUFFER, data, &reply); @@ -280,7 +280,7 @@ public: return err; } - *buffer = (void*)reply.readIntPtr(); + *buffer = (buffer_id)reply.readInt32(); return err; } @@ -290,10 +290,10 @@ public: const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(port_index); data.write(*graphicBuffer); - data.writeIntPtr((intptr_t)buffer); + data.writeInt32((int32_t)buffer); remote()->transact(UPDATE_GRAPHIC_BUFFER_IN_META, data, &reply); status_t err = reply.readInt32(); @@ -306,7 +306,7 @@ public: Parcel data, reply; status_t err; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(port_index); err = remote()->transact(CREATE_INPUT_SURFACE, data, &reply); if (err != OK) { @@ -329,7 +329,7 @@ public: Parcel data, reply; status_t err; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); err = remote()->transact(SIGNAL_END_OF_INPUT_STREAM, data, &reply); if (err != OK) { ALOGW("binder transaction failed: %d", err); @@ -343,7 +343,7 @@ public: node_id node, OMX_U32 port_index, OMX_BOOL enable) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(port_index); data.writeInt32((uint32_t)enable); remote()->transact(STORE_META_DATA_IN_BUFFERS, data, &reply); @@ -357,7 +357,7 @@ public: OMX_U32 max_width, OMX_U32 max_height) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(port_index); data.writeInt32((int32_t)enable); data.writeInt32(max_width); @@ -373,9 +373,9 @@ public: buffer_id *buffer, void **buffer_data) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(port_index); - data.writeInt32(size); + data.writeInt64(size); remote()->transact(ALLOC_BUFFER, data, &reply); status_t err = reply.readInt32(); @@ -385,8 +385,8 @@ public: return err; } - *buffer = (void *)reply.readIntPtr(); - *buffer_data = (void *)reply.readIntPtr(); + *buffer = (buffer_id)reply.readInt32(); + *buffer_data = (void *)reply.readInt64(); return err; } @@ -396,7 +396,7 @@ public: buffer_id *buffer) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(port_index); data.writeStrongBinder(params->asBinder()); remote()->transact(ALLOC_BUFFER_WITH_BACKUP, data, &reply); @@ -408,7 +408,7 @@ public: return err; } - *buffer = (void*)reply.readIntPtr(); + *buffer = (buffer_id)reply.readInt32(); return err; } @@ -417,9 +417,9 @@ public: node_id node, OMX_U32 port_index, buffer_id buffer) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(port_index); - data.writeIntPtr((intptr_t)buffer); + data.writeInt32((int32_t)buffer); remote()->transact(FREE_BUFFER, data, &reply); return reply.readInt32(); @@ -428,8 +428,8 @@ public: virtual status_t fillBuffer(node_id node, buffer_id buffer) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); - data.writeIntPtr((intptr_t)buffer); + data.writeInt32((int32_t)node); + data.writeInt32((int32_t)buffer); remote()->transact(FILL_BUFFER, data, &reply); return reply.readInt32(); @@ -442,8 +442,8 @@ public: OMX_U32 flags, OMX_TICKS timestamp) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); - data.writeIntPtr((intptr_t)buffer); + data.writeInt32((int32_t)node); + data.writeInt32((int32_t)buffer); data.writeInt32(range_offset); data.writeInt32(range_length); data.writeInt32(flags); @@ -459,7 +459,7 @@ public: OMX_INDEXTYPE *index) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeCString(parameter_name); remote()->transact(GET_EXTENSION_INDEX, data, &reply); @@ -482,9 +482,9 @@ public: size_t size) { Parcel data, reply; data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); - data.writeIntPtr((intptr_t)node); + data.writeInt32((int32_t)node); data.writeInt32(port_index); - data.writeInt32(size); + data.writeInt64(size); data.write(optionData, size); data.writeInt32(type); remote()->transact(SET_INTERNAL_OPTION, data, &reply); @@ -509,7 +509,7 @@ status_t BnOMX::onTransact( case LIVES_LOCALLY: { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void *)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); pid_t pid = (pid_t)data.readInt32(); reply->writeInt32(livesLocally(node, pid)); @@ -553,7 +553,7 @@ status_t BnOMX::onTransact( status_t err = allocateNode(name, observer, &node); reply->writeInt32(err); if (err == OK) { - reply->writeIntPtr((intptr_t)node); + reply->writeInt32((int32_t)node); } return NO_ERROR; @@ -563,7 +563,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); reply->writeInt32(freeNode(node)); @@ -574,7 +574,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_COMMANDTYPE cmd = static_cast<OMX_COMMANDTYPE>(data.readInt32()); @@ -593,10 +593,10 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32()); - size_t size = data.readInt32(); + size_t size = data.readInt64(); void *params = malloc(size); data.read(params, size); @@ -644,7 +644,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_STATETYPE state = OMX_StateInvalid; status_t err = getState(node, &state); @@ -658,7 +658,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_U32 port_index = data.readInt32(); OMX_BOOL enable = (OMX_BOOL)data.readInt32(); @@ -672,7 +672,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_U32 port_index = data.readInt32(); OMX_U32 usage = 0; @@ -687,7 +687,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_U32 port_index = data.readInt32(); sp<IMemory> params = interface_cast<IMemory>(data.readStrongBinder()); @@ -697,7 +697,7 @@ status_t BnOMX::onTransact( reply->writeInt32(err); if (err == OK) { - reply->writeIntPtr((intptr_t)buffer); + reply->writeInt32((int32_t)buffer); } return NO_ERROR; @@ -707,7 +707,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_U32 port_index = data.readInt32(); sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(); data.read(*graphicBuffer); @@ -718,7 +718,7 @@ status_t BnOMX::onTransact( reply->writeInt32(err); if (err == OK) { - reply->writeIntPtr((intptr_t)buffer); + reply->writeInt32((int32_t)buffer); } return NO_ERROR; @@ -728,11 +728,11 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_U32 port_index = data.readInt32(); sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(); data.read(*graphicBuffer); - buffer_id buffer = (void*)data.readIntPtr(); + buffer_id buffer = (buffer_id)data.readInt32(); status_t err = updateGraphicBufferInMeta( node, port_index, graphicBuffer, buffer); @@ -745,7 +745,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_U32 port_index = data.readInt32(); sp<IGraphicBufferProducer> bufferProducer; @@ -765,7 +765,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); status_t err = signalEndOfInputStream(node); reply->writeInt32(err); @@ -777,7 +777,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_U32 port_index = data.readInt32(); OMX_BOOL enable = (OMX_BOOL)data.readInt32(); @@ -791,7 +791,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_U32 port_index = data.readInt32(); OMX_BOOL enable = (OMX_BOOL)data.readInt32(); OMX_U32 max_width = data.readInt32(); @@ -808,9 +808,9 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_U32 port_index = data.readInt32(); - size_t size = data.readInt32(); + size_t size = data.readInt64(); buffer_id buffer; void *buffer_data; @@ -819,8 +819,8 @@ status_t BnOMX::onTransact( reply->writeInt32(err); if (err == OK) { - reply->writeIntPtr((intptr_t)buffer); - reply->writeIntPtr((intptr_t)buffer_data); + reply->writeInt32((int32_t)buffer); + reply->writeInt64((uintptr_t)buffer_data); } return NO_ERROR; @@ -830,7 +830,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_U32 port_index = data.readInt32(); sp<IMemory> params = interface_cast<IMemory>(data.readStrongBinder()); @@ -842,7 +842,7 @@ status_t BnOMX::onTransact( reply->writeInt32(err); if (err == OK) { - reply->writeIntPtr((intptr_t)buffer); + reply->writeInt32((int32_t)buffer); } return NO_ERROR; @@ -852,9 +852,9 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); OMX_U32 port_index = data.readInt32(); - buffer_id buffer = (void*)data.readIntPtr(); + buffer_id buffer = (buffer_id)data.readInt32(); reply->writeInt32(freeBuffer(node, port_index, buffer)); return NO_ERROR; @@ -864,8 +864,8 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); - buffer_id buffer = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); + buffer_id buffer = (buffer_id)data.readInt32(); reply->writeInt32(fillBuffer(node, buffer)); return NO_ERROR; @@ -875,8 +875,8 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); - buffer_id buffer = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); + buffer_id buffer = (buffer_id)data.readInt32(); OMX_U32 range_offset = data.readInt32(); OMX_U32 range_length = data.readInt32(); OMX_U32 flags = data.readInt32(); @@ -894,7 +894,7 @@ status_t BnOMX::onTransact( { CHECK_OMX_INTERFACE(IOMX, data, reply); - node_id node = (void*)data.readIntPtr(); + node_id node = (node_id)data.readInt32(); const char *parameter_name = data.readCString(); OMX_INDEXTYPE index; @@ -927,6 +927,8 @@ public: data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor()); data.write(&msg, sizeof(msg)); + ALOGV("onMessage writing message %d, size %zu", msg.type, sizeof(msg)); + remote()->transact(OBSERVER_ON_MSG, data, &reply, IBinder::FLAG_ONEWAY); } }; @@ -943,6 +945,8 @@ status_t BnOMXObserver::onTransact( omx_message msg; data.read(&msg, sizeof(msg)); + ALOGV("onTransact reading message %d, size %zu", msg.type, sizeof(msg)); + // XXX Could use readInplace maybe? onMessage(msg); diff --git a/media/libmedia/IStreamSource.cpp b/media/libmedia/IStreamSource.cpp index 68ffca8..fe2cc61 100644 --- a/media/libmedia/IStreamSource.cpp +++ b/media/libmedia/IStreamSource.cpp @@ -62,7 +62,7 @@ struct BpStreamSource : public BpInterface<IStreamSource> { virtual void setBuffers(const Vector<sp<IMemory> > &buffers) { Parcel data, reply; data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor()); - data.writeInt32(static_cast<int32_t>(buffers.size())); + data.writeInt64(static_cast<int64_t>(buffers.size())); for (size_t i = 0; i < buffers.size(); ++i) { data.writeStrongBinder(buffers.itemAt(i)->asBinder()); } @@ -72,7 +72,7 @@ struct BpStreamSource : public BpInterface<IStreamSource> { virtual void onBufferAvailable(size_t index) { Parcel data, reply; data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor()); - data.writeInt32(static_cast<int32_t>(index)); + data.writeInt64(static_cast<int64_t>(index)); remote()->transact( ON_BUFFER_AVAILABLE, data, &reply, IBinder::FLAG_ONEWAY); } @@ -102,7 +102,7 @@ status_t BnStreamSource::onTransact( case SET_BUFFERS: { CHECK_INTERFACE(IStreamSource, data, reply); - size_t n = static_cast<size_t>(data.readInt32()); + size_t n = static_cast<size_t>(data.readInt64()); Vector<sp<IMemory> > buffers; for (size_t i = 0; i < n; ++i) { sp<IMemory> mem = @@ -117,7 +117,7 @@ status_t BnStreamSource::onTransact( case ON_BUFFER_AVAILABLE: { CHECK_INTERFACE(IStreamSource, data, reply); - onBufferAvailable(static_cast<size_t>(data.readInt32())); + onBufferAvailable(static_cast<size_t>(data.readInt64())); break; } @@ -145,8 +145,8 @@ struct BpStreamListener : public BpInterface<IStreamListener> { virtual void queueBuffer(size_t index, size_t size) { Parcel data, reply; data.writeInterfaceToken(IStreamListener::getInterfaceDescriptor()); - data.writeInt32(static_cast<int32_t>(index)); - data.writeInt32(static_cast<int32_t>(size)); + data.writeInt64(static_cast<int64_t>(index)); + data.writeInt64(static_cast<int64_t>(size)); remote()->transact(QUEUE_BUFFER, data, &reply, IBinder::FLAG_ONEWAY); } @@ -177,8 +177,8 @@ status_t BnStreamListener::onTransact( case QUEUE_BUFFER: { CHECK_INTERFACE(IStreamListener, data, reply); - size_t index = static_cast<size_t>(data.readInt32()); - size_t size = static_cast<size_t>(data.readInt32()); + size_t index = static_cast<size_t>(data.readInt64()); + size_t size = static_cast<size_t>(data.readInt64()); queueBuffer(index, size); break; diff --git a/media/libmedia/MediaScanner.cpp b/media/libmedia/MediaScanner.cpp index 28b5aa7..dcbb769 100644 --- a/media/libmedia/MediaScanner.cpp +++ b/media/libmedia/MediaScanner.cpp @@ -237,4 +237,24 @@ MediaScanResult MediaScanner::doProcessDirectoryEntry( return MEDIA_SCAN_RESULT_OK; } +MediaAlbumArt *MediaAlbumArt::clone() { + size_t byte_size = this->size() + sizeof(MediaAlbumArt); + MediaAlbumArt *result = reinterpret_cast<MediaAlbumArt *>(malloc(byte_size)); + result->mSize = this->size(); + memcpy(&result->mData[0], &this->mData[0], this->size()); + return result; +} + +void MediaAlbumArt::init(MediaAlbumArt *instance, int32_t dataSize, const void *data) { + instance->mSize = dataSize; + memcpy(&instance->mData[0], data, dataSize); +} + +MediaAlbumArt *MediaAlbumArt::fromData(int32_t dataSize, const void* data) { + size_t byte_size = sizeof(MediaAlbumArt) + dataSize; + MediaAlbumArt *result = reinterpret_cast<MediaAlbumArt *>(malloc(byte_size)); + init(result, dataSize, data); + return result; +} + } // namespace android diff --git a/media/libmedia/MemoryLeakTrackUtil.cpp b/media/libmedia/MemoryLeakTrackUtil.cpp index 6a108ae..66f7161 100644 --- a/media/libmedia/MemoryLeakTrackUtil.cpp +++ b/media/libmedia/MemoryLeakTrackUtil.cpp @@ -17,6 +17,7 @@ #include <media/MemoryLeakTrackUtil.h> #include <stdio.h> +#include <stdlib.h> #include <sys/types.h> #include <unistd.h> @@ -49,7 +50,7 @@ struct MyString8 { } void append(const char *s) { - strcat(mPtr, s); + strncat(mPtr, s, MAX_SIZE - size() - 1); } const char *string() const { @@ -60,6 +61,10 @@ struct MyString8 { return strlen(mPtr); } + void clear() { + *mPtr = '\0'; + } + private: char *mPtr; @@ -139,6 +144,9 @@ void dumpMemoryAddresses(int fd) } } while (moved); + write(fd, result.string(), result.size()); + result.clear(); + for (size_t i = 0; i < count; i++) { AllocEntry *e = &entries[i]; @@ -152,13 +160,14 @@ void dumpMemoryAddresses(int fd) result.append(buffer); } result.append("\n"); + + write(fd, result.string(), result.size()); + result.clear(); } delete[] entries; free_malloc_leak_info(info); } - - write(fd, result.string(), result.size()); } #else diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index 0f6d897..7a6f31d 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -654,7 +654,7 @@ status_t MediaPlayer::setRetransmitEndpoint(const char* addrString, return BAD_VALUE; } - memset(&mRetransmitEndpoint, 0, sizeof(&mRetransmitEndpoint)); + memset(&mRetransmitEndpoint, 0, sizeof(mRetransmitEndpoint)); mRetransmitEndpoint.sin_family = AF_INET; mRetransmitEndpoint.sin_addr = saddr; mRetransmitEndpoint.sin_port = htons(port); diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk index 8f21632..a645f13 100644 --- a/media/libmediaplayerservice/Android.mk +++ b/media/libmediaplayerservice/Android.mk @@ -26,6 +26,7 @@ LOCAL_SRC_FILES:= \ LOCAL_SHARED_LIBRARIES := \ libbinder \ libcamera_client \ + libcrypto \ libcutils \ liblog \ libdl \ @@ -54,6 +55,8 @@ LOCAL_C_INCLUDES := \ LOCAL_MODULE:= libmediaplayerservice +LOCAL_32_BIT_ONLY := true + include $(BUILD_SHARED_LIBRARY) include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/media/libmediaplayerservice/MediaPlayerFactory.cpp b/media/libmediaplayerservice/MediaPlayerFactory.cpp index 90aed39..09e6976 100644 --- a/media/libmediaplayerservice/MediaPlayerFactory.cpp +++ b/media/libmediaplayerservice/MediaPlayerFactory.cpp @@ -170,11 +170,11 @@ sp<MediaPlayerBase> MediaPlayerFactory::createPlayer( class StagefrightPlayerFactory : public MediaPlayerFactory::IFactory { public: - virtual float scoreFactory(const sp<IMediaPlayer>& client, + virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/, int fd, int64_t offset, - int64_t length, - float curScore) { + int64_t /*length*/, + float /*curScore*/) { char buf[20]; lseek(fd, offset, SEEK_SET); read(fd, buf, sizeof(buf)); @@ -197,7 +197,7 @@ class StagefrightPlayerFactory : class NuPlayerFactory : public MediaPlayerFactory::IFactory { public: - virtual float scoreFactory(const sp<IMediaPlayer>& client, + virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/, const char* url, float curScore) { static const float kOurScore = 0.8; @@ -229,9 +229,9 @@ class NuPlayerFactory : public MediaPlayerFactory::IFactory { return 0.0; } - virtual float scoreFactory(const sp<IMediaPlayer>& client, - const sp<IStreamSource> &source, - float curScore) { + virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/, + const sp<IStreamSource>& /*source*/, + float /*curScore*/) { return 1.0; } @@ -243,7 +243,7 @@ class NuPlayerFactory : public MediaPlayerFactory::IFactory { class SonivoxPlayerFactory : public MediaPlayerFactory::IFactory { public: - virtual float scoreFactory(const sp<IMediaPlayer>& client, + virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/, const char* url, float curScore) { static const float kOurScore = 0.4; @@ -274,7 +274,7 @@ class SonivoxPlayerFactory : public MediaPlayerFactory::IFactory { return 0.0; } - virtual float scoreFactory(const sp<IMediaPlayer>& client, + virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/, int fd, int64_t offset, int64_t length, @@ -312,9 +312,9 @@ class SonivoxPlayerFactory : public MediaPlayerFactory::IFactory { class TestPlayerFactory : public MediaPlayerFactory::IFactory { public: - virtual float scoreFactory(const sp<IMediaPlayer>& client, + virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/, const char* url, - float curScore) { + float /*curScore*/) { if (TestPlayerStub::canBeUsed(url)) { return 1.0; } diff --git a/media/libmediaplayerservice/MediaPlayerFactory.h b/media/libmediaplayerservice/MediaPlayerFactory.h index fe8972b..5ddde19 100644 --- a/media/libmediaplayerservice/MediaPlayerFactory.h +++ b/media/libmediaplayerservice/MediaPlayerFactory.h @@ -29,19 +29,19 @@ class MediaPlayerFactory { public: virtual ~IFactory() { } - virtual float scoreFactory(const sp<IMediaPlayer>& client, - const char* url, - float curScore) { return 0.0; } - - virtual float scoreFactory(const sp<IMediaPlayer>& client, - int fd, - int64_t offset, - int64_t length, - float curScore) { return 0.0; } - - virtual float scoreFactory(const sp<IMediaPlayer>& client, - const sp<IStreamSource> &source, - float curScore) { return 0.0; } + virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/, + const char* /*url*/, + float /*curScore*/) { return 0.0; } + + virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/, + int /*fd*/, + int64_t /*offset*/, + int64_t /*length*/, + float /*curScore*/) { return 0.0; } + + virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/, + const sp<IStreamSource> &/*source*/, + float /*curScore*/) { return 0.0; } virtual sp<MediaPlayerBase> createPlayer() = 0; }; diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index cd052e6..a392b76 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -319,7 +319,7 @@ status_t MediaPlayerService::AudioCache::dump(int fd, const Vector<String16>& ar result.append(" AudioCache\n"); if (mHeap != 0) { - snprintf(buffer, 255, " heap base(%p), size(%d), flags(%d)\n", + snprintf(buffer, 255, " heap base(%p), size(%zu), flags(%d)\n", mHeap->getBase(), mHeap->getSize(), mHeap->getFlags()); result.append(buffer); } @@ -1813,6 +1813,12 @@ int MediaPlayerService::AudioOutput::getSessionId() const return mSessionId; } +uint32_t MediaPlayerService::AudioOutput::getSampleRate() const +{ + if (mTrack == 0) return 0; + return mTrack->getSampleRate(); +} + #undef LOG_TAG #define LOG_TAG "AudioCache" MediaPlayerService::AudioCache::AudioCache(const sp<IMemoryHeap>& heap) : @@ -2015,6 +2021,14 @@ int MediaPlayerService::AudioCache::getSessionId() const return 0; } +uint32_t MediaPlayerService::AudioCache::getSampleRate() const +{ + if (mMsecsPerFrame == 0) { + return 0; + } + return (uint32_t)(1.e3 / mMsecsPerFrame); +} + void MediaPlayerService::addBatteryData(uint32_t params) { Mutex::Autolock lock(mLock); diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index a486cb5..9c084e1 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -86,6 +86,7 @@ class MediaPlayerService : public BnMediaPlayerService virtual status_t getPosition(uint32_t *position) const; virtual status_t getFramesWritten(uint32_t *frameswritten) const; virtual int getSessionId() const; + virtual uint32_t getSampleRate() const; virtual status_t open( uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask, @@ -195,6 +196,7 @@ class MediaPlayerService : public BnMediaPlayerService virtual status_t getPosition(uint32_t *position) const; virtual status_t getFramesWritten(uint32_t *frameswritten) const; virtual int getSessionId() const; + virtual uint32_t getSampleRate() const; virtual status_t open( uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask, diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp index 348957f..063eb94 100644 --- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp +++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp @@ -56,7 +56,7 @@ MetadataRetrieverClient::~MetadataRetrieverClient() disconnect(); } -status_t MetadataRetrieverClient::dump(int fd, const Vector<String16>& args) const +status_t MetadataRetrieverClient::dump(int fd, const Vector<String16>& /*args*/) const { const size_t SIZE = 256; char buffer[SIZE]; @@ -230,7 +230,7 @@ sp<IMemory> MetadataRetrieverClient::extractAlbumArt() ALOGE("failed to extract an album art"); return NULL; } - size_t size = sizeof(MediaAlbumArt) + albumArt->mSize; + size_t size = sizeof(MediaAlbumArt) + albumArt->size(); sp<MemoryHeapBase> heap = new MemoryHeapBase(size, 0, "MetadataRetrieverClient"); if (heap == NULL) { ALOGE("failed to create MemoryDealer object"); @@ -243,11 +243,9 @@ sp<IMemory> MetadataRetrieverClient::extractAlbumArt() delete albumArt; return NULL; } - MediaAlbumArt *albumArtCopy = static_cast<MediaAlbumArt *>(mAlbumArt->pointer()); - albumArtCopy->mSize = albumArt->mSize; - albumArtCopy->mData = (uint8_t *)albumArtCopy + sizeof(MediaAlbumArt); - memcpy(albumArtCopy->mData, albumArt->mData, albumArt->mSize); - delete albumArt; // Fix memory leakage + MediaAlbumArt::init((MediaAlbumArt *) mAlbumArt->pointer(), + albumArt->size(), albumArt->data()); + delete albumArt; // We've taken our copy. return mAlbumArt; } diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h index 24d59b4..16792ab 100644 --- a/media/libmediaplayerservice/MidiFile.h +++ b/media/libmediaplayerservice/MidiFile.h @@ -36,7 +36,7 @@ public: virtual status_t setDataSource(int fd, int64_t offset, int64_t length); virtual status_t setVideoSurfaceTexture( - const sp<IGraphicBufferProducer>& bufferProducer) + const sp<IGraphicBufferProducer>& /*bufferProducer*/) { return UNKNOWN_ERROR; } virtual status_t prepare(); virtual status_t prepareAsync(); @@ -51,13 +51,13 @@ public: virtual status_t reset(); virtual status_t setLooping(int loop); virtual player_type playerType() { return SONIVOX_PLAYER; } - virtual status_t invoke(const Parcel& request, Parcel *reply) { + virtual status_t invoke(const Parcel& /*request*/, Parcel* /*reply*/) { return INVALID_OPERATION; } - virtual status_t setParameter(int key, const Parcel &request) { + virtual status_t setParameter(int /*key*/, const Parcel &/*request*/) { return INVALID_OPERATION; } - virtual status_t getParameter(int key, Parcel *reply) { + virtual status_t getParameter(int /*key*/, Parcel* /*reply*/) { return INVALID_OPERATION; } diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp index de61d9b..42b7766 100644 --- a/media/libmediaplayerservice/StagefrightPlayer.cpp +++ b/media/libmediaplayerservice/StagefrightPlayer.cpp @@ -187,7 +187,7 @@ status_t StagefrightPlayer::getParameter(int key, Parcel *reply) { } status_t StagefrightPlayer::getMetadata( - const media::Metadata::Filter& ids, Parcel *records) { + const media::Metadata::Filter& /* ids */, Parcel *records) { using media::Metadata; uint32_t flags = mPlayer->flags(); diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index f9d9020..4da74e1 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -16,6 +16,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "StagefrightRecorder" +#include <inttypes.h> #include <utils/Log.h> #include "StagefrightRecorder.h" @@ -1747,15 +1748,15 @@ status_t StagefrightRecorder::dump( result.append(buffer); snprintf(buffer, SIZE, " File format: %d\n", mOutputFormat); result.append(buffer); - snprintf(buffer, SIZE, " Max file size (bytes): %lld\n", mMaxFileSizeBytes); + snprintf(buffer, SIZE, " Max file size (bytes): %" PRId64 "\n", mMaxFileSizeBytes); result.append(buffer); - snprintf(buffer, SIZE, " Max file duration (us): %lld\n", mMaxFileDurationUs); + snprintf(buffer, SIZE, " Max file duration (us): %" PRId64 "\n", mMaxFileDurationUs); result.append(buffer); snprintf(buffer, SIZE, " File offset length (bits): %d\n", mUse64BitFileOffset? 64: 32); result.append(buffer); snprintf(buffer, SIZE, " Interleave duration (us): %d\n", mInterleaveDurationUs); result.append(buffer); - snprintf(buffer, SIZE, " Progress notification: %lld us\n", mTrackEveryTimeDurationUs); + snprintf(buffer, SIZE, " Progress notification: %" PRId64 " us\n", mTrackEveryTimeDurationUs); result.append(buffer); snprintf(buffer, SIZE, " Audio\n"); result.append(buffer); diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp index f1782cc..510dcc9 100644 --- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp +++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp @@ -140,7 +140,7 @@ status_t NuPlayer::HTTPLiveSource::selectTrack(size_t trackIndex, bool select) { // LiveSession::selectTrack returns BAD_VALUE when selecting the currently // selected track, or unselecting a non-selected track. In this case it's an // no-op so we return OK. - return (err == OK || err == BAD_VALUE) ? OK : err; + return (err == OK || err == BAD_VALUE) ? (status_t)OK : err; } status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs) { diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 3669a5b..25d55a3 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -1011,7 +1011,14 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) { &NuPlayer::performScanSources)); } - flushDecoder(audio, formatChange); + sp<AMessage> newFormat = mSource->getFormat(audio); + sp<Decoder> &decoder = audio ? mAudioDecoder : mVideoDecoder; + if (formatChange && !decoder->supportsSeamlessFormatChange(newFormat)) { + flushDecoder(audio, /* needShutdown = */ true); + } else { + flushDecoder(audio, /* needShutdown = */ false); + err = OK; + } } else { // This stream is unaffected by the discontinuity diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp index 22f699e..2423fd5 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp @@ -67,6 +67,7 @@ void NuPlayer::Decoder::configure(const sp<AMessage> &format) { // queue. bool needDedicatedLooper = !strncasecmp(mime.c_str(), "video/", 6); + mFormat = format; mCodec = new ACodec; if (needDedicatedLooper && mCodecLooper == NULL) { @@ -147,5 +148,65 @@ void NuPlayer::Decoder::initiateShutdown() { } } +bool NuPlayer::Decoder::supportsSeamlessAudioFormatChange(const sp<AMessage> &targetFormat) const { + if (targetFormat == NULL) { + return true; + } + + AString mime; + if (!targetFormat->findString("mime", &mime)) { + return false; + } + + if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) { + // field-by-field comparison + const char * keys[] = { "channel-count", "sample-rate", "is-adts" }; + for (unsigned int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) { + int32_t oldVal, newVal; + if (!mFormat->findInt32(keys[i], &oldVal) || !targetFormat->findInt32(keys[i], &newVal) + || oldVal != newVal) { + return false; + } + } + + sp<ABuffer> oldBuf, newBuf; + if (mFormat->findBuffer("csd-0", &oldBuf) && targetFormat->findBuffer("csd-0", &newBuf)) { + if (oldBuf->size() != newBuf->size()) { + return false; + } + return !memcmp(oldBuf->data(), newBuf->data(), oldBuf->size()); + } + } + return false; +} + +bool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetFormat) const { + if (mFormat == NULL) { + return false; + } + + if (targetFormat == NULL) { + return true; + } + + AString oldMime, newMime; + if (!mFormat->findString("mime", &oldMime) + || !targetFormat->findString("mime", &newMime) + || !(oldMime == newMime)) { + return false; + } + + bool audio = !strncasecmp(oldMime.c_str(), "audio/", strlen("audio/")); + bool seamless; + if (audio) { + seamless = supportsSeamlessAudioFormatChange(targetFormat); + } else { + seamless = mCodec != NULL && mCodec->isConfiguredForAdaptivePlayback(); + } + + ALOGV("%s seamless support for %s", seamless ? "yes" : "no", oldMime.c_str()); + return seamless; +} + } // namespace android diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h index a876148..78ea74a 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h @@ -36,6 +36,8 @@ struct NuPlayer::Decoder : public AHandler { void signalResume(); void initiateShutdown(); + bool supportsSeamlessFormatChange(const sp<AMessage> &to) const; + protected: virtual ~Decoder(); @@ -49,6 +51,7 @@ private: sp<AMessage> mNotify; sp<NativeWindowWrapper> mNativeWindow; + sp<AMessage> mFormat; sp<ACodec> mCodec; sp<ALooper> mCodecLooper; @@ -59,6 +62,8 @@ private: void onFillThisBuffer(const sp<AMessage> &msg); + bool supportsSeamlessAudioFormatChange(const sp<AMessage> &targetFormat) const; + DISALLOW_EVIL_CONSTRUCTORS(Decoder); }; diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp index 47834fd..b9651a1 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp @@ -16,6 +16,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "NuPlayerDriver" +#include <inttypes.h> #include <utils/Log.h> #include "NuPlayerDriver.h" @@ -364,7 +365,7 @@ status_t NuPlayerDriver::reset() { return OK; } -status_t NuPlayerDriver::setLooping(int loop) { +status_t NuPlayerDriver::setLooping(int /* loop */) { return INVALID_OPERATION; } @@ -420,16 +421,17 @@ void NuPlayerDriver::setAudioSink(const sp<AudioSink> &audioSink) { mPlayer->setAudioSink(audioSink); } -status_t NuPlayerDriver::setParameter(int key, const Parcel &request) { +status_t NuPlayerDriver::setParameter( + int /* key */, const Parcel & /* request */) { return INVALID_OPERATION; } -status_t NuPlayerDriver::getParameter(int key, Parcel *reply) { +status_t NuPlayerDriver::getParameter(int /* key */, Parcel * /* reply */) { return INVALID_OPERATION; } status_t NuPlayerDriver::getMetadata( - const media::Metadata::Filter& ids, Parcel *records) { + const media::Metadata::Filter& /* ids */, Parcel *records) { Mutex::Autolock autoLock(mLock); using media::Metadata; @@ -493,13 +495,14 @@ void NuPlayerDriver::notifyFrameStats( mNumFramesDropped = numFramesDropped; } -status_t NuPlayerDriver::dump(int fd, const Vector<String16> &args) const { +status_t NuPlayerDriver::dump( + int fd, const Vector<String16> & /* args */) const { Mutex::Autolock autoLock(mLock); FILE *out = fdopen(dup(fd), "w"); fprintf(out, " NuPlayer\n"); - fprintf(out, " numFramesTotal(%lld), numFramesDropped(%lld), " + fprintf(out, " numFramesTotal(%" PRId64 "), numFramesDropped(%" PRId64 "), " "percentageDropped(%.2f)\n", mNumFramesTotal, mNumFramesDropped, diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp index 92b9a92..bf5271e 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp @@ -422,7 +422,9 @@ void NuPlayer::Renderer::onDrainVideoQueue() { ALOGV("video late by %lld us (%.2f secs)", mVideoLateByUs, mVideoLateByUs / 1E6); } else { - ALOGV("rendering video at media time %.2f secs", mediaTimeUs / 1E6); + ALOGV("rendering video at media time %.2f secs", + (mFlags & FLAG_REAL_TIME ? realTimeUs : + (realTimeUs + mAnchorTimeMediaUs - mAnchorTimeRealUs)) / 1E6); if (mSoftRenderer != NULL) { mSoftRenderer->render(entry->mBuffer->data(), entry->mBuffer->size(), NULL); } diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h index e50533a..11279fc 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h @@ -68,19 +68,19 @@ struct NuPlayer::Source : public AHandler { virtual status_t dequeueAccessUnit( bool audio, sp<ABuffer> *accessUnit) = 0; - virtual status_t getDuration(int64_t *durationUs) { + virtual status_t getDuration(int64_t * /* durationUs */) { return INVALID_OPERATION; } - virtual status_t getTrackInfo(Parcel* reply) const { + virtual status_t getTrackInfo(Parcel* /* reply */) const { return INVALID_OPERATION; } - virtual status_t selectTrack(size_t trackIndex, bool select) { + virtual status_t selectTrack(size_t /* trackIndex */, bool /* select */) { return INVALID_OPERATION; } - virtual status_t seekTo(int64_t seekTimeUs) { + virtual status_t seekTo(int64_t /* seekTimeUs */) { return INVALID_OPERATION; } @@ -93,7 +93,7 @@ protected: virtual void onMessageReceived(const sp<AMessage> &msg); - virtual sp<MetaData> getFormatMeta(bool audio) { return NULL; } + virtual sp<MetaData> getFormatMeta(bool /* audio */) { return NULL; } sp<AMessage> dupNotify() const { return mNotify->dup(); } diff --git a/media/libmediaplayerservice/nuplayer/mp4/MP4Source.cpp b/media/libmediaplayerservice/nuplayer/mp4/MP4Source.cpp index d31d947..2aae4dd 100644 --- a/media/libmediaplayerservice/nuplayer/mp4/MP4Source.cpp +++ b/media/libmediaplayerservice/nuplayer/mp4/MP4Source.cpp @@ -86,7 +86,7 @@ struct StreamSource : public FragmentedMP4Parser::Source { total += n; } - ALOGV("read %ld bytes at offset %lld", n, mPosition); + ALOGV("read %ld bytes at offset %lld", total, mPosition); mPosition += total; diff --git a/media/libnbaio/MonoPipe.cpp b/media/libnbaio/MonoPipe.cpp index de0ad28..3c61b60 100644 --- a/media/libnbaio/MonoPipe.cpp +++ b/media/libnbaio/MonoPipe.cpp @@ -183,7 +183,7 @@ ssize_t MonoPipe::write(const void *buffer, size_t count) } } if (ns > 0) { - const struct timespec req = {0, ns}; + const struct timespec req = {0, static_cast<long>(ns)}; nanosleep(&req, NULL); } // record the time that this write() completed diff --git a/media/libnbaio/NBLog.cpp b/media/libnbaio/NBLog.cpp index 045bf64..4f5762f 100644 --- a/media/libnbaio/NBLog.cpp +++ b/media/libnbaio/NBLog.cpp @@ -26,6 +26,7 @@ #include <cutils/atomic.h> #include <media/nbaio/NBLog.h> #include <utils/Log.h> +#include <utils/String8.h> namespace android { @@ -337,25 +338,25 @@ void NBLog::Reader::dump(int fd, size_t indent) } i -= length + 3; } + mFd = fd; + mIndent = indent; + String8 timestamp, body; if (i > 0) { lost += i; - if (fd >= 0) { - fdprintf(fd, "%*swarning: lost %u bytes worth of events\n", indent, "", lost); - } else { - ALOGI("%*swarning: lost %u bytes worth of events\n", indent, "", lost); - } + body.appendFormat("warning: lost %zu bytes worth of events", lost); + // TODO timestamp empty here, only other choice to wait for the first timestamp event in the + // log to push it out. Consider keeping the timestamp/body between calls to readAt(). + dumpLine(timestamp, body); } size_t width = 1; while (maxSec >= 10) { ++width; maxSec /= 10; } - char prefix[32]; if (maxSec >= 0) { - snprintf(prefix, sizeof(prefix), "[%*s] ", width + 4, ""); - } else { - prefix[0] = '\0'; + timestamp.appendFormat("[%*s]", (int) width + 4, ""); } + bool deferredTimestamp = false; while (i < avail) { event = (Event) copy[i]; length = copy[i + 1]; @@ -363,11 +364,8 @@ void NBLog::Reader::dump(int fd, size_t indent) size_t advance = length + 3; switch (event) { case EVENT_STRING: - if (fd >= 0) { - fdprintf(fd, "%*s%s%.*s\n", indent, "", prefix, length, (const char *) data); - } else { - ALOGI("%*s%s%.*s", indent, "", prefix, length, (const char *) data); - } break; + body.appendFormat("%.*s", (int) length, (const char *) data); + break; case EVENT_TIMESTAMP: { // already checked that length == sizeof(struct timespec); memcpy(&ts, data, sizeof(struct timespec)); @@ -400,45 +398,53 @@ void NBLog::Reader::dump(int fd, size_t indent) prevNsec = tsNext.tv_nsec; } size_t n = (j - i) / (sizeof(struct timespec) + 3); + if (deferredTimestamp) { + dumpLine(timestamp, body); + deferredTimestamp = false; + } + timestamp.clear(); if (n >= kSquashTimestamp) { - if (fd >= 0) { - fdprintf(fd, "%*s[%d.%03d to .%.03d by .%.03d to .%.03d]\n", indent, "", - (int) ts.tv_sec, (int) (ts.tv_nsec / 1000000), - (int) ((ts.tv_nsec + deltaTotal) / 1000000), - (int) (deltaMin / 1000000), (int) (deltaMax / 1000000)); - } else { - ALOGI("%*s[%d.%03d to .%.03d by .%.03d to .%.03d]\n", indent, "", - (int) ts.tv_sec, (int) (ts.tv_nsec / 1000000), - (int) ((ts.tv_nsec + deltaTotal) / 1000000), - (int) (deltaMin / 1000000), (int) (deltaMax / 1000000)); - } + timestamp.appendFormat("[%d.%03d to .%.03d by .%.03d to .%.03d]", + (int) ts.tv_sec, (int) (ts.tv_nsec / 1000000), + (int) ((ts.tv_nsec + deltaTotal) / 1000000), + (int) (deltaMin / 1000000), (int) (deltaMax / 1000000)); i = j; advance = 0; break; } - if (fd >= 0) { - fdprintf(fd, "%*s[%d.%03d]\n", indent, "", (int) ts.tv_sec, - (int) (ts.tv_nsec / 1000000)); - } else { - ALOGI("%*s[%d.%03d]", indent, "", (int) ts.tv_sec, - (int) (ts.tv_nsec / 1000000)); - } + timestamp.appendFormat("[%d.%03d]", (int) ts.tv_sec, + (int) (ts.tv_nsec / 1000000)); + deferredTimestamp = true; } break; case EVENT_RESERVED: default: - if (fd >= 0) { - fdprintf(fd, "%*s%swarning: unknown event %d\n", indent, "", prefix, event); - } else { - ALOGI("%*s%swarning: unknown event %d", indent, "", prefix, event); - } + body.appendFormat("warning: unknown event %d", event); break; } i += advance; + + if (!body.isEmpty()) { + dumpLine(timestamp, body); + deferredTimestamp = false; + } + } + if (deferredTimestamp) { + dumpLine(timestamp, body); } // FIXME it would be more efficient to put a char mCopy[256] as a member variable of the dumper delete[] copy; } +void NBLog::Reader::dumpLine(const String8& timestamp, String8& body) +{ + if (mFd >= 0) { + dprintf(mFd, "%.*s%s %s\n", mIndent, "", timestamp.string(), body.string()); + } else { + ALOGI("%.*s%s %s", mIndent, "", timestamp.string(), body.string()); + } + body.clear(); +} + bool NBLog::Reader::isIMemory(const sp<IMemory>& iMemory) const { return iMemory.get() == mIMemory.get(); diff --git a/media/libstagefright/AACExtractor.cpp b/media/libstagefright/AACExtractor.cpp index 4d1072f..196f6ee 100644 --- a/media/libstagefright/AACExtractor.cpp +++ b/media/libstagefright/AACExtractor.cpp @@ -219,7 +219,7 @@ sp<MediaSource> AACExtractor::getTrack(size_t index) { return new AACSource(mDataSource, mMeta, mOffsetVector, mFrameDurationUs); } -sp<MetaData> AACExtractor::getTrackMetaData(size_t index, uint32_t flags) { +sp<MetaData> AACExtractor::getTrackMetaData(size_t index, uint32_t /* flags */) { if (mInitCheck != OK || index != 0) { return NULL; } @@ -252,7 +252,7 @@ AACSource::~AACSource() { } } -status_t AACSource::start(MetaData *params) { +status_t AACSource::start(MetaData * /* params */) { CHECK(!mStarted); if (mOffsetVector.empty()) { diff --git a/media/libstagefright/AACWriter.cpp b/media/libstagefright/AACWriter.cpp index a6f7cfb..deee8e7 100644 --- a/media/libstagefright/AACWriter.cpp +++ b/media/libstagefright/AACWriter.cpp @@ -111,7 +111,7 @@ status_t AACWriter::addSource(const sp<MediaSource> &source) { return OK; } -status_t AACWriter::start(MetaData *params) { +status_t AACWriter::start(MetaData * /* params */) { if (mInitCheck != OK) { return mInitCheck; } @@ -171,7 +171,7 @@ status_t AACWriter::reset() { void *dummy; pthread_join(mThread, &dummy); - status_t err = (status_t) dummy; + status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); { status_t status = mSource->stop(); if (err == OK && @@ -200,7 +200,7 @@ bool AACWriter::exceedsFileDurationLimit() { // static void *AACWriter::ThreadWrapper(void *me) { - return (void *) static_cast<AACWriter *>(me)->threadFunc(); + return (void *)(uintptr_t)static_cast<AACWriter *>(me)->threadFunc(); } /* diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index 528fdb9..1a87e9c 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -17,6 +17,9 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "ACodec" +#include <inttypes.h> +#include <utils/Trace.h> + #include <media/stagefright/ACodec.h> #include <binder/MemoryDealer.h> @@ -62,7 +65,7 @@ struct CodecObserver : public BnOMXObserver { sp<AMessage> msg = mNotify->dup(); msg->setInt32("type", omx_msg.type); - msg->setPointer("node", omx_msg.node); + msg->setInt32("node", omx_msg.node); switch (omx_msg.type) { case omx_message::EVENT: @@ -75,13 +78,13 @@ struct CodecObserver : public BnOMXObserver { case omx_message::EMPTY_BUFFER_DONE: { - msg->setPointer("buffer", omx_msg.u.buffer_data.buffer); + msg->setInt32("buffer", omx_msg.u.buffer_data.buffer); break; } case omx_message::FILL_BUFFER_DONE: { - msg->setPointer( + msg->setInt32( "buffer", omx_msg.u.extended_buffer_data.buffer); msg->setInt32( "range_offset", @@ -358,11 +361,12 @@ private: ACodec::ACodec() : mQuirks(0), - mNode(NULL), + mNode(0), mSentFormat(false), mIsEncoder(false), mUseMetadataOnEncoderOutput(false), mShutdownInProgress(false), + mIsConfiguredForAdaptivePlayback(false), mEncoderDelay(0), mEncoderPadding(0), mChannelMaskPresent(false), @@ -370,7 +374,8 @@ ACodec::ACodec() mDequeueCounter(0), mStoreMetaDataInOutputBuffers(false), mMetaDataBuffersToSubmit(0), - mRepeatFrameDelayUs(-1ll) { + mRepeatFrameDelayUs(-1ll), + mMaxPtsGapUs(-1ll) { mUninitializedState = new UninitializedState(this); mLoadedState = new LoadedState(this); mLoadedToIdleState = new LoadedToIdleState(this); @@ -452,6 +457,18 @@ void ACodec::signalRequestIDRFrame() { (new AMessage(kWhatRequestIDRFrame, id()))->post(); } +// *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** +// Some codecs may return input buffers before having them processed. +// This causes a halt if we already signaled an EOS on the input +// port. For now keep submitting an output buffer if there was an +// EOS on the input port, but not yet on the output port. +void ACodec::signalSubmitOutputMetaDataBufferIfEOS_workaround() { + if (mPortEOS[kPortIndexInput] && !mPortEOS[kPortIndexOutput] && + mMetaDataBuffersToSubmit > 0) { + (new AMessage(kWhatSubmitOutputMetaDataBufferIfEOS, id()))->post(); + } +} + status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); @@ -474,7 +491,7 @@ status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); if (err == OK) { - ALOGV("[%s] Allocating %lu buffers of size %lu on %s port", + ALOGV("[%s] Allocating %u buffers of size %u on %s port", mComponentName.c_str(), def.nBufferCountActual, def.nBufferSize, portIndex == kPortIndexInput ? "input" : "output"); @@ -624,18 +641,34 @@ status_t ACodec::configureOutputBuffersFromNativeWindow( return err; } - // XXX: Is this the right logic to use? It's not clear to me what the OMX - // buffer counts refer to - how do they account for the renderer holding on - // to buffers? - if (def.nBufferCountActual < def.nBufferCountMin + *minUndequeuedBuffers) { - OMX_U32 newBufferCount = def.nBufferCountMin + *minUndequeuedBuffers; + // FIXME: assume that surface is controlled by app (native window + // returns the number for the case when surface is not controlled by app) + // FIXME2: This means that minUndeqeueudBufs can be 1 larger than reported + // For now, try to allocate 1 more buffer, but don't fail if unsuccessful + + // Use conservative allocation while also trying to reduce starvation + // + // 1. allocate at least nBufferCountMin + minUndequeuedBuffers - that is the + // minimum needed for the consumer to be able to work + // 2. try to allocate two (2) additional buffers to reduce starvation from + // the consumer + // plus an extra buffer to account for incorrect minUndequeuedBufs + for (OMX_U32 extraBuffers = 2 + 1; /* condition inside loop */; extraBuffers--) { + OMX_U32 newBufferCount = + def.nBufferCountMin + *minUndequeuedBuffers + extraBuffers; def.nBufferCountActual = newBufferCount; err = mOMX->setParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - if (err != OK) { - ALOGE("[%s] setting nBufferCountActual to %lu failed: %d", - mComponentName.c_str(), newBufferCount, err); + if (err == OK) { + *minUndequeuedBuffers += extraBuffers; + break; + } + + ALOGW("[%s] setting nBufferCountActual to %u failed: %d", + mComponentName.c_str(), newBufferCount, err); + /* exit condition */ + if (extraBuffers == 0) { return err; } } @@ -660,8 +693,9 @@ status_t ACodec::allocateOutputBuffersFromNativeWindow() { &bufferCount, &bufferSize, &minUndequeuedBuffers); if (err != 0) return err; + mNumUndequeuedBuffers = minUndequeuedBuffers; - ALOGV("[%s] Allocating %lu buffers from a native window of size %lu on " + ALOGV("[%s] Allocating %u buffers from a native window of size %u on " "output port", mComponentName.c_str(), bufferCount, bufferSize); @@ -685,14 +719,14 @@ status_t ACodec::allocateOutputBuffersFromNativeWindow() { err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer, &bufferId); if (err != 0) { - ALOGE("registering GraphicBuffer %lu with OMX IL component failed: " + ALOGE("registering GraphicBuffer %u with OMX IL component failed: " "%d", i, err); break; } mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId; - ALOGV("[%s] Registered graphic buffer with ID %p (pointer = %p)", + ALOGV("[%s] Registered graphic buffer with ID %u (pointer = %p)", mComponentName.c_str(), bufferId, graphicBuffer.get()); } @@ -725,8 +759,9 @@ status_t ACodec::allocateOutputMetaDataBuffers() { &bufferCount, &bufferSize, &minUndequeuedBuffers); if (err != 0) return err; + mNumUndequeuedBuffers = minUndequeuedBuffers; - ALOGV("[%s] Allocating %lu meta buffers on output port", + ALOGV("[%s] Allocating %u meta buffers on output port", mComponentName.c_str(), bufferCount); size_t totalSize = bufferCount * 8; @@ -750,7 +785,7 @@ status_t ACodec::allocateOutputMetaDataBuffers() { mBuffers[kPortIndexOutput].push(info); - ALOGV("[%s] allocated meta buffer with ID %p (pointer = %p)", + ALOGV("[%s] allocated meta buffer with ID %u (pointer = %p)", mComponentName.c_str(), info.mBufferID, mem->pointer()); } @@ -767,7 +802,7 @@ status_t ACodec::submitOutputMetaDataBuffer() { if (info == NULL) return ERROR_IO; - ALOGV("[%s] submitting output meta buffer ID %p for graphic buffer %p", + ALOGV("[%s] submitting output meta buffer ID %u for graphic buffer %p", mComponentName.c_str(), info->mBufferID, info->mGraphicBuffer.get()); --mMetaDataBuffersToSubmit; @@ -781,7 +816,7 @@ status_t ACodec::submitOutputMetaDataBuffer() { status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) { CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); - ALOGV("[%s] Calling cancelBuffer on buffer %p", + ALOGV("[%s] Calling cancelBuffer on buffer %u", mComponentName.c_str(), info->mBufferID); int err = mNativeWindow->cancelBuffer( @@ -1096,6 +1131,10 @@ status_t ACodec::configureCodec( &mRepeatFrameDelayUs)) { mRepeatFrameDelayUs = -1ll; } + + if (!msg->findInt64("max-pts-gap-to-encoder", &mMaxPtsGapUs)) { + mMaxPtsGapUs = -1l; + } } // Always try to enable dynamic output buffers on native surface @@ -1103,6 +1142,7 @@ status_t ACodec::configureCodec( int32_t haveNativeWindow = msg->findObject("native-window", &obj) && obj != NULL; mStoreMetaDataInOutputBuffers = false; + mIsConfiguredForAdaptivePlayback = false; if (!encoder && video && haveNativeWindow) { err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, OMX_TRUE); if (err != OK) { @@ -1139,7 +1179,7 @@ status_t ACodec::configureCodec( if (canDoAdaptivePlayback && msg->findInt32("max-width", &maxWidth) && msg->findInt32("max-height", &maxHeight)) { - ALOGV("[%s] prepareForAdaptivePlayback(%ldx%ld)", + ALOGV("[%s] prepareForAdaptivePlayback(%dx%d)", mComponentName.c_str(), maxWidth, maxHeight); err = mOMX->prepareForAdaptivePlayback( @@ -1147,12 +1187,14 @@ status_t ACodec::configureCodec( ALOGW_IF(err != OK, "[%s] prepareForAdaptivePlayback failed w/ err %d", mComponentName.c_str(), err); + mIsConfiguredForAdaptivePlayback = (err == OK); } // allow failure err = OK; } else { ALOGV("[%s] storeMetaDataInBuffers succeeded", mComponentName.c_str()); mStoreMetaDataInOutputBuffers = true; + mIsConfiguredForAdaptivePlayback = true; } int32_t push; @@ -2408,19 +2450,7 @@ void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() { return; } - int minUndequeuedBufs = 0; - status_t err = mNativeWindow->query( - mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, - &minUndequeuedBufs); - - if (err != OK) { - ALOGE("[%s] NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)", - mComponentName.c_str(), strerror(-err), -err); - - minUndequeuedBufs = 0; - } - - while (countBuffersOwnedByNativeWindow() > (size_t)minUndequeuedBufs + while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers && dequeueBufferFromNativeWindow() != NULL) { // these buffers will be submitted as regular buffers; account for this if (mStoreMetaDataInOutputBuffers && mMetaDataBuffersToSubmit > 0) { @@ -2436,7 +2466,7 @@ bool ACodec::allYourBuffersAreBelongToUs( if (info->mStatus != BufferInfo::OWNED_BY_US && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { - ALOGV("[%s] Buffer %p on port %ld still has status %d", + ALOGV("[%s] Buffer %u on port %u still has status %d", mComponentName.c_str(), info->mBufferID, portIndex, info->mStatus); return false; @@ -2918,7 +2948,7 @@ bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) { CHECK(msg->findInt32("type", &type)); IOMX::node_id nodeID; - CHECK(msg->findPointer("node", &nodeID)); + CHECK(msg->findInt32("node", (int32_t*)&nodeID)); CHECK_EQ(nodeID, mCodec->mNode); switch (type) { @@ -2949,7 +2979,7 @@ bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) { case omx_message::EMPTY_BUFFER_DONE: { IOMX::buffer_id bufferID; - CHECK(msg->findPointer("buffer", &bufferID)); + CHECK(msg->findInt32("buffer", (int32_t*)&bufferID)); return onOMXEmptyBufferDone(bufferID); } @@ -2957,7 +2987,7 @@ bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) { case omx_message::FILL_BUFFER_DONE: { IOMX::buffer_id bufferID; - CHECK(msg->findPointer("buffer", &bufferID)); + CHECK(msg->findInt32("buffer", (int32_t*)&bufferID)); int32_t rangeOffset, rangeLength, flags; int64_t timeUs; @@ -3060,13 +3090,13 @@ void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) { sp<AMessage> notify = mCodec->mNotify->dup(); notify->setInt32("what", ACodec::kWhatFillThisBuffer); - notify->setPointer("buffer-id", info->mBufferID); + notify->setInt32("buffer-id", info->mBufferID); info->mData->meta()->clear(); notify->setBuffer("buffer", info->mData); sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id()); - reply->setPointer("buffer-id", info->mBufferID); + reply->setInt32("buffer-id", info->mBufferID); notify->setMessage("reply", reply); @@ -3077,8 +3107,7 @@ void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) { void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { IOMX::buffer_id bufferID; - CHECK(msg->findPointer("buffer-id", &bufferID)); - + CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); sp<ABuffer> buffer; int32_t err = OK; bool eos = false; @@ -3235,11 +3264,11 @@ void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { mCodec->mInputEOSResult = err; } break; - - default: - CHECK_EQ((int)mode, (int)FREE_BUFFERS); - break; } + + default: + CHECK_EQ((int)mode, (int)FREE_BUFFERS); + break; } } @@ -3316,7 +3345,7 @@ bool ACodec::BaseState::onOMXFillBufferDone( case RESUBMIT_BUFFERS: { if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) { - ALOGV("[%s] calling fillBuffer %p", + ALOGV("[%s] calling fillBuffer %u", mCodec->mComponentName.c_str(), info->mBufferID); CHECK_EQ(mCodec->mOMX->fillBuffer( @@ -3358,11 +3387,11 @@ bool ACodec::BaseState::onOMXFillBufferDone( sp<AMessage> notify = mCodec->mNotify->dup(); notify->setInt32("what", ACodec::kWhatDrainThisBuffer); - notify->setPointer("buffer-id", info->mBufferID); + notify->setInt32("buffer-id", info->mBufferID); notify->setBuffer("buffer", info->mData); notify->setInt32("flags", flags); - reply->setPointer("buffer-id", info->mBufferID); + reply->setInt32("buffer-id", info->mBufferID); notify->setMessage("reply", reply); @@ -3398,8 +3427,7 @@ bool ACodec::BaseState::onOMXFillBufferDone( void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { IOMX::buffer_id bufferID; - CHECK(msg->findPointer("buffer-id", &bufferID)); - + CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); ssize_t index; BufferInfo *info = mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); @@ -3415,7 +3443,8 @@ void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { int32_t render; if (mCodec->mNativeWindow != NULL && msg->findInt32("render", &render) && render != 0 - && (info->mData == NULL || info->mData->size() != 0)) { + && info->mData != NULL && info->mData->size() != 0) { + ATRACE_NAME("render"); // The client wants this buffer to be rendered. status_t err; @@ -3428,6 +3457,10 @@ void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { info->mStatus = BufferInfo::OWNED_BY_US; } } else { + if (mCodec->mNativeWindow != NULL && + (info->mData == NULL || info->mData->size() != 0)) { + ATRACE_NAME("frame-drop"); + } info->mStatus = BufferInfo::OWNED_BY_US; } @@ -3458,7 +3491,7 @@ void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { } if (info != NULL) { - ALOGV("[%s] calling fillBuffer %p", + ALOGV("[%s] calling fillBuffer %u", mCodec->mComponentName.c_str(), info->mBufferID); CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), @@ -3621,7 +3654,7 @@ bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) { componentName = matchingCodecs.itemAt(matchIndex).mName.string(); quirks = matchingCodecs.itemAt(matchIndex).mQuirks; - pid_t tid = androidGetTid(); + pid_t tid = gettid(); int prevPriority = androidGetThreadPriority(tid); androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND); status_t err = omx->allocateNode(componentName.c_str(), observer, &node); @@ -3690,6 +3723,7 @@ void ACodec::LoadedState::stateEntered() { mCodec->mDequeueCounter = 0; mCodec->mMetaDataBuffersToSubmit = 0; mCodec->mRepeatFrameDelayUs = -1ll; + mCodec->mIsConfiguredForAdaptivePlayback = false; if (mCodec->mShutdownInProgress) { bool keepComponentAllocated = mCodec->mKeepComponentAllocated; @@ -3838,6 +3872,21 @@ void ACodec::LoadedState::onCreateInputSurface( } } + if (err == OK && mCodec->mMaxPtsGapUs > 0l) { + err = mCodec->mOMX->setInternalOption( + mCodec->mNode, + kPortIndexInput, + IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP, + &mCodec->mMaxPtsGapUs, + sizeof(mCodec->mMaxPtsGapUs)); + + if (err != OK) { + ALOGE("[%s] Unable to configure max timestamp gap (err %d)", + mCodec->mComponentName.c_str(), + err); + } + } + if (err == OK) { notify->setObject("input-surface", new BufferProducerWrapper(bufferProducer)); @@ -4036,6 +4085,9 @@ void ACodec::ExecutingState::submitOutputMetaBuffers() { break; } } + + // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** + mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround(); } void ACodec::ExecutingState::submitRegularOutputBuffers() { @@ -4184,6 +4236,19 @@ bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) { break; } + // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** + case kWhatSubmitOutputMetaDataBufferIfEOS: + { + if (mCodec->mPortEOS[kPortIndexInput] && + !mCodec->mPortEOS[kPortIndexOutput]) { + status_t err = mCodec->submitOutputMetaDataBuffer(); + if (err == OK) { + mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround(); + } + } + return true; + } + default: handled = BaseState::onMessageReceived(msg); break; @@ -4636,7 +4701,7 @@ bool ACodec::FlushingState::onOMXEvent( { sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id()); msg->setInt32("type", omx_message::EVENT); - msg->setPointer("node", mCodec->mNode); + msg->setInt32("node", mCodec->mNode); msg->setInt32("event", event); msg->setInt32("data1", data1); msg->setInt32("data2", data2); diff --git a/media/libstagefright/AMRExtractor.cpp b/media/libstagefright/AMRExtractor.cpp index 03dcbf9..a6fb3d8 100644 --- a/media/libstagefright/AMRExtractor.cpp +++ b/media/libstagefright/AMRExtractor.cpp @@ -189,7 +189,7 @@ sp<MediaSource> AMRExtractor::getTrack(size_t index) { mOffsetTable, mOffsetTableLength); } -sp<MetaData> AMRExtractor::getTrackMetaData(size_t index, uint32_t flags) { +sp<MetaData> AMRExtractor::getTrackMetaData(size_t index, uint32_t /* flags */) { if (mInitCheck != OK || index != 0) { return NULL; } @@ -221,7 +221,7 @@ AMRSource::~AMRSource() { } } -status_t AMRSource::start(MetaData *params) { +status_t AMRSource::start(MetaData * /* params */) { CHECK(!mStarted); mOffset = mIsWide ? 9 : 6; @@ -258,14 +258,14 @@ status_t AMRSource::read( int64_t seekFrame = seekTimeUs / 20000ll; // 20ms per frame. mCurrentTimeUs = seekFrame * 20000ll; - int index = seekFrame / 50; + size_t index = seekFrame < 0 ? 0 : seekFrame / 50; if (index >= mOffsetTableLength) { index = mOffsetTableLength - 1; } mOffset = mOffsetTable[index] + (mIsWide ? 9 : 6); - for (int i = 0; i< seekFrame - index * 50; i++) { + for (size_t i = 0; i< seekFrame - index * 50; i++) { status_t err; if ((err = getFrameSizeByOffset(mDataSource, mOffset, mIsWide, &size)) != OK) { diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp index 8d5eec8..653ca36 100644 --- a/media/libstagefright/AMRWriter.cpp +++ b/media/libstagefright/AMRWriter.cpp @@ -105,7 +105,7 @@ status_t AMRWriter::addSource(const sp<MediaSource> &source) { return OK; } -status_t AMRWriter::start(MetaData *params) { +status_t AMRWriter::start(MetaData * /* params */) { if (mInitCheck != OK) { return mInitCheck; } @@ -162,7 +162,7 @@ status_t AMRWriter::reset() { void *dummy; pthread_join(mThread, &dummy); - status_t err = (status_t) dummy; + status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); { status_t status = mSource->stop(); if (err == OK && @@ -191,7 +191,7 @@ bool AMRWriter::exceedsFileDurationLimit() { // static void *AMRWriter::ThreadWrapper(void *me) { - return (void *) static_cast<AMRWriter *>(me)->threadFunc(); + return (void *)(uintptr_t) static_cast<AMRWriter *>(me)->threadFunc(); } status_t AMRWriter::threadFunc() { diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk index 6a2a696..3619821 100644 --- a/media/libstagefright/Android.mk +++ b/media/libstagefright/Android.mk @@ -14,6 +14,7 @@ LOCAL_SRC_FILES:= \ AwesomePlayer.cpp \ CameraSource.cpp \ CameraSourceTimeLapse.cpp \ + ClockEstimator.cpp \ DataSource.cpp \ DRMExtractor.cpp \ ESDS.cpp \ diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp index a8a8786..8623100 100644 --- a/media/libstagefright/AudioPlayer.cpp +++ b/media/libstagefright/AudioPlayer.cpp @@ -410,7 +410,7 @@ status_t AudioPlayer::setPlaybackRatePermille(int32_t ratePermille) { // static size_t AudioPlayer::AudioSinkCallback( - MediaPlayerBase::AudioSink *audioSink, + MediaPlayerBase::AudioSink * /* audioSink */, void *buffer, size_t size, void *cookie, MediaPlayerBase::AudioSink::cb_event_t event) { AudioPlayer *me = (AudioPlayer *)cookie; @@ -721,16 +721,27 @@ int64_t AudioPlayer::getRealTimeUsLocked() const { return result + diffUs; } -int64_t AudioPlayer::getOutputPlayPositionUs_l() const +int64_t AudioPlayer::getOutputPlayPositionUs_l() { uint32_t playedSamples = 0; + uint32_t sampleRate; if (mAudioSink != NULL) { mAudioSink->getPosition(&playedSamples); + sampleRate = mAudioSink->getSampleRate(); } else { mAudioTrack->getPosition(&playedSamples); + sampleRate = mAudioTrack->getSampleRate(); + } + if (sampleRate != 0) { + mSampleRate = sampleRate; } - const int64_t playedUs = (static_cast<int64_t>(playedSamples) * 1000000 ) / mSampleRate; + int64_t playedUs; + if (mSampleRate != 0) { + playedUs = (static_cast<int64_t>(playedSamples) * 1000000 ) / mSampleRate; + } else { + playedUs = 0; + } // HAL position is relative to the first buffer we sent at mStartPosUs const int64_t renderedDuration = mStartPosUs + playedUs; diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp index d7223d9..e68a710 100644 --- a/media/libstagefright/AudioSource.cpp +++ b/media/libstagefright/AudioSource.cpp @@ -68,7 +68,7 @@ AudioSource::AudioSource( int frameCount = kMaxBufferSize / sizeof(int16_t) / channelCount; // make sure that the AudioRecord total buffer size is large enough - int bufCount = 2; + size_t bufCount = 2; while ((bufCount * frameCount) < minFrameCount) { bufCount++; } @@ -208,7 +208,7 @@ void AudioSource::rampVolume( } status_t AudioSource::read( - MediaBuffer **out, const ReadOptions *options) { + MediaBuffer **out, const ReadOptions * /* options */) { Mutex::Autolock autoLock(mLock); *out = NULL; @@ -308,7 +308,7 @@ status_t AudioSource::dataCallback(const AudioRecord::Buffer& audioBuffer) { if (numLostBytes > 0) { // Loss of audio frames should happen rarely; thus the LOGW should // not cause a logging spam - ALOGW("Lost audio record data: %d bytes", numLostBytes); + ALOGW("Lost audio record data: %zu bytes", numLostBytes); } while (numLostBytes > 0) { diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index 130207d..ea6c15b 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -19,6 +19,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "AwesomePlayer" #define ATRACE_TAG ATRACE_TAG_VIDEO +#include <inttypes.h> #include <utils/Log.h> #include <utils/Trace.h> @@ -39,6 +40,7 @@ #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/timedtext/TimedTextDriver.h> #include <media/stagefright/AudioPlayer.h> +#include <media/stagefright/ClockEstimator.h> #include <media/stagefright/DataSource.h> #include <media/stagefright/FileSource.h> #include <media/stagefright/MediaBuffer.h> @@ -82,7 +84,7 @@ struct AwesomeEvent : public TimedEventQueue::Event { protected: virtual ~AwesomeEvent() {} - virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) { + virtual void fire(TimedEventQueue * /* queue */, int64_t /* now_us */) { (mPlayer->*mMethod)(); } @@ -227,6 +229,8 @@ AwesomePlayer::AwesomePlayer() &AwesomePlayer::onAudioTearDownEvent); mAudioTearDownEventPending = false; + mClockEstimator = new WindowedLinearFitEstimator(); + reset(); } @@ -725,7 +729,7 @@ void AwesomePlayer::onBufferingUpdate() { if ((mFlags & PLAYING) && !eos && (cachedDataRemaining < kLowWaterMarkBytes)) { - ALOGI("cache is running low (< %d) , pausing.", + ALOGI("cache is running low (< %zu) , pausing.", kLowWaterMarkBytes); modifyFlags(CACHE_UNDERRUN, SET); pause_l(); @@ -734,12 +738,12 @@ void AwesomePlayer::onBufferingUpdate() { notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START); } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) { if (mFlags & CACHE_UNDERRUN) { - ALOGI("cache has filled up (> %d), resuming.", + ALOGI("cache has filled up (> %zu), resuming.", kHighWaterMarkBytes); modifyFlags(CACHE_UNDERRUN, CLEAR); play_l(); } else if (mFlags & PREPARING) { - ALOGV("cache has filled up (> %d), prepare is done", + ALOGV("cache has filled up (> %zu), prepare is done", kHighWaterMarkBytes); finishAsyncPrepare_l(); } @@ -1858,21 +1862,28 @@ void AwesomePlayer::onVideoEvent() { TimeSource *ts = ((mFlags & AUDIO_AT_EOS) || !(mFlags & AUDIOPLAYER_STARTED)) ? &mSystemTimeSource : mTimeSource; + int64_t systemTimeUs = mSystemTimeSource.getRealTimeUs(); + int64_t looperTimeUs = ALooper::GetNowUs(); if (mFlags & FIRST_FRAME) { modifyFlags(FIRST_FRAME, CLEAR); mSinceLastDropped = 0; - mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs; + mClockEstimator->reset(); + mTimeSourceDeltaUs = estimateRealTimeUs(ts, systemTimeUs) - timeUs; } int64_t realTimeUs, mediaTimeUs; if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) { + ALOGV("updating TSdelta (%" PRId64 " => %" PRId64 " change %" PRId64 ")", + mTimeSourceDeltaUs, realTimeUs - mediaTimeUs, + mTimeSourceDeltaUs - (realTimeUs - mediaTimeUs)); + ATRACE_INT("TS delta change (ms)", (mTimeSourceDeltaUs - (realTimeUs - mediaTimeUs)) / 1E3); mTimeSourceDeltaUs = realTimeUs - mediaTimeUs; } if (wasSeeking == SEEK_VIDEO_ONLY) { - int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs; + int64_t nowUs = estimateRealTimeUs(ts, systemTimeUs) - mTimeSourceDeltaUs; int64_t latenessUs = nowUs - timeUs; @@ -1883,12 +1894,13 @@ void AwesomePlayer::onVideoEvent() { } } + int64_t latenessUs = 0; if (wasSeeking == NO_SEEK) { // Let's display the first frame after seeking right away. - int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs; + int64_t nowUs = estimateRealTimeUs(ts, systemTimeUs) - mTimeSourceDeltaUs; - int64_t latenessUs = nowUs - timeUs; + latenessUs = nowUs - timeUs; ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3); @@ -1942,9 +1954,9 @@ void AwesomePlayer::onVideoEvent() { } } - if (latenessUs < -10000) { - // We're more than 10ms early. - postVideoEvent_l(10000); + if (latenessUs < -30000) { + // We're more than 30ms early, schedule at most 20 ms before time due + postVideoEvent_l(latenessUs < -60000 ? 30000 : -latenessUs - 20000); return; } } @@ -1958,6 +1970,8 @@ void AwesomePlayer::onVideoEvent() { if (mVideoRenderer != NULL) { mSinceLastDropped++; + mVideoBuffer->meta_data()->setInt64(kKeyTime, looperTimeUs - latenessUs); + mVideoRenderer->render(mVideoBuffer); if (!mVideoRenderingStarted) { mVideoRenderingStarted = true; @@ -2007,14 +2021,26 @@ void AwesomePlayer::onVideoEvent() { int64_t nextTimeUs; CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &nextTimeUs)); - int64_t delayUs = nextTimeUs - ts->getRealTimeUs() + mTimeSourceDeltaUs; - postVideoEvent_l(delayUs > 10000 ? 10000 : delayUs < 0 ? 0 : delayUs); + systemTimeUs = mSystemTimeSource.getRealTimeUs(); + int64_t delayUs = nextTimeUs - estimateRealTimeUs(ts, systemTimeUs) + mTimeSourceDeltaUs; + ATRACE_INT("Frame delta (ms)", (nextTimeUs - timeUs) / 1E3); + ALOGV("next frame in %" PRId64, delayUs); + // try to schedule 30ms before time due + postVideoEvent_l(delayUs > 60000 ? 30000 : (delayUs < 30000 ? 0 : delayUs - 30000)); return; } postVideoEvent_l(); } +int64_t AwesomePlayer::estimateRealTimeUs(TimeSource *ts, int64_t systemTimeUs) { + if (ts == &mSystemTimeSource) { + return systemTimeUs; + } else { + return (int64_t)mClockEstimator->estimate(systemTimeUs, ts->getRealTimeUs()); + } +} + void AwesomePlayer::postVideoEvent_l(int64_t delayUs) { ATRACE_CALL(); @@ -2096,7 +2122,10 @@ void AwesomePlayer::onCheckAudioStatus() { mSeekNotificationSent = true; } - mSeeking = NO_SEEK; + if (mVideoSource == NULL) { + // For video the mSeeking flag is always reset in finishSeekIfNecessary + mSeeking = NO_SEEK; + } notifyIfMediaStarted_l(); } @@ -2292,8 +2321,8 @@ status_t AwesomePlayer::finishSetDataSource_l() { sniffedMIME = tmp.string(); if (meta == NULL - || !meta->findInt64( - "meta-data-size", &metaDataSize)) { + || !meta->findInt64("meta-data-size", + reinterpret_cast<int64_t*>(&metaDataSize))) { metaDataSize = kHighWaterMarkBytes; } @@ -2580,12 +2609,12 @@ status_t AwesomePlayer::getTrackInfo(Parcel *reply) const { status_t AwesomePlayer::selectAudioTrack_l( const sp<MediaSource>& source, size_t trackIndex) { - ALOGI("selectAudioTrack_l: trackIndex=%d, mFlags=0x%x", trackIndex, mFlags); + ALOGI("selectAudioTrack_l: trackIndex=%zu, mFlags=0x%x", trackIndex, mFlags); { Mutex::Autolock autoLock(mStatsLock); if ((ssize_t)trackIndex == mActiveAudioTrackIndex) { - ALOGI("Track %d is active. Does nothing.", trackIndex); + ALOGI("Track %zu is active. Does nothing.", trackIndex); return OK; } //mStats.mFlags = mFlags; @@ -2658,7 +2687,7 @@ status_t AwesomePlayer::selectTrack(size_t trackIndex, bool select) { trackCount += mTextDriver->countExternalTracks(); } if (trackIndex >= trackCount) { - ALOGE("Track index (%d) is out of range [0, %d)", trackIndex, trackCount); + ALOGE("Track index (%zu) is out of range [0, %zu)", trackIndex, trackCount); return ERROR_OUT_OF_RANGE; } @@ -2670,14 +2699,14 @@ status_t AwesomePlayer::selectTrack(size_t trackIndex, bool select) { isAudioTrack = !strncasecmp(mime, "audio/", 6); if (!isAudioTrack && strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) != 0) { - ALOGE("Track %d is not either audio or timed text", trackIndex); + ALOGE("Track %zu is not either audio or timed text", trackIndex); return ERROR_UNSUPPORTED; } } if (isAudioTrack) { if (!select) { - ALOGE("Deselect an audio track (%d) is not supported", trackIndex); + ALOGE("Deselect an audio track (%zu) is not supported", trackIndex); return ERROR_UNSUPPORTED; } return selectAudioTrack_l(mExtractor->getTrack(trackIndex), trackIndex); @@ -2800,7 +2829,8 @@ bool AwesomePlayer::isStreamingHTTP() const { return mCachedSource != NULL || mWVMExtractor != NULL; } -status_t AwesomePlayer::dump(int fd, const Vector<String16> &args) const { +status_t AwesomePlayer::dump( + int fd, const Vector<String16> & /* args */) const { Mutex::Autolock autoLock(mStatsLock); FILE *out = fdopen(dup(fd), "w"); @@ -2815,7 +2845,7 @@ status_t AwesomePlayer::dump(int fd, const Vector<String16> &args) const { fprintf(out, ", flags(0x%08x)", mStats.mFlags); if (mStats.mBitrate >= 0) { - fprintf(out, ", bitrate(%lld bps)", mStats.mBitrate); + fprintf(out, ", bitrate(%" PRId64 " bps)", mStats.mBitrate); } fprintf(out, "\n"); @@ -2823,7 +2853,7 @@ status_t AwesomePlayer::dump(int fd, const Vector<String16> &args) const { for (size_t i = 0; i < mStats.mTracks.size(); ++i) { const TrackStat &stat = mStats.mTracks.itemAt(i); - fprintf(out, " Track %d\n", i + 1); + fprintf(out, " Track %zu\n", i + 1); fprintf(out, " MIME(%s)", stat.mMIME.string()); if (!stat.mDecoderName.isEmpty()) { @@ -2835,8 +2865,8 @@ status_t AwesomePlayer::dump(int fd, const Vector<String16> &args) const { if ((ssize_t)i == mStats.mVideoTrackIndex) { fprintf(out, " videoDimensions(%d x %d), " - "numVideoFramesDecoded(%lld), " - "numVideoFramesDropped(%lld)\n", + "numVideoFramesDecoded(%" PRId64 "), " + "numVideoFramesDropped(%" PRId64 ")\n", mStats.mVideoWidth, mStats.mVideoHeight, mStats.mNumVideoFramesDecoded, diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp index 3017fe7..5b41f30 100644 --- a/media/libstagefright/CameraSource.cpp +++ b/media/libstagefright/CameraSource.cpp @@ -67,7 +67,7 @@ void CameraSourceListener::notify(int32_t msgType, int32_t ext1, int32_t ext2) { } void CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr, - camera_frame_metadata_t *metadata) { + camera_frame_metadata_t * /* metadata */) { ALOGV("postData(%d, ptr:%p, size:%d)", msgType, dataPtr->pointer(), dataPtr->size()); diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp index 5772316..591daac 100644 --- a/media/libstagefright/CameraSourceTimeLapse.cpp +++ b/media/libstagefright/CameraSourceTimeLapse.cpp @@ -134,7 +134,7 @@ bool CameraSourceTimeLapse::trySettingVideoSize( } bool videoSizeSupported = false; - for (uint32_t i = 0; i < supportedSizes.size(); ++i) { + for (size_t i = 0; i < supportedSizes.size(); ++i) { int32_t pictureWidth = supportedSizes[i].width; int32_t pictureHeight = supportedSizes[i].height; @@ -231,7 +231,7 @@ sp<IMemory> CameraSourceTimeLapse::createIMemoryCopy( return newMemory; } -bool CameraSourceTimeLapse::skipCurrentFrame(int64_t timestampUs) { +bool CameraSourceTimeLapse::skipCurrentFrame(int64_t /* timestampUs */) { ALOGV("skipCurrentFrame"); if (mSkipCurrentFrame) { mSkipCurrentFrame = false; diff --git a/media/libstagefright/ClockEstimator.cpp b/media/libstagefright/ClockEstimator.cpp new file mode 100644 index 0000000..34d1e42 --- /dev/null +++ b/media/libstagefright/ClockEstimator.cpp @@ -0,0 +1,177 @@ +/* +** +** Copyright 2014, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "ClockEstimator" +#include <utils/Log.h> + +#include <math.h> +#include <media/stagefright/ClockEstimator.h> + +#include <media/stagefright/foundation/ADebug.h> + +namespace android { + +WindowedLinearFitEstimator::WindowedLinearFitEstimator( + size_t headLength, double headFactor, size_t mainLength, double tailFactor) + : mHeadFactorInv(1. / headFactor), + mTailFactor(tailFactor), + mHistoryLength(mainLength + headLength), + mHeadLength(headLength) { + reset(); + mXHistory.resize(mHistoryLength); + mYHistory.resize(mHistoryLength); + mFirstWeight = pow(headFactor, mHeadLength); +} + +WindowedLinearFitEstimator::LinearFit::LinearFit() { + reset(); +} + +void WindowedLinearFitEstimator::LinearFit::reset() { + mX = mXX = mY = mYY = mXY = mW = 0.; +} + +double WindowedLinearFitEstimator::LinearFit::size() const { + double s = mW * mW + mX * mX + mY * mY + mXX * mXX + mXY * mXY + mYY * mYY; + if (s > 1e72) { + // 1e72 corresponds to clock monotonic time of about 8 years + ALOGW("estimator is overflowing: w=%g x=%g y=%g xx=%g xy=%g yy=%g", + mW, mX, mY, mXX, mXY, mYY); + } + return s; +} + +void WindowedLinearFitEstimator::LinearFit::add(double x, double y, double w) { + mW += w; + mX += w * x; + mY += w * y; + mXX += w * x * x; + mXY += w * x * y; + mYY += w * y * y; +} + +void WindowedLinearFitEstimator::LinearFit::combine(const LinearFit &lf) { + mW += lf.mW; + mX += lf.mX; + mY += lf.mY; + mXX += lf.mXX; + mXY += lf.mXY; + mYY += lf.mYY; +} + +void WindowedLinearFitEstimator::LinearFit::scale(double w) { + mW *= w; + mX *= w; + mY *= w; + mXX *= w; + mXY *= w; + mYY *= w; +} + +double WindowedLinearFitEstimator::LinearFit::interpolate(double x) { + double div = mW * mXX - mX * mX; + if (fabs(div) < 1e-5 * mW * mW) { + // this only should happen on the first value + return x; + // assuming a = 1, we could also return x + (mY - mX) / mW; + } + double a_div = (mW * mXY - mX * mY); + double b_div = (mXX * mY - mX * mXY); + ALOGV("a=%.4g b=%.4g in=%g out=%g", + a_div / div, b_div / div, x, (a_div * x + b_div) / div); + return (a_div * x + b_div) / div; +} + +double WindowedLinearFitEstimator::estimate(double x, double y) { + /* + * TODO: We could update the head by adding the new sample to it + * and amplifying it, but this approach can lead to unbounded + * error. Instead, we recalculate the head at each step, which + * is computationally more expensive. We could balance the two + * methods by recalculating just before the error becomes + * significant. + */ + const bool update_head = false; + if (update_head) { + // add new sample to the head + mHead.scale(mHeadFactorInv); // amplify head + mHead.add(x, y, mFirstWeight); + } + + /* + * TRICKY: place elements into the circular buffer at decreasing + * indices, so that we can access past elements by addition + * (thereby avoiding potentially negative indices.) + */ + if (mNumSamples >= mHeadLength) { + // move last head sample from head to the main window + size_t lastHeadIx = (mSampleIx + mHeadLength) % mHistoryLength; + if (update_head) { + mHead.add(mXHistory[lastHeadIx], mYHistory[lastHeadIx], -1.); // remove + } + mMain.add(mXHistory[lastHeadIx], mYHistory[lastHeadIx], 1.); + if (mNumSamples >= mHistoryLength) { + // move last main sample from main window to tail + mMain.add(mXHistory[mSampleIx], mYHistory[mSampleIx], -1.); // remove + mTail.add(mXHistory[mSampleIx], mYHistory[mSampleIx], 1.); + mTail.scale(mTailFactor); // attenuate tail + } + } + + mXHistory.editItemAt(mSampleIx) = x; + mYHistory.editItemAt(mSampleIx) = y; + if (mNumSamples < mHistoryLength) { + ++mNumSamples; + } + + // recalculate head unless we were using the update method + if (!update_head) { + mHead.reset(); + double w = mFirstWeight; + for (size_t headIx = 0; headIx < mHeadLength && headIx < mNumSamples; ++headIx) { + size_t ix = (mSampleIx + headIx) % mHistoryLength; + mHead.add(mXHistory[ix], mYHistory[ix], w); + w *= mHeadFactorInv; + } + } + + if (mSampleIx > 0) { + --mSampleIx; + } else { + mSampleIx = mHistoryLength - 1; + } + + // return estimation result + LinearFit total; + total.combine(mHead); + total.combine(mMain); + total.combine(mTail); + return total.interpolate(x); +} + +void WindowedLinearFitEstimator::reset() { + mHead.reset(); + mMain.reset(); + mTail.reset(); + mNumSamples = 0; + mSampleIx = mHistoryLength - 1; +} + +}; // namespace android + + diff --git a/media/libstagefright/FLACExtractor.cpp b/media/libstagefright/FLACExtractor.cpp index 098fcf9..fa7251c 100644 --- a/media/libstagefright/FLACExtractor.cpp +++ b/media/libstagefright/FLACExtractor.cpp @@ -208,55 +208,55 @@ private: // with the same parameter list, but discard redundant information. FLAC__StreamDecoderReadStatus FLACParser::read_callback( - const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], + const FLAC__StreamDecoder * /* decoder */, FLAC__byte buffer[], size_t *bytes, void *client_data) { return ((FLACParser *) client_data)->readCallback(buffer, bytes); } FLAC__StreamDecoderSeekStatus FLACParser::seek_callback( - const FLAC__StreamDecoder *decoder, + const FLAC__StreamDecoder * /* decoder */, FLAC__uint64 absolute_byte_offset, void *client_data) { return ((FLACParser *) client_data)->seekCallback(absolute_byte_offset); } FLAC__StreamDecoderTellStatus FLACParser::tell_callback( - const FLAC__StreamDecoder *decoder, + const FLAC__StreamDecoder * /* decoder */, FLAC__uint64 *absolute_byte_offset, void *client_data) { return ((FLACParser *) client_data)->tellCallback(absolute_byte_offset); } FLAC__StreamDecoderLengthStatus FLACParser::length_callback( - const FLAC__StreamDecoder *decoder, + const FLAC__StreamDecoder * /* decoder */, FLAC__uint64 *stream_length, void *client_data) { return ((FLACParser *) client_data)->lengthCallback(stream_length); } FLAC__bool FLACParser::eof_callback( - const FLAC__StreamDecoder *decoder, void *client_data) + const FLAC__StreamDecoder * /* decoder */, void *client_data) { return ((FLACParser *) client_data)->eofCallback(); } FLAC__StreamDecoderWriteStatus FLACParser::write_callback( - const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, + const FLAC__StreamDecoder * /* decoder */, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) { return ((FLACParser *) client_data)->writeCallback(frame, buffer); } void FLACParser::metadata_callback( - const FLAC__StreamDecoder *decoder, + const FLAC__StreamDecoder * /* decoder */, const FLAC__StreamMetadata *metadata, void *client_data) { ((FLACParser *) client_data)->metadataCallback(metadata); } void FLACParser::error_callback( - const FLAC__StreamDecoder *decoder, + const FLAC__StreamDecoder * /* decoder */, FLAC__StreamDecoderErrorStatus status, void *client_data) { ((FLACParser *) client_data)->errorCallback(status); @@ -380,15 +380,21 @@ void FLACParser::errorCallback(FLAC__StreamDecoderErrorStatus status) // Copy samples from FLAC native 32-bit non-interleaved to 16-bit interleaved. // These are candidates for optimization if needed. -static void copyMono8(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels) -{ +static void copyMono8( + short *dst, + const int *const *src, + unsigned nSamples, + unsigned /* nChannels */) { for (unsigned i = 0; i < nSamples; ++i) { *dst++ = src[0][i] << 8; } } -static void copyStereo8(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels) -{ +static void copyStereo8( + short *dst, + const int *const *src, + unsigned nSamples, + unsigned /* nChannels */) { for (unsigned i = 0; i < nSamples; ++i) { *dst++ = src[0][i] << 8; *dst++ = src[1][i] << 8; @@ -404,15 +410,21 @@ static void copyMultiCh8(short *dst, const int *const *src, unsigned nSamples, u } } -static void copyMono16(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels) -{ +static void copyMono16( + short *dst, + const int *const *src, + unsigned nSamples, + unsigned /* nChannels */) { for (unsigned i = 0; i < nSamples; ++i) { *dst++ = src[0][i]; } } -static void copyStereo16(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels) -{ +static void copyStereo16( + short *dst, + const int *const *src, + unsigned nSamples, + unsigned /* nChannels */) { for (unsigned i = 0; i < nSamples; ++i) { *dst++ = src[0][i]; *dst++ = src[1][i]; @@ -430,15 +442,21 @@ static void copyMultiCh16(short *dst, const int *const *src, unsigned nSamples, // 24-bit versions should do dithering or noise-shaping, here or in AudioFlinger -static void copyMono24(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels) -{ +static void copyMono24( + short *dst, + const int *const *src, + unsigned nSamples, + unsigned /* nChannels */) { for (unsigned i = 0; i < nSamples; ++i) { *dst++ = src[0][i] >> 8; } } -static void copyStereo24(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels) -{ +static void copyStereo24( + short *dst, + const int *const *src, + unsigned nSamples, + unsigned /* nChannels */) { for (unsigned i = 0; i < nSamples; ++i) { *dst++ = src[0][i] >> 8; *dst++ = src[1][i] >> 8; @@ -454,8 +472,11 @@ static void copyMultiCh24(short *dst, const int *const *src, unsigned nSamples, } } -static void copyTrespass(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels) -{ +static void copyTrespass( + short * /* dst */, + const int *const * /* src */, + unsigned /* nSamples */, + unsigned /* nChannels */) { TRESPASS(); } @@ -700,7 +721,7 @@ FLACSource::~FLACSource() } } -status_t FLACSource::start(MetaData *params) +status_t FLACSource::start(MetaData * /* params */) { ALOGV("FLACSource::start"); @@ -792,8 +813,7 @@ sp<MediaSource> FLACExtractor::getTrack(size_t index) } sp<MetaData> FLACExtractor::getTrackMetaData( - size_t index, uint32_t flags) -{ + size_t index, uint32_t /* flags */) { if (mInitCheck != OK || index > 0) { return NULL; } diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp index 380dab4..4a63152 100644 --- a/media/libstagefright/MP3Extractor.cpp +++ b/media/libstagefright/MP3Extractor.cpp @@ -398,7 +398,8 @@ sp<MediaSource> MP3Extractor::getTrack(size_t index) { mSeeker); } -sp<MetaData> MP3Extractor::getTrackMetaData(size_t index, uint32_t flags) { +sp<MetaData> MP3Extractor::getTrackMetaData( + size_t index, uint32_t /* flags */) { if (mInitCheck != OK || index != 0) { return NULL; } diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp index c9ed5bb..78c12e1 100644 --- a/media/libstagefright/MPEG2TSWriter.cpp +++ b/media/libstagefright/MPEG2TSWriter.cpp @@ -555,7 +555,7 @@ status_t MPEG2TSWriter::addSource(const sp<MediaSource> &source) { return OK; } -status_t MPEG2TSWriter::start(MetaData *param) { +status_t MPEG2TSWriter::start(MetaData * /* param */) { CHECK(!mStarted); mStarted = true; @@ -596,7 +596,8 @@ bool MPEG2TSWriter::reachedEOS() { return !mStarted || (mNumSourcesDone == mSources.size() ? true : false); } -status_t MPEG2TSWriter::dump(int fd, const Vector<String16> &args) { +status_t MPEG2TSWriter::dump( + int /* fd */, const Vector<String16> & /* args */) { return OK; } diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index 9b36b6a..7d3a838 100644 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -39,6 +39,7 @@ #include <utils/String8.h> #include <byteswap.h> +#include "include/ID3.h" namespace android { @@ -259,7 +260,7 @@ static void hexdump(const void *_data, size_t size) { const uint8_t *data = (const uint8_t *)_data; size_t offset = 0; while (offset < size) { - printf("0x%04x ", offset); + printf("0x%04zx ", offset); size_t n = size - offset; if (n > 16) { @@ -570,7 +571,8 @@ static int32_t readSize(off64_t offset, return size; } -status_t MPEG4Extractor::parseDrmSINF(off64_t *offset, off64_t data_offset) { +status_t MPEG4Extractor::parseDrmSINF( + off64_t * /* offset */, off64_t data_offset) { uint8_t updateIdTag; if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) { return ERROR_IO; @@ -1787,6 +1789,18 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { break; } + case FOURCC('I', 'D', '3', '2'): + { + if (chunk_data_size < 6) { + return ERROR_MALFORMED; + } + + parseID3v2MetaData(data_offset + 6); + + *offset += chunk_size; + break; + } + case FOURCC('-', '-', '-', '-'): { mLastCommentMean.clear(); @@ -2167,7 +2181,7 @@ status_t MPEG4Extractor::parseITunesMetaData(off64_t offset, size_t size) { break; } - if (size >= 8 && metadataKey) { + if (size >= 8 && metadataKey && !mFileMetaData->hasData(metadataKey)) { if (metadataKey == kKeyAlbumArt) { mFileMetaData->setData( kKeyAlbumArt, MetaData::TYPE_NONE, @@ -2316,6 +2330,62 @@ status_t MPEG4Extractor::parse3GPPMetaData(off64_t offset, size_t size, int dept return OK; } +void MPEG4Extractor::parseID3v2MetaData(off64_t offset) { + ID3 id3(mDataSource, true /* ignorev1 */, offset); + + if (id3.isValid()) { + struct Map { + int key; + const char *tag1; + const char *tag2; + }; + static const Map kMap[] = { + { kKeyAlbum, "TALB", "TAL" }, + { kKeyArtist, "TPE1", "TP1" }, + { kKeyAlbumArtist, "TPE2", "TP2" }, + { kKeyComposer, "TCOM", "TCM" }, + { kKeyGenre, "TCON", "TCO" }, + { kKeyTitle, "TIT2", "TT2" }, + { kKeyYear, "TYE", "TYER" }, + { kKeyAuthor, "TXT", "TEXT" }, + { kKeyCDTrackNumber, "TRK", "TRCK" }, + { kKeyDiscNumber, "TPA", "TPOS" }, + { kKeyCompilation, "TCP", "TCMP" }, + }; + static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]); + + for (size_t i = 0; i < kNumMapEntries; ++i) { + if (!mFileMetaData->hasData(kMap[i].key)) { + ID3::Iterator *it = new ID3::Iterator(id3, kMap[i].tag1); + if (it->done()) { + delete it; + it = new ID3::Iterator(id3, kMap[i].tag2); + } + + if (it->done()) { + delete it; + continue; + } + + String8 s; + it->getString(&s); + delete it; + + mFileMetaData->setCString(kMap[i].key, s); + } + } + + size_t dataSize; + String8 mime; + const void *data = id3.getAlbumArt(&dataSize, &mime); + + if (data) { + mFileMetaData->setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize); + mFileMetaData->setCString(kKeyAlbumArtMIME, mime.string()); + } + } +} + sp<MediaSource> MPEG4Extractor::getTrack(size_t index) { status_t err; if ((err = readMetaData()) != OK) { @@ -2419,6 +2489,11 @@ status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( return ERROR_MALFORMED; } + static uint32_t kSamplingRate[] = { + 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, + 16000, 12000, 11025, 8000, 7350 + }; + ABitReader br(csd, csd_size); uint32_t objectType = br.getBits(5); @@ -2426,6 +2501,9 @@ status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( objectType = 32 + br.getBits(6); } + //keep AOT type + mLastTrack->meta->setInt32(kKeyAACAOT, objectType); + uint32_t freqIndex = br.getBits(4); int32_t sampleRate = 0; @@ -2438,29 +2516,30 @@ status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( numChannels = br.getBits(4); } else { numChannels = br.getBits(4); - if (objectType == 5) { - // SBR specific config per 14496-3 table 1.13 - freqIndex = br.getBits(4); - if (freqIndex == 15) { - if (csd_size < 8) { - return ERROR_MALFORMED; - } - sampleRate = br.getBits(24); - } + + if (freqIndex == 13 || freqIndex == 14) { + return ERROR_MALFORMED; } - if (sampleRate == 0) { - static uint32_t kSamplingRate[] = { - 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, - 16000, 12000, 11025, 8000, 7350 - }; + sampleRate = kSamplingRate[freqIndex]; + } - if (freqIndex == 13 || freqIndex == 14) { + if (objectType == 5 || objectType == 29) { // SBR specific config per 14496-3 table 1.13 + uint32_t extFreqIndex = br.getBits(4); + int32_t extSampleRate; + if (extFreqIndex == 15) { + if (csd_size < 8) { return ERROR_MALFORMED; } - - sampleRate = kSamplingRate[freqIndex]; + extSampleRate = br.getBits(24); + } else { + if (extFreqIndex == 13 || extFreqIndex == 14) { + return ERROR_MALFORMED; + } + extSampleRate = kSamplingRate[extFreqIndex]; } + //TODO: save the extension sampling rate value in meta data => + // mLastTrack->meta->setInt32(kKeyExtSampleRate, extSampleRate); } if (numChannels == 0) { @@ -2724,7 +2803,8 @@ status_t MPEG4Source::parseChunk(off64_t *offset) { return OK; } -status_t MPEG4Source::parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size) { +status_t MPEG4Source::parseSampleAuxiliaryInformationSizes( + off64_t offset, off64_t /* size */) { ALOGV("parseSampleAuxiliaryInformationSizes"); // 14496-12 8.7.12 uint8_t version; @@ -2786,7 +2866,8 @@ status_t MPEG4Source::parseSampleAuxiliaryInformationSizes(off64_t offset, off64 return OK; } -status_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size) { +status_t MPEG4Source::parseSampleAuxiliaryInformationOffsets( + off64_t offset, off64_t /* size */) { ALOGV("parseSampleAuxiliaryInformationOffsets"); // 14496-12 8.7.13 uint8_t version; @@ -3203,7 +3284,7 @@ status_t MPEG4Source::read( uint32_t sampleIndex; status_t err = mSampleTable->findSampleAtTime( - seekTimeUs * mTimescale / 1000000, + seekTimeUs, 1000000, mTimescale, &sampleIndex, findFlags); if (mode == ReadOptions::SEEK_CLOSEST) { diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp index a0f17b5..58a4487 100644 --- a/media/libstagefright/MPEG4Writer.cpp +++ b/media/libstagefright/MPEG4Writer.cpp @@ -16,6 +16,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "MPEG4Writer" +#include <inttypes.h> #include <utils/Log.h> #include <arpa/inet.h> @@ -43,7 +44,9 @@ namespace android { static const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024; -static const int64_t kMax32BitFileSize = 0x007fffffffLL; +static const int64_t kMax32BitFileSize = 0x00ffffffffLL; // 2^32-1 : max FAT32 + // filesystem file size + // used by most SD cards static const uint8_t kNalUnitTypeSeqParamSet = 0x07; static const uint8_t kNalUnitTypePicParamSet = 0x08; static const int64_t kInitialDelayTimeUs = 700000LL; @@ -406,7 +409,7 @@ status_t MPEG4Writer::dump( } status_t MPEG4Writer::Track::dump( - int fd, const Vector<String16>& args) const { + int fd, const Vector<String16>& /* args */) const { const size_t SIZE = 256; char buffer[SIZE]; String8 result; @@ -417,7 +420,7 @@ status_t MPEG4Writer::Track::dump( result.append(buffer); snprintf(buffer, SIZE, " frames encoded : %d\n", mStszTableEntries->count()); result.append(buffer); - snprintf(buffer, SIZE, " duration encoded : %lld us\n", mTrackDurationUs); + snprintf(buffer, SIZE, " duration encoded : %" PRId64 " us\n", mTrackDurationUs); result.append(buffer); ::write(fd, result.string(), result.size()); return OK; @@ -860,11 +863,11 @@ status_t MPEG4Writer::reset() { // Fix up the size of the 'mdat' chunk. if (mUse32BitOffset) { lseek64(mFd, mMdatOffset, SEEK_SET); - int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset)); + uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset)); ::write(mFd, &size, 4); } else { lseek64(mFd, mMdatOffset + 8, SEEK_SET); - int64_t size = mOffset - mMdatOffset; + uint64_t size = mOffset - mMdatOffset; size = hton64(size); ::write(mFd, &size, 8); } @@ -1404,7 +1407,7 @@ void MPEG4Writer::Track::addOneSttsTableEntry( size_t sampleCount, int32_t duration) { if (duration == 0) { - ALOGW("0-duration samples found: %d", sampleCount); + ALOGW("0-duration samples found: %zu", sampleCount); } mSttsTableEntries->add(htonl(sampleCount)); mSttsTableEntries->add(htonl(duration)); @@ -1584,7 +1587,7 @@ void MPEG4Writer::writeAllChunks() { sendSessionSummary(); mChunkInfos.clear(); - ALOGD("%d chunks are written in the last batch", outstandingChunks); + ALOGD("%zu chunks are written in the last batch", outstandingChunks); } bool MPEG4Writer::findChunkToWrite(Chunk *chunk) { @@ -1774,7 +1777,7 @@ status_t MPEG4Writer::Track::stop() { void *dummy; pthread_join(mThread, &dummy); - status_t err = (status_t) dummy; + status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); ALOGD("Stopping %s track source", mIsAudio? "Audio": "Video"); { @@ -1797,7 +1800,7 @@ void *MPEG4Writer::Track::ThreadWrapper(void *me) { Track *track = static_cast<Track *>(me); status_t err = track->threadEntry(); - return (void *) err; + return (void *)(uintptr_t)err; } static void getNalUnitType(uint8_t byte, uint8_t* type) { @@ -1869,7 +1872,7 @@ status_t MPEG4Writer::Track::copyAVCCodecSpecificData( // 2 bytes for each of the parameter set length field // plus the 7 bytes for the header if (size < 4 + 7) { - ALOGE("Codec specific data length too short: %d", size); + ALOGE("Codec specific data length too short: %zu", size); return ERROR_MALFORMED; } @@ -1938,7 +1941,7 @@ status_t MPEG4Writer::Track::parseAVCCodecSpecificData( } if (nSeqParamSets > 0x1F) { - ALOGE("Too many seq parameter sets (%d) found", nSeqParamSets); + ALOGE("Too many seq parameter sets (%zu) found", nSeqParamSets); return ERROR_MALFORMED; } } @@ -1951,7 +1954,7 @@ status_t MPEG4Writer::Track::parseAVCCodecSpecificData( return ERROR_MALFORMED; } if (nPicParamSets > 0xFF) { - ALOGE("Too many pic parameter sets (%d) found", nPicParamSets); + ALOGE("Too many pic parameter sets (%zd) found", nPicParamSets); return ERROR_MALFORMED; } } @@ -1981,7 +1984,7 @@ status_t MPEG4Writer::Track::makeAVCCodecSpecificData( } if (size < 4) { - ALOGE("Codec specific data length too short: %d", size); + ALOGE("Codec specific data length too short: %zu", size); return ERROR_MALFORMED; } diff --git a/media/libstagefright/MediaAdapter.cpp b/media/libstagefright/MediaAdapter.cpp index 2484212..d680e0c 100644 --- a/media/libstagefright/MediaAdapter.cpp +++ b/media/libstagefright/MediaAdapter.cpp @@ -36,7 +36,7 @@ MediaAdapter::~MediaAdapter() { CHECK(mCurrentMediaBuffer == NULL); } -status_t MediaAdapter::start(MetaData *params) { +status_t MediaAdapter::start(MetaData * /* params */) { Mutex::Autolock autoLock(mAdapterLock); if (!mStarted) { mStarted = true; @@ -75,7 +75,7 @@ void MediaAdapter::signalBufferReturned(MediaBuffer *buffer) { } status_t MediaAdapter::read( - MediaBuffer **buffer, const ReadOptions *options) { + MediaBuffer **buffer, const ReadOptions * /* options */) { Mutex::Autolock autoLock(mAdapterLock); if (!mStarted) { ALOGV("Read before even started!"); diff --git a/media/libstagefright/MediaBuffer.cpp b/media/libstagefright/MediaBuffer.cpp index 11b80bf..8af0880 100644 --- a/media/libstagefright/MediaBuffer.cpp +++ b/media/libstagefright/MediaBuffer.cpp @@ -27,7 +27,6 @@ #include <media/stagefright/MetaData.h> #include <ui/GraphicBuffer.h> -#include <sys/atomics.h> namespace android { @@ -92,7 +91,7 @@ void MediaBuffer::release() { return; } - int prevCount = __atomic_dec(&mRefCount); + int prevCount = __sync_fetch_and_sub(&mRefCount, 1); if (prevCount == 1) { if (mObserver == NULL) { delete this; @@ -112,7 +111,7 @@ void MediaBuffer::claim() { } void MediaBuffer::add_ref() { - (void) __atomic_inc(&mRefCount); + (void) __sync_fetch_and_add(&mRefCount, 1); } void *MediaBuffer::data() const { diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index 8af1aaf..3cb4217 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -115,7 +115,7 @@ status_t MediaCodec::init(const char *name, bool nameIsType, bool encoder) { if (codecIdx >= 0) { Vector<AString> types; if (mcl->getSupportedTypes(codecIdx, &types) == OK) { - for (int i = 0; i < types.size(); i++) { + for (size_t i = 0; i < types.size(); i++) { if (types[i].startsWith("video/")) { needDedicatedLooper = true; break; @@ -1520,8 +1520,8 @@ size_t MediaCodec::updateBuffers( int32_t portIndex, const sp<AMessage> &msg) { CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); - void *bufferID; - CHECK(msg->findPointer("buffer-id", &bufferID)); + uint32_t bufferID; + CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; @@ -1680,7 +1680,7 @@ status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) { return -EACCES; } - if (render && (info->mData == NULL || info->mData->size() != 0)) { + if (render && info->mData != NULL && info->mData->size() != 0) { info->mNotify->setInt32("render", true); if (mSoftRenderer != NULL) { diff --git a/media/libstagefright/MetaData.cpp b/media/libstagefright/MetaData.cpp index 7b60afc..74234a6 100644 --- a/media/libstagefright/MetaData.cpp +++ b/media/libstagefright/MetaData.cpp @@ -16,6 +16,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "MetaData" +#include <inttypes.h> #include <utils/Log.h> #include <stdlib.h> @@ -221,6 +222,16 @@ bool MetaData::findData(uint32_t key, uint32_t *type, return true; } +bool MetaData::hasData(uint32_t key) const { + ssize_t i = mItems.indexOfKey(key); + + if (i < 0) { + return false; + } + + return true; +} + MetaData::typed_data::typed_data() : mType(0), mSize(0) { @@ -297,7 +308,7 @@ String8 MetaData::typed_data::asString() const { const void *data = storage(); switch(mType) { case TYPE_NONE: - out = String8::format("no type, size %d)", mSize); + out = String8::format("no type, size %zu)", mSize); break; case TYPE_C_STRING: out = String8::format("(char*) %s", (const char *)data); @@ -306,7 +317,7 @@ String8 MetaData::typed_data::asString() const { out = String8::format("(int32_t) %d", *(int32_t *)data); break; case TYPE_INT64: - out = String8::format("(int64_t) %lld", *(int64_t *)data); + out = String8::format("(int64_t) %" PRId64, *(int64_t *)data); break; case TYPE_FLOAT: out = String8::format("(float) %f", *(float *)data); @@ -323,7 +334,7 @@ String8 MetaData::typed_data::asString() const { } default: - out = String8::format("(unknown type %d, size %d)", mType, mSize); + out = String8::format("(unknown type %d, size %zu)", mType, mSize); if (mSize <= 48) { // if it's less than three lines of hex data, dump it AString foo; hexdump(data, mSize, 0, &foo); diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp index 05e599b..06e2d43 100644 --- a/media/libstagefright/NuCachedSource2.cpp +++ b/media/libstagefright/NuCachedSource2.cpp @@ -326,7 +326,7 @@ void NuCachedSource2::fetchInternal() { mNumRetriesLeft = 0; } - ALOGE("source returned error %ld, %d retries left", n, mNumRetriesLeft); + ALOGE("source returned error %d, %d retries left", n, mNumRetriesLeft); mCache->releasePage(page); } else if (n == 0) { ALOGI("ERROR_END_OF_STREAM"); @@ -641,7 +641,7 @@ void NuCachedSource2::updateCacheParamsFromString(const char *s) { ssize_t lowwaterMarkKb, highwaterMarkKb; int keepAliveSecs; - if (sscanf(s, "%ld/%ld/%d", + if (sscanf(s, "%zd/%zd/%d", &lowwaterMarkKb, &highwaterMarkKb, &keepAliveSecs) != 3) { ALOGE("Failed to parse cache parameters from '%s'.", s); return; diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp index 9f9352d..72f2306 100644 --- a/media/libstagefright/OMXClient.cpp +++ b/media/libstagefright/OMXClient.cpp @@ -141,7 +141,7 @@ private: const sp<IOMX> &getOMX(node_id node) const; const sp<IOMX> &getOMX_l(node_id node) const; - static bool IsSoftwareComponent(const char *name); + static bool CanLiveLocally(const char *name); DISALLOW_EVIL_CONSTRUCTORS(MuxOMX); }; @@ -164,7 +164,7 @@ bool MuxOMX::isLocalNode_l(node_id node) const { } // static -bool MuxOMX::IsSoftwareComponent(const char *name) { +bool MuxOMX::CanLiveLocally(const char *name) { return !strncasecmp(name, "OMX.google.", 11); } @@ -197,7 +197,7 @@ status_t MuxOMX::allocateNode( sp<IOMX> omx; - if (IsSoftwareComponent(name)) { + if (CanLiveLocally(name)) { if (mLocalOMX == NULL) { mLocalOMX = new OMX; } @@ -382,7 +382,7 @@ status_t OMXClient::connect() { mOMX = service->getOMX(); CHECK(mOMX.get() != NULL); - if (!mOMX->livesLocally(NULL /* node */, getpid())) { + if (!mOMX->livesLocally(0 /* node */, getpid())) { ALOGI("Using client-side OMX mux."); mOMX = new MuxOMX(mOMX); } diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index 43736ad..d5550e8 100644 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include <inttypes.h> + //#define LOG_NDEBUG 0 #define LOG_TAG "OMXCodec" #include <utils/Log.h> @@ -92,6 +94,7 @@ static sp<MediaSource> InstantiateSoftwareEncoder( #define CODEC_LOGI(x, ...) ALOGI("[%s] "x, mComponentName, ##__VA_ARGS__) #define CODEC_LOGV(x, ...) ALOGV("[%s] "x, mComponentName, ##__VA_ARGS__) +#define CODEC_LOGW(x, ...) ALOGW("[%s] "x, mComponentName, ##__VA_ARGS__) #define CODEC_LOGE(x, ...) ALOGE("[%s] "x, mComponentName, ##__VA_ARGS__) struct OMXCodecObserver : public BnOMXObserver { @@ -666,7 +669,7 @@ status_t OMXCodec::setVideoPortFormatType( // CHECK_EQ(format.nIndex, index); #if 1 - CODEC_LOGV("portIndex: %ld, index: %ld, eCompressionFormat=%d eColorFormat=%d", + CODEC_LOGV("portIndex: %u, index: %u, eCompressionFormat=%d eColorFormat=%d", portIndex, index, format.eCompressionFormat, format.eColorFormat); #endif @@ -768,7 +771,7 @@ status_t OMXCodec::isColorFormatSupported( portFormat.nIndex = index; if (index >= kMaxColorFormatSupported) { - CODEC_LOGE("More than %ld color formats are supported???", index); + CODEC_LOGE("More than %u color formats are supported???", index); break; } } @@ -1777,21 +1780,42 @@ status_t OMXCodec::allocateOutputBuffersFromNativeWindow() { strerror(-err), -err); return err; } - - // XXX: Is this the right logic to use? It's not clear to me what the OMX - // buffer counts refer to - how do they account for the renderer holding on - // to buffers? - if (def.nBufferCountActual < def.nBufferCountMin + minUndequeuedBufs) { - OMX_U32 newBufferCount = def.nBufferCountMin + minUndequeuedBufs; + // FIXME: assume that surface is controlled by app (native window + // returns the number for the case when surface is not controlled by app) + // FIXME2: This means that minUndeqeueudBufs can be 1 larger than reported + // For now, try to allocate 1 more buffer, but don't fail if unsuccessful + + // Use conservative allocation while also trying to reduce starvation + // + // 1. allocate at least nBufferCountMin + minUndequeuedBuffers - that is the + // minimum needed for the consumer to be able to work + // 2. try to allocate two (2) additional buffers to reduce starvation from + // the consumer + // plus an extra buffer to account for incorrect minUndequeuedBufs + CODEC_LOGI("OMX-buffers: min=%u actual=%u undeq=%d+1", + def.nBufferCountMin, def.nBufferCountActual, minUndequeuedBufs); + + for (OMX_U32 extraBuffers = 2 + 1; /* condition inside loop */; extraBuffers--) { + OMX_U32 newBufferCount = + def.nBufferCountMin + minUndequeuedBufs + extraBuffers; def.nBufferCountActual = newBufferCount; err = mOMX->setParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - if (err != OK) { - CODEC_LOGE("setting nBufferCountActual to %lu failed: %d", - newBufferCount, err); + + if (err == OK) { + minUndequeuedBufs += extraBuffers; + break; + } + + CODEC_LOGW("setting nBufferCountActual to %u failed: %d", + newBufferCount, err); + /* exit condition */ + if (extraBuffers == 0) { return err; } } + CODEC_LOGI("OMX-buffers: min=%u actual=%u undeq=%d+1", + def.nBufferCountMin, def.nBufferCountActual, minUndequeuedBufs); err = native_window_set_buffer_count( mNativeWindow.get(), def.nBufferCountActual); @@ -1801,7 +1825,7 @@ status_t OMXCodec::allocateOutputBuffersFromNativeWindow() { return err; } - CODEC_LOGV("allocating %lu buffers from a native window of size %lu on " + CODEC_LOGV("allocating %u buffers from a native window of size %u on " "output port", def.nBufferCountActual, def.nBufferSize); // Dequeue buffers and send them to OMX @@ -1834,7 +1858,7 @@ status_t OMXCodec::allocateOutputBuffersFromNativeWindow() { mPortBuffers[kPortIndexOutput].editItemAt(i).mBuffer = bufferId; - CODEC_LOGV("registered graphic buffer with ID %p (pointer = %p)", + CODEC_LOGV("registered graphic buffer with ID %u (pointer = %p)", bufferId, graphicBuffer.get()); } @@ -1861,7 +1885,7 @@ status_t OMXCodec::allocateOutputBuffersFromNativeWindow() { status_t OMXCodec::cancelBufferToNativeWindow(BufferInfo *info) { CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US); - CODEC_LOGV("Calling cancelBuffer on buffer %p", info->mBuffer); + CODEC_LOGV("Calling cancelBuffer on buffer %u", info->mBuffer); int err = mNativeWindow->cancelBuffer( mNativeWindow.get(), info->mMediaBuffer->graphicBuffer().get(), -1); if (err != 0) { @@ -2099,7 +2123,7 @@ void OMXCodec::on_message(const omx_message &msg) { { IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer; - CODEC_LOGV("EMPTY_BUFFER_DONE(buffer: %p)", buffer); + CODEC_LOGV("EMPTY_BUFFER_DONE(buffer: %u)", buffer); Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput]; size_t i = 0; @@ -2109,7 +2133,7 @@ void OMXCodec::on_message(const omx_message &msg) { CHECK(i < buffers->size()); if ((*buffers)[i].mStatus != OWNED_BY_COMPONENT) { - ALOGW("We already own input buffer %p, yet received " + ALOGW("We already own input buffer %u, yet received " "an EMPTY_BUFFER_DONE.", buffer); } @@ -2123,7 +2147,7 @@ void OMXCodec::on_message(const omx_message &msg) { } if (mPortStatus[kPortIndexInput] == DISABLING) { - CODEC_LOGV("Port is disabled, freeing buffer %p", buffer); + CODEC_LOGV("Port is disabled, freeing buffer %u", buffer); status_t err = freeBuffer(kPortIndexInput, i); CHECK_EQ(err, (status_t)OK); @@ -2145,7 +2169,7 @@ void OMXCodec::on_message(const omx_message &msg) { IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer; OMX_U32 flags = msg.u.extended_buffer_data.flags; - CODEC_LOGV("FILL_BUFFER_DONE(buffer: %p, size: %ld, flags: 0x%08lx, timestamp: %lld us (%.2f secs))", + CODEC_LOGV("FILL_BUFFER_DONE(buffer: %u, size: %u, flags: 0x%08x, timestamp: %lld us (%.2f secs))", buffer, msg.u.extended_buffer_data.range_length, flags, @@ -2162,14 +2186,14 @@ void OMXCodec::on_message(const omx_message &msg) { BufferInfo *info = &buffers->editItemAt(i); if (info->mStatus != OWNED_BY_COMPONENT) { - ALOGW("We already own output buffer %p, yet received " + ALOGW("We already own output buffer %u, yet received " "a FILL_BUFFER_DONE.", buffer); } info->mStatus = OWNED_BY_US; if (mPortStatus[kPortIndexOutput] == DISABLING) { - CODEC_LOGV("Port is disabled, freeing buffer %p", buffer); + CODEC_LOGV("Port is disabled, freeing buffer %u", buffer); status_t err = freeBuffer(kPortIndexOutput, i); CHECK_EQ(err, (status_t)OK); @@ -2238,7 +2262,7 @@ void OMXCodec::on_message(const omx_message &msg) { kKeyPlatformPrivate, msg.u.extended_buffer_data.platform_private); - buffer->meta_data()->setPointer( + buffer->meta_data()->setInt32( kKeyBufferID, msg.u.extended_buffer_data.buffer); @@ -2380,7 +2404,7 @@ void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { case OMX_EventError: { - CODEC_LOGE("ERROR(0x%08lx, %ld)", data1, data2); + CODEC_LOGE("OMX_EventError(0x%08x, %u)", data1, data2); setState(ERROR); break; @@ -2388,7 +2412,7 @@ void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { case OMX_EventPortSettingsChanged: { - CODEC_LOGV("OMX_EventPortSettingsChanged(port=%ld, data2=0x%08lx)", + CODEC_LOGV("OMX_EventPortSettingsChanged(port=%u, data2=0x%08x)", data1, data2); if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { @@ -2428,7 +2452,7 @@ void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { // The scale is in 16.16 format. // scale 1.0 = 0x010000. When there is no // need to change the display, skip it. - ALOGV("Get OMX_IndexConfigScale: 0x%lx/0x%lx", + ALOGV("Get OMX_IndexConfigScale: 0x%x/0x%x", scale.xWidth, scale.xHeight); if (scale.xWidth != 0x010000) { @@ -2462,7 +2486,7 @@ void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { default: { - CODEC_LOGV("EVENT(%d, %ld, %ld)", event, data1, data2); + CODEC_LOGV("EVENT(%d, %u, %u)", event, data1, data2); break; } } @@ -2479,7 +2503,7 @@ void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) { case OMX_CommandPortDisable: { OMX_U32 portIndex = data; - CODEC_LOGV("PORT_DISABLED(%ld)", portIndex); + CODEC_LOGV("PORT_DISABLED(%u)", portIndex); CHECK(mState == EXECUTING || mState == RECONFIGURING); CHECK_EQ((int)mPortStatus[portIndex], (int)DISABLING); @@ -2503,7 +2527,7 @@ void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) { status_t err = enablePortAsync(portIndex); if (err != OK) { - CODEC_LOGE("enablePortAsync(%ld) failed (err = %d)", portIndex, err); + CODEC_LOGE("enablePortAsync(%u) failed (err = %d)", portIndex, err); setState(ERROR); } else { err = allocateBuffersOnPort(portIndex); @@ -2524,7 +2548,7 @@ void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) { case OMX_CommandPortEnable: { OMX_U32 portIndex = data; - CODEC_LOGV("PORT_ENABLED(%ld)", portIndex); + CODEC_LOGV("PORT_ENABLED(%u)", portIndex); CHECK(mState == EXECUTING || mState == RECONFIGURING); CHECK_EQ((int)mPortStatus[portIndex], (int)ENABLING); @@ -2545,7 +2569,7 @@ void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) { { OMX_U32 portIndex = data; - CODEC_LOGV("FLUSH_DONE(%ld)", portIndex); + CODEC_LOGV("FLUSH_DONE(%u)", portIndex); CHECK_EQ((int)mPortStatus[portIndex], (int)SHUTTING_DOWN); mPortStatus[portIndex] = ENABLED; @@ -3838,7 +3862,7 @@ status_t OMXCodec::read( return UNKNOWN_ERROR; } - CODEC_LOGV("seeking to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6); + CODEC_LOGV("seeking to %" PRId64 " us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6); mSignalledEOS = false; @@ -4177,9 +4201,9 @@ void OMXCodec::dumpPortStatus(OMX_U32 portIndex) { CHECK((portIndex == kPortIndexInput && def.eDir == OMX_DirInput) || (portIndex == kPortIndexOutput && def.eDir == OMX_DirOutput)); - printf(" nBufferCountActual = %ld\n", def.nBufferCountActual); - printf(" nBufferCountMin = %ld\n", def.nBufferCountMin); - printf(" nBufferSize = %ld\n", def.nBufferSize); + printf(" nBufferCountActual = %" PRIu32 "\n", def.nBufferCountActual); + printf(" nBufferCountMin = %" PRIu32 "\n", def.nBufferCountMin); + printf(" nBufferSize = %" PRIu32 "\n", def.nBufferSize); switch (def.eDomain) { case OMX_PortDomainImage: @@ -4188,9 +4212,9 @@ void OMXCodec::dumpPortStatus(OMX_U32 portIndex) { printf("\n"); printf(" // Image\n"); - printf(" nFrameWidth = %ld\n", imageDef->nFrameWidth); - printf(" nFrameHeight = %ld\n", imageDef->nFrameHeight); - printf(" nStride = %ld\n", imageDef->nStride); + printf(" nFrameWidth = %" PRIu32 "\n", imageDef->nFrameWidth); + printf(" nFrameHeight = %" PRIu32 "\n", imageDef->nFrameHeight); + printf(" nStride = %" PRIu32 "\n", imageDef->nStride); printf(" eCompressionFormat = %s\n", imageCompressionFormatString(imageDef->eCompressionFormat)); @@ -4207,9 +4231,9 @@ void OMXCodec::dumpPortStatus(OMX_U32 portIndex) { printf("\n"); printf(" // Video\n"); - printf(" nFrameWidth = %ld\n", videoDef->nFrameWidth); - printf(" nFrameHeight = %ld\n", videoDef->nFrameHeight); - printf(" nStride = %ld\n", videoDef->nStride); + printf(" nFrameWidth = %" PRIu32 "\n", videoDef->nFrameWidth); + printf(" nFrameHeight = %" PRIu32 "\n", videoDef->nFrameHeight); + printf(" nStride = %" PRIu32 "\n", videoDef->nStride); printf(" eCompressionFormat = %s\n", videoCompressionFormatString(videoDef->eCompressionFormat)); @@ -4238,10 +4262,10 @@ void OMXCodec::dumpPortStatus(OMX_U32 portIndex) { mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); CHECK_EQ(err, (status_t)OK); - printf(" nSamplingRate = %ld\n", params.nSamplingRate); - printf(" nChannels = %ld\n", params.nChannels); + printf(" nSamplingRate = %" PRIu32 "\n", params.nSamplingRate); + printf(" nChannels = %" PRIu32 "\n", params.nChannels); printf(" bInterleaved = %d\n", params.bInterleaved); - printf(" nBitPerSample = %ld\n", params.nBitPerSample); + printf(" nBitPerSample = %" PRIu32 "\n", params.nBitPerSample); printf(" eNumData = %s\n", params.eNumData == OMX_NumericalDataSigned @@ -4257,7 +4281,7 @@ void OMXCodec::dumpPortStatus(OMX_U32 portIndex) { mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr)); CHECK_EQ(err, (status_t)OK); - printf(" nChannels = %ld\n", amr.nChannels); + printf(" nChannels = %" PRIu32 "\n", amr.nChannels); printf(" eAMRBandMode = %s\n", amrBandModeString(amr.eAMRBandMode)); printf(" eAMRFrameFormat = %s\n", diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp index 5e79e78..1965ef9 100644 --- a/media/libstagefright/OggExtractor.cpp +++ b/media/libstagefright/OggExtractor.cpp @@ -151,7 +151,7 @@ sp<MetaData> OggSource::getFormat() { return mExtractor->mImpl->getFormat(); } -status_t OggSource::start(MetaData *params) { +status_t OggSource::start(MetaData * /* params */) { if (mStarted) { return INVALID_OPERATION; } @@ -320,22 +320,26 @@ status_t MyVorbisExtractor::seekToTime(int64_t timeUs) { } size_t left = 0; - size_t right = mTableOfContents.size(); - while (left < right) { - size_t center = left / 2 + right / 2 + (left & right & 1); + size_t right_plus_one = mTableOfContents.size(); + while (left < right_plus_one) { + size_t center = left + (right_plus_one - left) / 2; const TOCEntry &entry = mTableOfContents.itemAt(center); if (timeUs < entry.mTimeUs) { - right = center; + right_plus_one = center; } else if (timeUs > entry.mTimeUs) { left = center + 1; } else { - left = right = center; + left = center; break; } } + if (left == mTableOfContents.size()) { + --left; + } + const TOCEntry &entry = mTableOfContents.itemAt(left); ALOGV("seeking to entry %d / %d at offset %lld", @@ -381,7 +385,7 @@ ssize_t MyVorbisExtractor::readPage(off64_t offset, Page *page) { ssize_t n; if ((n = mSource->readAt(offset, header, sizeof(header))) < (ssize_t)sizeof(header)) { - ALOGV("failed to read %d bytes at offset 0x%016llx, got %ld bytes", + ALOGV("failed to read %zu bytes at offset 0x%016llx, got %d bytes", sizeof(header), offset, n); if (n < 0) { @@ -505,7 +509,7 @@ status_t MyVorbisExtractor::readNextPacket(MediaBuffer **out) { packetSize); if (n < (ssize_t)packetSize) { - ALOGV("failed to read %d bytes at 0x%016llx, got %ld bytes", + ALOGV("failed to read %zu bytes at 0x%016llx, got %d bytes", packetSize, dataOffset, n); return ERROR_IO; } @@ -546,7 +550,7 @@ status_t MyVorbisExtractor::readNextPacket(MediaBuffer **out) { buffer = NULL; } - ALOGV("readPage returned %ld", n); + ALOGV("readPage returned %d", n); return n < 0 ? n : (status_t)ERROR_END_OF_STREAM; } @@ -998,7 +1002,7 @@ sp<MediaSource> OggExtractor::getTrack(size_t index) { } sp<MetaData> OggExtractor::getTrackMetaData( - size_t index, uint32_t flags) { + size_t index, uint32_t /* flags */) { if (index >= 1) { return NULL; } diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp index d9858d7..318555e 100644 --- a/media/libstagefright/SampleTable.cpp +++ b/media/libstagefright/SampleTable.cpp @@ -520,83 +520,72 @@ void SampleTable::buildSampleEntriesTable() { } status_t SampleTable::findSampleAtTime( - uint32_t req_time, uint32_t *sample_index, uint32_t flags) { + uint64_t req_time, uint64_t scale_num, uint64_t scale_den, + uint32_t *sample_index, uint32_t flags) { buildSampleEntriesTable(); uint32_t left = 0; - uint32_t right = mNumSampleSizes; - while (left < right) { - uint32_t center = (left + right) / 2; - uint32_t centerTime = mSampleTimeEntries[center].mCompositionTime; + uint32_t right_plus_one = mNumSampleSizes; + while (left < right_plus_one) { + uint32_t center = left + (right_plus_one - left) / 2; + uint64_t centerTime = + getSampleTime(center, scale_num, scale_den); if (req_time < centerTime) { - right = center; + right_plus_one = center; } else if (req_time > centerTime) { left = center + 1; } else { - left = center; - break; + *sample_index = mSampleTimeEntries[center].mSampleIndex; + return OK; } } - if (left == mNumSampleSizes) { + uint32_t closestIndex = left; + + if (closestIndex == mNumSampleSizes) { if (flags == kFlagAfter) { return ERROR_OUT_OF_RANGE; } - - --left; + flags = kFlagBefore; + } else if (closestIndex == 0) { + if (flags == kFlagBefore) { + // normally we should return out of range, but that is + // treated as end-of-stream. instead return first sample + // + // return ERROR_OUT_OF_RANGE; + } + flags = kFlagAfter; } - uint32_t closestIndex = left; - switch (flags) { case kFlagBefore: { - while (closestIndex > 0 - && mSampleTimeEntries[closestIndex].mCompositionTime - > req_time) { - --closestIndex; - } + --closestIndex; break; } case kFlagAfter: { - while (closestIndex + 1 < mNumSampleSizes - && mSampleTimeEntries[closestIndex].mCompositionTime - < req_time) { - ++closestIndex; - } + // nothing to do break; } default: { CHECK(flags == kFlagClosest); - - if (closestIndex > 0) { - // Check left neighbour and pick closest. - uint32_t absdiff1 = - abs_difference( - mSampleTimeEntries[closestIndex].mCompositionTime, - req_time); - - uint32_t absdiff2 = - abs_difference( - mSampleTimeEntries[closestIndex - 1].mCompositionTime, - req_time); - - if (absdiff1 > absdiff2) { - closestIndex = closestIndex - 1; - } + // pick closest based on timestamp. use abs_difference for safety + if (abs_difference( + getSampleTime(closestIndex, scale_num, scale_den), req_time) > + abs_difference( + req_time, getSampleTime(closestIndex - 1, scale_num, scale_den))) { + --closestIndex; } - break; } } *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex; - return OK; } @@ -618,109 +607,85 @@ status_t SampleTable::findSyncSampleNear( } uint32_t left = 0; - uint32_t right = mNumSyncSamples; - while (left < right) { - uint32_t center = left + (right - left) / 2; + uint32_t right_plus_one = mNumSyncSamples; + while (left < right_plus_one) { + uint32_t center = left + (right_plus_one - left) / 2; uint32_t x = mSyncSamples[center]; if (start_sample_index < x) { - right = center; + right_plus_one = center; } else if (start_sample_index > x) { left = center + 1; } else { - left = center; - break; + *sample_index = x; + return OK; } } + if (left == mNumSyncSamples) { if (flags == kFlagAfter) { ALOGE("tried to find a sync frame after the last one: %d", left); return ERROR_OUT_OF_RANGE; } - left = left - 1; + flags = kFlagBefore; } + else if (left == 0) { + if (flags == kFlagBefore) { + ALOGE("tried to find a sync frame before the first one: %d", left); - // Now ssi[left] is the sync sample index just before (or at) - // start_sample_index. - // Also start_sample_index < ssi[left + 1], if left + 1 < mNumSyncSamples. - - uint32_t x = mSyncSamples[left]; - - if (left + 1 < mNumSyncSamples) { - uint32_t y = mSyncSamples[left + 1]; - - // our sample lies between sync samples x and y. - - status_t err = mSampleIterator->seekTo(start_sample_index); - if (err != OK) { - return err; - } - - uint32_t sample_time = mSampleIterator->getSampleTime(); - - err = mSampleIterator->seekTo(x); - if (err != OK) { - return err; - } - uint32_t x_time = mSampleIterator->getSampleTime(); - - err = mSampleIterator->seekTo(y); - if (err != OK) { - return err; - } - - uint32_t y_time = mSampleIterator->getSampleTime(); - - if (abs_difference(x_time, sample_time) - > abs_difference(y_time, sample_time)) { - // Pick the sync sample closest (timewise) to the start-sample. - x = y; - ++left; + // normally we should return out of range, but that is + // treated as end-of-stream. instead seek to first sync + // + // return ERROR_OUT_OF_RANGE; } + flags = kFlagAfter; } + // Now ssi[left - 1] <(=) start_sample_index <= ssi[left] switch (flags) { case kFlagBefore: { - if (x > start_sample_index) { - CHECK(left > 0); - - x = mSyncSamples[left - 1]; - - if (x > start_sample_index) { - // The table of sync sample indices was not sorted - // properly. - return ERROR_MALFORMED; - } - } + --left; break; } - case kFlagAfter: { - if (x < start_sample_index) { - if (left + 1 >= mNumSyncSamples) { - return ERROR_OUT_OF_RANGE; - } - - x = mSyncSamples[left + 1]; - - if (x < start_sample_index) { - // The table of sync sample indices was not sorted - // properly. - return ERROR_MALFORMED; - } - } - + // nothing to do break; } - default: + { + // this route is not used, but implement it nonetheless + CHECK(flags == kFlagClosest); + + status_t err = mSampleIterator->seekTo(start_sample_index); + if (err != OK) { + return err; + } + uint32_t sample_time = mSampleIterator->getSampleTime(); + + err = mSampleIterator->seekTo(mSyncSamples[left]); + if (err != OK) { + return err; + } + uint32_t upper_time = mSampleIterator->getSampleTime(); + + err = mSampleIterator->seekTo(mSyncSamples[left - 1]); + if (err != OK) { + return err; + } + uint32_t lower_time = mSampleIterator->getSampleTime(); + + // use abs_difference for safety + if (abs_difference(upper_time, sample_time) > + abs_difference(sample_time, lower_time)) { + --left; + } break; + } } - *sample_index = x; - + *sample_index = mSyncSamples[left]; return OK; } diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp index af8186c..f3fc3f6 100644 --- a/media/libstagefright/StagefrightMediaScanner.cpp +++ b/media/libstagefright/StagefrightMediaScanner.cpp @@ -117,7 +117,7 @@ MediaScanResult StagefrightMediaScanner::processFile( } MediaScanResult StagefrightMediaScanner::processFileInternal( - const char *path, const char *mimeType, + const char *path, const char * /* mimeType */, MediaScannerClient &client) { const char *extension = strrchr(path, '.'); @@ -202,7 +202,7 @@ MediaScanResult StagefrightMediaScanner::processFileInternal( return MEDIA_SCAN_RESULT_OK; } -char *StagefrightMediaScanner::extractAlbumArt(int fd) { +MediaAlbumArt *StagefrightMediaScanner::extractAlbumArt(int fd) { ALOGV("extractAlbumArt %d", fd); off64_t size = lseek64(fd, 0, SEEK_END); @@ -214,15 +214,9 @@ char *StagefrightMediaScanner::extractAlbumArt(int fd) { sp<MediaMetadataRetriever> mRetriever(new MediaMetadataRetriever); if (mRetriever->setDataSource(fd, 0, size) == OK) { sp<IMemory> mem = mRetriever->extractAlbumArt(); - if (mem != NULL) { MediaAlbumArt *art = static_cast<MediaAlbumArt *>(mem->pointer()); - - char *data = (char *)malloc(art->mSize + 4); - *(int32_t *)data = art->mSize; - memcpy(&data[4], &art[1], art->mSize); - - return data; + return art->clone(); } } diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp index 19af4fb..e4d3c79 100644 --- a/media/libstagefright/StagefrightMetadataRetriever.cpp +++ b/media/libstagefright/StagefrightMetadataRetriever.cpp @@ -16,6 +16,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "StagefrightMetadataRetriever" +#include <inttypes.h> #include <utils/Log.h> #include "include/StagefrightMetadataRetriever.h" @@ -374,10 +375,7 @@ VideoFrame *StagefrightMetadataRetriever::getFrameAtTime( size_t dataSize; if (fileMeta->findData(kKeyAlbumArt, &type, &data, &dataSize) && mAlbumArt == NULL) { - mAlbumArt = new MediaAlbumArt; - mAlbumArt->mSize = dataSize; - mAlbumArt->mData = new uint8_t[dataSize]; - memcpy(mAlbumArt->mData, data, dataSize); + mAlbumArt = MediaAlbumArt::fromData(dataSize, data); } VideoFrame *frame = @@ -410,7 +408,7 @@ MediaAlbumArt *StagefrightMetadataRetriever::extractAlbumArt() { } if (mAlbumArt) { - return new MediaAlbumArt(*mAlbumArt); + return mAlbumArt->clone(); } return NULL; @@ -479,16 +477,13 @@ void StagefrightMetadataRetriever::parseMetaData() { size_t dataSize; if (meta->findData(kKeyAlbumArt, &type, &data, &dataSize) && mAlbumArt == NULL) { - mAlbumArt = new MediaAlbumArt; - mAlbumArt->mSize = dataSize; - mAlbumArt->mData = new uint8_t[dataSize]; - memcpy(mAlbumArt->mData, data, dataSize); + mAlbumArt = MediaAlbumArt::fromData(dataSize, data); } size_t numTracks = mExtractor->countTracks(); char tmp[32]; - sprintf(tmp, "%d", numTracks); + sprintf(tmp, "%zu", numTracks); mMetaData.add(METADATA_KEY_NUM_TRACKS, String8(tmp)); @@ -545,7 +540,7 @@ void StagefrightMetadataRetriever::parseMetaData() { } // The duration value is a string representing the duration in ms. - sprintf(tmp, "%lld", (maxDurationUs + 500) / 1000); + sprintf(tmp, "%" PRId64, (maxDurationUs + 500) / 1000); mMetaData.add(METADATA_KEY_DURATION, String8(tmp)); if (hasAudio) { @@ -573,7 +568,7 @@ void StagefrightMetadataRetriever::parseMetaData() { if (mSource->getSize(&sourceSize) == OK) { int64_t avgBitRate = (int64_t)(sourceSize * 8E6 / maxDurationUs); - sprintf(tmp, "%lld", avgBitRate); + sprintf(tmp, "%" PRId64, avgBitRate); mMetaData.add(METADATA_KEY_BITRATE, String8(tmp)); } } diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp index 6b934d4..686d03a 100644 --- a/media/libstagefright/SurfaceMediaSource.cpp +++ b/media/libstagefright/SurfaceMediaSource.cpp @@ -99,8 +99,11 @@ void SurfaceMediaSource::dump(String8& result) const dump(result, "", buffer, 1024); } -void SurfaceMediaSource::dump(String8& result, const char* prefix, - char* buffer, size_t SIZE) const +void SurfaceMediaSource::dump( + String8& result, + const char* /* prefix */, + char* buffer, + size_t /* SIZE */) const { Mutex::Autolock lock(mMutex); @@ -269,9 +272,8 @@ static void passMetadataBuffer(MediaBuffer **buffer, bufferHandle, (*buffer)->range_length(), (*buffer)->range_offset()); } -status_t SurfaceMediaSource::read( MediaBuffer **buffer, - const ReadOptions *options) -{ +status_t SurfaceMediaSource::read( + MediaBuffer **buffer, const ReadOptions * /* options */) { ALOGV("read"); Mutex::Autolock lock(mMutex); diff --git a/media/libstagefright/TimedEventQueue.cpp b/media/libstagefright/TimedEventQueue.cpp index 1a9a26b..3d2eb1f 100644 --- a/media/libstagefright/TimedEventQueue.cpp +++ b/media/libstagefright/TimedEventQueue.cpp @@ -217,6 +217,7 @@ void TimedEventQueue::threadEntry() { for (;;) { int64_t now_us = 0; sp<Event> event; + bool wakeLocked = false; { Mutex::Autolock autoLock(mLock); @@ -283,26 +284,28 @@ void TimedEventQueue::threadEntry() { // removeEventFromQueue_l will return NULL. // Otherwise, the QueueItem will be removed // from the queue and the referenced event returned. - event = removeEventFromQueue_l(eventID); + event = removeEventFromQueue_l(eventID, &wakeLocked); } if (event != NULL) { // Fire event with the lock NOT held. event->fire(this, now_us); + if (wakeLocked) { + Mutex::Autolock autoLock(mLock); + releaseWakeLock_l(); + } } } } sp<TimedEventQueue::Event> TimedEventQueue::removeEventFromQueue_l( - event_id id) { + event_id id, bool *wakeLocked) { for (List<QueueItem>::iterator it = mQueue.begin(); it != mQueue.end(); ++it) { if ((*it).event->eventID() == id) { sp<Event> event = (*it).event; event->setEventID(0); - if ((*it).has_wakelock) { - releaseWakeLock_l(); - } + *wakeLocked = (*it).has_wakelock; mQueue.erase(it); return event; } @@ -315,7 +318,7 @@ sp<TimedEventQueue::Event> TimedEventQueue::removeEventFromQueue_l( void TimedEventQueue::acquireWakeLock_l() { - if (mWakeLockCount++ == 0) { + if (mWakeLockCount == 0) { CHECK(mWakeLockToken == 0); if (mPowerManager == 0) { // use checkService() to avoid blocking if power service is not up yet @@ -338,21 +341,23 @@ void TimedEventQueue::acquireWakeLock_l() IPCThreadState::self()->restoreCallingIdentity(token); if (status == NO_ERROR) { mWakeLockToken = binder; + mWakeLockCount++; } } + } else { + mWakeLockCount++; } } void TimedEventQueue::releaseWakeLock_l(bool force) { + if (mWakeLockCount == 0) { + return; + } if (force) { - if (mWakeLockCount == 0) { - return; - } // Force wakelock release below by setting reference count to 1. mWakeLockCount = 1; } - CHECK(mWakeLockCount != 0); if (--mWakeLockCount == 0) { CHECK(mWakeLockToken != 0); if (mPowerManager != 0) { @@ -371,8 +376,8 @@ void TimedEventQueue::clearPowerManager() mPowerManager.clear(); } -void TimedEventQueue::PMDeathRecipient::binderDied(const wp<IBinder>& who) -{ +void TimedEventQueue::PMDeathRecipient::binderDied( + const wp<IBinder>& /* who */) { mQueue->clearPowerManager(); } diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp index 9041c21..216a329 100644 --- a/media/libstagefright/Utils.cpp +++ b/media/libstagefright/Utils.cpp @@ -562,6 +562,17 @@ bool canOffloadStream(const sp<MetaData>& meta, bool hasVideo, return false; } + // check whether it is ELD/LD content -> no offloading + // FIXME: this should depend on audio DSP capabilities. mapMimeToAudioFormat() should use the + // metadata to refine the AAC format and the audio HAL should only list supported profiles. + int32_t aacaot = -1; + if (meta->findInt32(kKeyAACAOT, &aacaot)) { + if (aacaot == 23 || aacaot == 39 ) { + ALOGV("track of type '%s' is ELD/LD content", mime); + return false; + } + } + int32_t srate = -1; if (!meta->findInt32(kKeySampleRate, &srate)) { ALOGV("track of type '%s' does not publish sample rate", mime); diff --git a/media/libstagefright/VBRISeeker.cpp b/media/libstagefright/VBRISeeker.cpp index a245f2c..af858b9 100644 --- a/media/libstagefright/VBRISeeker.cpp +++ b/media/libstagefright/VBRISeeker.cpp @@ -119,7 +119,7 @@ sp<VBRISeeker> VBRISeeker::CreateFromSource( seeker->mSegments.push(numBytes); - ALOGV("entry #%d: %d offset 0x%08lx", i, numBytes, offset); + ALOGV("entry #%d: %u offset 0x%016llx", i, numBytes, offset); offset += numBytes; } @@ -160,7 +160,7 @@ bool VBRISeeker::getOffsetForTime(int64_t *timeUs, off64_t *pos) { *pos += mSegments.itemAt(segmentIndex++); } - ALOGV("getOffsetForTime %lld us => 0x%08lx", *timeUs, *pos); + ALOGV("getOffsetForTime %lld us => 0x%016llx", *timeUs, *pos); *timeUs = nowUs; diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp index 22af6fb..fe9058b 100644 --- a/media/libstagefright/WAVExtractor.cpp +++ b/media/libstagefright/WAVExtractor.cpp @@ -127,7 +127,7 @@ sp<MediaSource> WAVExtractor::getTrack(size_t index) { } sp<MetaData> WAVExtractor::getTrackMetaData( - size_t index, uint32_t flags) { + size_t index, uint32_t /* flags */) { if (mInitCheck != OK || index > 0) { return NULL; } @@ -358,7 +358,7 @@ WAVSource::~WAVSource() { } } -status_t WAVSource::start(MetaData *params) { +status_t WAVSource::start(MetaData * /* params */) { ALOGV("WAVSource::start"); CHECK(!mStarted); diff --git a/media/libstagefright/avc_utils.cpp b/media/libstagefright/avc_utils.cpp index b822868..c6ac0da 100644 --- a/media/libstagefright/avc_utils.cpp +++ b/media/libstagefright/avc_utils.cpp @@ -251,9 +251,7 @@ status_t getNextNALUnit( return OK; } -static sp<ABuffer> FindNAL( - const uint8_t *data, size_t size, unsigned nalType, - size_t *stopOffset) { +static sp<ABuffer> FindNAL(const uint8_t *data, size_t size, unsigned nalType) { const uint8_t *nalStart; size_t nalSize; while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) { @@ -293,7 +291,7 @@ sp<MetaData> MakeAVCCodecSpecificData(const sp<ABuffer> &accessUnit) { const uint8_t *data = accessUnit->data(); size_t size = accessUnit->size(); - sp<ABuffer> seqParamSet = FindNAL(data, size, 7, NULL); + sp<ABuffer> seqParamSet = FindNAL(data, size, 7); if (seqParamSet == NULL) { return NULL; } @@ -303,8 +301,7 @@ sp<MetaData> MakeAVCCodecSpecificData(const sp<ABuffer> &accessUnit) { FindAVCDimensions( seqParamSet, &width, &height, &sarWidth, &sarHeight); - size_t stopOffset; - sp<ABuffer> picParamSet = FindNAL(data, size, 8, &stopOffset); + sp<ABuffer> picParamSet = FindNAL(data, size, 8); CHECK(picParamSet != NULL); size_t csdSize = diff --git a/media/libstagefright/chromium_http/Android.mk b/media/libstagefright/chromium_http/Android.mk index f26f386..109e3fe 100644 --- a/media/libstagefright/chromium_http/Android.mk +++ b/media/libstagefright/chromium_http/Android.mk @@ -18,9 +18,11 @@ LOCAL_C_INCLUDES:= \ LOCAL_CFLAGS += -Wno-multichar LOCAL_SHARED_LIBRARIES += \ + libbinder \ libstlport \ libchromium_net \ libutils \ + libbinder \ libcutils \ liblog \ libstagefright_foundation \ diff --git a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp index a862d8b..7e5c280 100644 --- a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp +++ b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp @@ -108,6 +108,11 @@ status_t ChromiumHTTPDataSource::connect_l( return mState == CONNECTED ? OK : mIOResult; } +void ChromiumHTTPDataSource::onRedirect(const char *url) { + Mutex::Autolock autoLock(mLock); + mURI = url; +} + void ChromiumHTTPDataSource::onConnectionEstablished( int64_t contentSize, const char *contentType) { Mutex::Autolock autoLock(mLock); diff --git a/media/libstagefright/chromium_http/support.cpp b/media/libstagefright/chromium_http/support.cpp index 0a8e3e3..09c87be 100644 --- a/media/libstagefright/chromium_http/support.cpp +++ b/media/libstagefright/chromium_http/support.cpp @@ -34,14 +34,97 @@ #include "net/proxy/proxy_config_service_android.h" #include "include/ChromiumHTTPDataSource.h" - +#include <arpa/inet.h> +#include <binder/Parcel.h> #include <cutils/log.h> #include <media/stagefright/MediaErrors.h> #include <media/stagefright/Utils.h> #include <string> +#include <utils/Errors.h> +#include <binder/IInterface.h> +#include <binder/IServiceManager.h> + namespace android { +// must be kept in sync with interface defined in IAudioService.aidl +class IAudioService : public IInterface +{ +public: + DECLARE_META_INTERFACE(AudioService); + + virtual int verifyX509CertChain( + const std::vector<std::string>& cert_chain, + const std::string& hostname, + const std::string& auth_type) = 0; +}; + +class BpAudioService : public BpInterface<IAudioService> +{ +public: + BpAudioService(const sp<IBinder>& impl) + : BpInterface<IAudioService>(impl) + { + } + + virtual int verifyX509CertChain( + const std::vector<std::string>& cert_chain, + const std::string& hostname, + const std::string& auth_type) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioService::getInterfaceDescriptor()); + + // The vector of std::string we get isn't really a vector of strings, + // but rather a vector of binary certificate data. If we try to pass + // it to Java language code as a string, it ends up mangled on the other + // side, so send them as bytes instead. + // Since we can't send an array of byte arrays, send a single array, + // which will be split out by the recipient. + + int numcerts = cert_chain.size(); + data.writeInt32(numcerts); + size_t total = 0; + for (int i = 0; i < numcerts; i++) { + total += cert_chain[i].size(); + } + size_t bytesize = total + numcerts * 4; + uint8_t *bytes = (uint8_t*) malloc(bytesize); + if (!bytes) { + return 5; // SSL_INVALID + } + ALOGV("%d certs: %d -> %d", numcerts, total, bytesize); + + int offset = 0; + for (int i = 0; i < numcerts; i++) { + int32_t certsize = cert_chain[i].size(); + // store this in a known order, which just happens to match the default + // byte order of a java ByteBuffer + int32_t bigsize = htonl(certsize); + ALOGV("cert %d, size %d", i, certsize); + memcpy(bytes + offset, &bigsize, sizeof(bigsize)); + offset += sizeof(bigsize); + memcpy(bytes + offset, cert_chain[i].data(), certsize); + offset += certsize; + } + data.writeByteArray(bytesize, bytes); + free(bytes); + data.writeString16(String16(hostname.c_str())); + data.writeString16(String16(auth_type.c_str())); + + int32_t result; + if (remote()->transact(IBinder::FIRST_CALL_TRANSACTION, data, &reply) != NO_ERROR + || reply.readExceptionCode() < 0 || reply.readInt32(&result) != NO_ERROR) { + return 5; // SSL_INVALID; + } + return result; + } + +}; + +IMPLEMENT_META_INTERFACE(AudioService, "android.media.IAudioService"); + + static Mutex gNetworkThreadLock; static base::Thread *gNetworkThread = NULL; static scoped_refptr<SfRequestContext> gReqContext; @@ -76,7 +159,7 @@ bool logMessageHandler( struct AutoPrioritySaver { AutoPrioritySaver() - : mTID(androidGetTid()), + : mTID(gettid()), mPrevPriority(androidGetThreadPriority(mTID)) { androidSetThreadPriority(mTID, ANDROID_PRIORITY_NORMAL); } @@ -226,7 +309,24 @@ SfNetworkLibrary::VerifyResult SfNetworkLibrary::VerifyX509CertChain( const std::vector<std::string>& cert_chain, const std::string& hostname, const std::string& auth_type) { - return VERIFY_OK; + + sp<IBinder> binder = + defaultServiceManager()->checkService(String16("audio")); + if (binder == 0) { + ALOGW("Thread cannot connect to the audio service"); + } else { + sp<IAudioService> service = interface_cast<IAudioService>(binder); + int code = service->verifyX509CertChain(cert_chain, hostname, auth_type); + ALOGV("verified: %d", code); + if (code == -1) { + return VERIFY_OK; + } else if (code == 2) { // SSL_IDMISMATCH + return VERIFY_BAD_HOSTNAME; + } else if (code == 3) { // SSL_UNTRUSTED + return VERIFY_NO_TRUSTED_ROOT; + } + } + return VERIFY_INVOCATION_ERROR; } //////////////////////////////////////////////////////////////////////////////// @@ -269,6 +369,7 @@ bool SfDelegate::getUID(uid_t *uid) const { void SfDelegate::OnReceivedRedirect( net::URLRequest *request, const GURL &new_url, bool *defer_redirect) { MY_LOGV("OnReceivedRedirect"); + mOwner->onRedirect(new_url.spec().c_str()); } void SfDelegate::OnAuthRequired( diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp index 1b20cbb..d4b0de7 100644 --- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp +++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp @@ -58,6 +58,8 @@ SoftAAC2::SoftAAC2( mIsADTS(false), mInputBufferCount(0), mSignalledError(false), + mSawInputEos(false), + mSignalledOutputEos(false), mAnchorTimeUs(0), mNumSamplesOutput(0), mOutputPortSettingsChange(NONE) { @@ -350,115 +352,83 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) { return; } - while (!inQueue.empty() && !outQueue.empty()) { - BufferInfo *inInfo = *inQueue.begin(); - OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; + while ((!inQueue.empty() || (mSawInputEos && !mSignalledOutputEos)) && !outQueue.empty()) { + BufferInfo *inInfo = NULL; + OMX_BUFFERHEADERTYPE *inHeader = NULL; + if (!inQueue.empty()) { + inInfo = *inQueue.begin(); + inHeader = inInfo->mHeader; + } BufferInfo *outInfo = *outQueue.begin(); OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; + outHeader->nFlags = 0; - if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { - inQueue.erase(inQueue.begin()); - inInfo->mOwnedByUs = false; - notifyEmptyBufferDone(inHeader); - - if (mDecoderHasData) { - // flush out the decoder's delayed data by calling DecodeFrame - // one more time, with the AACDEC_FLUSH flag set - INT_PCM *outBuffer = - reinterpret_cast<INT_PCM *>( - outHeader->pBuffer + outHeader->nOffset); - - AAC_DECODER_ERROR decoderErr = - aacDecoder_DecodeFrame(mAACDecoder, - outBuffer, - outHeader->nAllocLen, - AACDEC_FLUSH); - mDecoderHasData = false; - - if (decoderErr != AAC_DEC_OK) { - mSignalledError = true; - - notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, - NULL); - - return; - } - - outHeader->nFilledLen = - mStreamInfo->frameSize - * sizeof(int16_t) - * mStreamInfo->numChannels; - } else { - // we never submitted any data to the decoder, so there's nothing to flush out - outHeader->nFilledLen = 0; + if (inHeader) { + if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { + mSawInputEos = true; } - outHeader->nFlags = OMX_BUFFERFLAG_EOS; - - outQueue.erase(outQueue.begin()); - outInfo->mOwnedByUs = false; - notifyFillBufferDone(outHeader); - return; - } - - if (inHeader->nOffset == 0) { - mAnchorTimeUs = inHeader->nTimeStamp; - mNumSamplesOutput = 0; - } + if (inHeader->nOffset == 0 && inHeader->nFilledLen) { + mAnchorTimeUs = inHeader->nTimeStamp; + mNumSamplesOutput = 0; + } - size_t adtsHeaderSize = 0; - if (mIsADTS) { - // skip 30 bits, aac_frame_length follows. - // ssssssss ssssiiip ppffffPc ccohCCll llllllll lll????? + if (mIsADTS) { + size_t adtsHeaderSize = 0; + // skip 30 bits, aac_frame_length follows. + // ssssssss ssssiiip ppffffPc ccohCCll llllllll lll????? - const uint8_t *adtsHeader = inHeader->pBuffer + inHeader->nOffset; + const uint8_t *adtsHeader = inHeader->pBuffer + inHeader->nOffset; - bool signalError = false; - if (inHeader->nFilledLen < 7) { - ALOGE("Audio data too short to contain even the ADTS header. " - "Got %ld bytes.", inHeader->nFilledLen); - hexdump(adtsHeader, inHeader->nFilledLen); - signalError = true; - } else { - bool protectionAbsent = (adtsHeader[1] & 1); - - unsigned aac_frame_length = - ((adtsHeader[3] & 3) << 11) - | (adtsHeader[4] << 3) - | (adtsHeader[5] >> 5); - - if (inHeader->nFilledLen < aac_frame_length) { - ALOGE("Not enough audio data for the complete frame. " - "Got %ld bytes, frame size according to the ADTS " - "header is %u bytes.", - inHeader->nFilledLen, aac_frame_length); + bool signalError = false; + if (inHeader->nFilledLen < 7) { + ALOGE("Audio data too short to contain even the ADTS header. " + "Got %d bytes.", inHeader->nFilledLen); hexdump(adtsHeader, inHeader->nFilledLen); signalError = true; } else { - adtsHeaderSize = (protectionAbsent ? 7 : 9); - - inBuffer[0] = (UCHAR *)adtsHeader + adtsHeaderSize; - inBufferLength[0] = aac_frame_length - adtsHeaderSize; - - inHeader->nOffset += adtsHeaderSize; - inHeader->nFilledLen -= adtsHeaderSize; + bool protectionAbsent = (adtsHeader[1] & 1); + + unsigned aac_frame_length = + ((adtsHeader[3] & 3) << 11) + | (adtsHeader[4] << 3) + | (adtsHeader[5] >> 5); + + if (inHeader->nFilledLen < aac_frame_length) { + ALOGE("Not enough audio data for the complete frame. " + "Got %d bytes, frame size according to the ADTS " + "header is %u bytes.", + inHeader->nFilledLen, aac_frame_length); + hexdump(adtsHeader, inHeader->nFilledLen); + signalError = true; + } else { + adtsHeaderSize = (protectionAbsent ? 7 : 9); + + inBuffer[0] = (UCHAR *)adtsHeader + adtsHeaderSize; + inBufferLength[0] = aac_frame_length - adtsHeaderSize; + + inHeader->nOffset += adtsHeaderSize; + inHeader->nFilledLen -= adtsHeaderSize; + } } - } - if (signalError) { - mSignalledError = true; + if (signalError) { + mSignalledError = true; - notify(OMX_EventError, - OMX_ErrorStreamCorrupt, - ERROR_MALFORMED, - NULL); + notify(OMX_EventError, + OMX_ErrorStreamCorrupt, + ERROR_MALFORMED, + NULL); - return; + return; + } + } else { + inBuffer[0] = inHeader->pBuffer + inHeader->nOffset; + inBufferLength[0] = inHeader->nFilledLen; } } else { - inBuffer[0] = inHeader->pBuffer + inHeader->nOffset; - inBufferLength[0] = inHeader->nFilledLen; + inBufferLength[0] = 0; } // Fill and decode @@ -471,50 +441,66 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) { int prevNumChannels = mStreamInfo->numChannels; AAC_DECODER_ERROR decoderErr = AAC_DEC_NOT_ENOUGH_BITS; - while (bytesValid[0] > 0 && decoderErr == AAC_DEC_NOT_ENOUGH_BITS) { + while ((bytesValid[0] > 0 || mSawInputEos) && decoderErr == AAC_DEC_NOT_ENOUGH_BITS) { + mDecoderHasData |= (bytesValid[0] > 0); aacDecoder_Fill(mAACDecoder, inBuffer, inBufferLength, bytesValid); - mDecoderHasData = true; decoderErr = aacDecoder_DecodeFrame(mAACDecoder, outBuffer, outHeader->nAllocLen, 0 /* flags */); - if (decoderErr == AAC_DEC_NOT_ENOUGH_BITS) { - ALOGW("Not enough bits, bytesValid %d", bytesValid[0]); + if (mSawInputEos && bytesValid[0] <= 0) { + if (mDecoderHasData) { + // flush out the decoder's delayed data by calling DecodeFrame + // one more time, with the AACDEC_FLUSH flag set + decoderErr = aacDecoder_DecodeFrame(mAACDecoder, + outBuffer, + outHeader->nAllocLen, + AACDEC_FLUSH); + mDecoderHasData = false; + } + outHeader->nFlags = OMX_BUFFERFLAG_EOS; + mSignalledOutputEos = true; + break; + } else { + ALOGW("Not enough bits, bytesValid %d", bytesValid[0]); + } } } size_t numOutBytes = mStreamInfo->frameSize * sizeof(int16_t) * mStreamInfo->numChannels; - if (decoderErr == AAC_DEC_OK) { - UINT inBufferUsedLength = inBufferLength[0] - bytesValid[0]; - inHeader->nFilledLen -= inBufferUsedLength; - inHeader->nOffset += inBufferUsedLength; - } else { - ALOGW("AAC decoder returned error %d, substituting silence", - decoderErr); + if (inHeader) { + if (decoderErr == AAC_DEC_OK) { + UINT inBufferUsedLength = inBufferLength[0] - bytesValid[0]; + inHeader->nFilledLen -= inBufferUsedLength; + inHeader->nOffset += inBufferUsedLength; + } else { + ALOGW("AAC decoder returned error %d, substituting silence", + decoderErr); - memset(outHeader->pBuffer + outHeader->nOffset, 0, numOutBytes); + memset(outHeader->pBuffer + outHeader->nOffset, 0, numOutBytes); - // Discard input buffer. - inHeader->nFilledLen = 0; + // Discard input buffer. + inHeader->nFilledLen = 0; - aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1); + aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1); - // fall through - } + // fall through + } - if (inHeader->nFilledLen == 0) { - inInfo->mOwnedByUs = false; - inQueue.erase(inQueue.begin()); - inInfo = NULL; - notifyEmptyBufferDone(inHeader); - inHeader = NULL; + if (inHeader->nFilledLen == 0) { + inInfo->mOwnedByUs = false; + inQueue.erase(inQueue.begin()); + inInfo = NULL; + notifyEmptyBufferDone(inHeader); + inHeader = NULL; + } } /* @@ -555,7 +541,6 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) { // we've previously decoded valid data, in the latter case // (decode failed) we'll output a silent frame. outHeader->nFilledLen = numOutBytes; - outHeader->nFlags = 0; outHeader->nTimeStamp = mAnchorTimeUs @@ -582,6 +567,12 @@ void SoftAAC2::onPortFlushCompleted(OMX_U32 portIndex) { // depend on fragments from the last one decoded. // drain all existing data drainDecoder(); + // force decoder loop to drop the first decoded buffer by resetting these state variables, + // but only if initialization has already happened. + if (mInputBufferCount != 0) { + mInputBufferCount = 1; + mStreamInfo->sampleRate = 0; + } } } @@ -606,6 +597,8 @@ void SoftAAC2::onReset() { mStreamInfo->sampleRate = 0; mSignalledError = false; + mSawInputEos = false; + mSignalledOutputEos = false; mOutputPortSettingsChange = NONE; } diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.h b/media/libstagefright/codecs/aacdec/SoftAAC2.h index 2d960ab..a7ea1e2 100644 --- a/media/libstagefright/codecs/aacdec/SoftAAC2.h +++ b/media/libstagefright/codecs/aacdec/SoftAAC2.h @@ -55,6 +55,8 @@ private: bool mDecoderHasData; size_t mInputBufferCount; bool mSignalledError; + bool mSawInputEos; + bool mSignalledOutputEos; int64_t mAnchorTimeUs; int64_t mNumSamplesOutput; diff --git a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp index ff2b503..6093621 100644 --- a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp +++ b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp @@ -308,7 +308,7 @@ status_t SoftAACEncoder2::setAudioParams() { // We call this whenever sample rate, number of channels or bitrate change // in reponse to setParameter calls. - ALOGV("setAudioParams: %lu Hz, %lu channels, %lu bps", + ALOGV("setAudioParams: %u Hz, %u channels, %u bps", mSampleRate, mNumChannels, mBitRate); if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_AOT, @@ -338,7 +338,7 @@ status_t SoftAACEncoder2::setAudioParams() { return OK; } -void SoftAACEncoder2::onQueueFilled(OMX_U32 portIndex) { +void SoftAACEncoder2::onQueueFilled(OMX_U32 /* portIndex */) { if (mSignalledError) { return; } @@ -364,7 +364,7 @@ void SoftAACEncoder2::onQueueFilled(OMX_U32 portIndex) { OMX_U32 actualBitRate = aacEncoder_GetParam(mAACEncoder, AACENC_BITRATE); if (mBitRate != actualBitRate) { - ALOGW("Requested bitrate %lu unsupported, using %lu", mBitRate, actualBitRate); + ALOGW("Requested bitrate %u unsupported, using %u", mBitRate, actualBitRate); } AACENC_InfoStruct encInfo; diff --git a/media/libstagefright/codecs/aacenc/src/adj_thr.c b/media/libstagefright/codecs/aacenc/src/adj_thr.c index ccfe883..471631c 100644 --- a/media/libstagefright/codecs/aacenc/src/adj_thr.c +++ b/media/libstagefright/codecs/aacenc/src/adj_thr.c @@ -72,7 +72,7 @@ static void calcThreshExp(Word32 thrExp[MAX_CHANNELS][MAX_GROUPED_SFB], const Word16 nChannels) { Word16 ch, sfb, sfbGrp; - Word32 *pthrExp, *psfbThre; + Word32 *pthrExp = NULL, *psfbThre; for (ch=0; ch<nChannels; ch++) { PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch]; for(sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt; sfbGrp+= psyOutChan->sfbPerGroup) diff --git a/media/libstagefright/codecs/aacenc/src/dyn_bits.c b/media/libstagefright/codecs/aacenc/src/dyn_bits.c index 7769188..4d763d0 100644 --- a/media/libstagefright/codecs/aacenc/src/dyn_bits.c +++ b/media/libstagefright/codecs/aacenc/src/dyn_bits.c @@ -25,7 +25,6 @@ #include "bit_cnt.h" #include "psy_const.h" - /***************************************************************************** * * function name: buildBitLookUp @@ -226,7 +225,7 @@ gmStage2(SECTION_INFO *sectionInfo, } while (TRUE) { - Word16 maxMergeGain, maxNdx, maxNdxNext, maxNdxLast; + Word16 maxMergeGain, maxNdx = 0, maxNdxNext, maxNdxLast; maxMergeGain = findMaxMerge(mergeGainLookUp, sectionInfo, maxSfb, &maxNdx); diff --git a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp index 3320688..d1b0f76 100644 --- a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp +++ b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp @@ -274,7 +274,7 @@ static size_t getFrameSize(unsigned FT) { return frameSize; } -void SoftAMR::onQueueFilled(OMX_U32 portIndex) { +void SoftAMR::onQueueFilled(OMX_U32 /* portIndex */) { List<BufferInfo *> &inQueue = getPortQueue(0); List<BufferInfo *> &outQueue = getPortQueue(1); @@ -428,7 +428,7 @@ void SoftAMR::onQueueFilled(OMX_U32 portIndex) { } } -void SoftAMR::onPortFlushCompleted(OMX_U32 portIndex) { +void SoftAMR::onPortFlushCompleted(OMX_U32 /* portIndex */) { } void SoftAMR::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) { diff --git a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp index 50b739c..9489457 100644 --- a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp +++ b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp @@ -270,7 +270,7 @@ OMX_ERRORTYPE SoftAMRNBEncoder::internalSetParameter( } } -void SoftAMRNBEncoder::onQueueFilled(OMX_U32 portIndex) { +void SoftAMRNBEncoder::onQueueFilled(OMX_U32 /* portIndex */) { if (mSignalledError) { return; } diff --git a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp index 9ccb49c..91a512d 100644 --- a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp +++ b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp @@ -317,7 +317,7 @@ OMX_ERRORTYPE SoftAMRWBEncoder::internalSetParameter( } } -void SoftAMRWBEncoder::onQueueFilled(OMX_U32 portIndex) { +void SoftAMRWBEncoder::onQueueFilled(OMX_U32 /* portIndex */) { if (mSignalledError) { return; } diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Filt_6k_7k_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Filt_6k_7k_opt.s index 8451195..f23b5a0 100644 --- a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Filt_6k_7k_opt.s +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Filt_6k_7k_opt.s @@ -29,6 +29,7 @@ .global Filt_6k_7k_asm .extern voAWB_Copy .extern fir_6k_7k + .hidden fir_6k_7k Filt_6k_7k_asm: diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/pred_lt4_1_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/pred_lt4_1_opt.s index ac2dd13..deb7efc 100644 --- a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/pred_lt4_1_opt.s +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/pred_lt4_1_opt.s @@ -32,6 +32,7 @@ .section .text .global pred_lt4_asm .extern inter4_2 + .hidden inter4_2 pred_lt4_asm: diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Filt_6k_7k_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Filt_6k_7k_neon.s index fc42a03..8df0caa 100644 --- a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Filt_6k_7k_neon.s +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Filt_6k_7k_neon.s @@ -28,6 +28,7 @@ .section .text .global Filt_6k_7k_asm .extern fir_6k_7k + .hidden fir_6k_7k Filt_6k_7k_asm: diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/pred_lt4_1_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/pred_lt4_1_neon.s index 8d2aaf2..67be1ed 100644 --- a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/pred_lt4_1_neon.s +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/pred_lt4_1_neon.s @@ -29,6 +29,7 @@ .section .text .global pred_lt4_asm .extern inter4_2 + .hidden inter4_2 pred_lt4_asm: diff --git a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp index 4a21a3e..27c63c3 100644 --- a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp +++ b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp @@ -217,7 +217,7 @@ OMX_ERRORTYPE SoftAVCEncoder::initEncParams() { mHandle->CBAVC_Free = FreeWrapper; CHECK(mEncParams != NULL); - memset(mEncParams, 0, sizeof(mEncParams)); + memset(mEncParams, 0, sizeof(*mEncParams)); mEncParams->rate_control = AVC_ON; mEncParams->initQP = 0; mEncParams->init_CBP_removal_delay = 1600; @@ -342,10 +342,10 @@ OMX_ERRORTYPE SoftAVCEncoder::releaseEncoder() { PVAVCCleanUpEncoder(mHandle); releaseOutputBuffers(); - delete mInputFrameData; + free(mInputFrameData); mInputFrameData = NULL; - delete mSliceGroup; + free(mSliceGroup); mSliceGroup = NULL; delete mEncParams; @@ -593,6 +593,17 @@ OMX_ERRORTYPE SoftAVCEncoder::internalSetParameter( mVideoHeight = def->format.video.nFrameHeight; mVideoFrameRate = def->format.video.xFramerate >> 16; mVideoColorFormat = def->format.video.eColorFormat; + + OMX_PARAM_PORTDEFINITIONTYPE *portDef = + &editPortInfo(0)->mDef; + portDef->format.video.nFrameWidth = mVideoWidth; + portDef->format.video.nFrameHeight = mVideoHeight; + portDef->format.video.xFramerate = def->format.video.xFramerate; + portDef->format.video.eColorFormat = + (OMX_COLOR_FORMATTYPE) mVideoColorFormat; + portDef = &editPortInfo(1)->mDef; + portDef->format.video.nFrameWidth = mVideoWidth; + portDef->format.video.nFrameHeight = mVideoHeight; } else { mVideoBitRate = def->format.video.nBitrate; } @@ -808,9 +819,10 @@ void SoftAVCEncoder::onQueueFilled(OMX_U32 portIndex) { videoInput.coding_timestamp = (inHeader->nTimeStamp + 500) / 1000; // in ms uint8_t *inputData = NULL; if (mStoreMetaDataInBuffers) { - if (inHeader->nFilledLen != 8) { + if (inHeader->nFilledLen != (sizeof(OMX_U32) + sizeof(buffer_handle_t))) { ALOGE("MetaData buffer is wrong size! " - "(got %lu bytes, expected 8)", inHeader->nFilledLen); + "(got %u bytes, expected %d)", inHeader->nFilledLen, + sizeof(OMX_U32) + sizeof(buffer_handle_t)); mSignalledError = true; notify(OMX_EventError, OMX_ErrorUndefined, 0, 0); return; @@ -970,11 +982,11 @@ uint8_t *SoftAVCEncoder::extractGrallocData(void *data, buffer_handle_t *buffer) status_t res; if (type != kMetadataBufferTypeGrallocSource) { ALOGE("Data passed in with metadata mode does not have type " - "kMetadataBufferTypeGrallocSource (%d), has type %ld instead", + "kMetadataBufferTypeGrallocSource (%d), has type %d instead", kMetadataBufferTypeGrallocSource, type); return NULL; } - buffer_handle_t imgBuffer = *(buffer_handle_t*)((uint8_t*)data + 4); + buffer_handle_t imgBuffer = *(buffer_handle_t*)((uint8_t*)data + sizeof(OMX_U32)); const Rect rect(mVideoWidth, mVideoHeight); uint8_t *img; diff --git a/media/libstagefright/codecs/avc/enc/src/bitstream_io.cpp b/media/libstagefright/codecs/avc/enc/src/bitstream_io.cpp index 0e3037f..d71c327 100644 --- a/media/libstagefright/codecs/avc/enc/src/bitstream_io.cpp +++ b/media/libstagefright/codecs/avc/enc/src/bitstream_io.cpp @@ -103,6 +103,15 @@ AVCEnc_Status AVCBitstreamSaveWord(AVCEncBitstream *stream) { num_bits -= 8; byte = (current_word >> num_bits) & 0xFF; + if (stream->count_zeros == 2) + { /* for num_bits = 32, this can add 2 more bytes extra for EPBS */ + if (byte <= 3) + { + *write_pnt++ = 0x3; + stream->write_pos++; + stream->count_zeros = 0; + } + } if (byte != 0) { *write_pnt++ = byte; @@ -114,12 +123,6 @@ AVCEnc_Status AVCBitstreamSaveWord(AVCEncBitstream *stream) stream->count_zeros++; *write_pnt++ = byte; stream->write_pos++; - if (stream->count_zeros == 2) - { /* for num_bits = 32, this can add 2 more bytes extra for EPBS */ - *write_pnt++ = 0x3; - stream->write_pos++; - stream->count_zeros = 0; - } } } diff --git a/media/libstagefright/codecs/common/Config.mk b/media/libstagefright/codecs/common/Config.mk index a6d4286..a843cef 100644 --- a/media/libstagefright/codecs/common/Config.mk +++ b/media/libstagefright/codecs/common/Config.mk @@ -14,8 +14,10 @@ VOTT := pc endif # Do we also need to check on ARCH_ARM_HAVE_ARMV7A? - probably not -ifeq ($(ARCH_ARM_HAVE_NEON),true) -VOTT := v7 +ifeq ($(TARGET_ARCH),arm) + ifeq ($(ARCH_ARM_HAVE_NEON),true) + VOTT := v7 + endif endif VOTEST := 0 diff --git a/media/libstagefright/codecs/common/cmnMemory.c b/media/libstagefright/codecs/common/cmnMemory.c index aa52bd9..5bb6cc4 100644 --- a/media/libstagefright/codecs/common/cmnMemory.c +++ b/media/libstagefright/codecs/common/cmnMemory.c @@ -26,8 +26,12 @@ //VO_MEM_OPERATOR g_memOP; +#define UNUSED(x) (void)(x) + VO_U32 cmnMemAlloc (VO_S32 uID, VO_MEM_INFO * pMemInfo) { + UNUSED(uID); + if (!pMemInfo) return VO_ERR_INVALID_ARG; @@ -37,34 +41,48 @@ VO_U32 cmnMemAlloc (VO_S32 uID, VO_MEM_INFO * pMemInfo) VO_U32 cmnMemFree (VO_S32 uID, VO_PTR pMem) { + UNUSED(uID); + free (pMem); return 0; } VO_U32 cmnMemSet (VO_S32 uID, VO_PTR pBuff, VO_U8 uValue, VO_U32 uSize) { + UNUSED(uID); + memset (pBuff, uValue, uSize); return 0; } VO_U32 cmnMemCopy (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize) { + UNUSED(uID); + memcpy (pDest, pSource, uSize); return 0; } VO_U32 cmnMemCheck (VO_S32 uID, VO_PTR pBuffer, VO_U32 uSize) { + UNUSED(uID); + UNUSED(pBuffer); + UNUSED(uSize); + return 0; } VO_S32 cmnMemCompare (VO_S32 uID, VO_PTR pBuffer1, VO_PTR pBuffer2, VO_U32 uSize) { + UNUSED(uID); + return memcmp(pBuffer1, pBuffer2, uSize); } VO_U32 cmnMemMove (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize) { + UNUSED(uID); + memmove (pDest, pSource, uSize); return 0; } diff --git a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp index e64fe72..d797197 100644 --- a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp +++ b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp @@ -204,7 +204,7 @@ OMX_ERRORTYPE SoftFlacEncoder::internalSetParameter( mNumChannels = pcmParams->nChannels; mSampleRate = pcmParams->nSamplingRate; - ALOGV("will encode %ld channels at %ldHz", mNumChannels, mSampleRate); + ALOGV("will encode %d channels at %dHz", mNumChannels, mSampleRate); return configureEncoder(); } @@ -241,7 +241,7 @@ OMX_ERRORTYPE SoftFlacEncoder::internalSetParameter( if (defParams->nPortIndex == 0) { if (defParams->nBufferSize > kMaxInputBufferSize) { - ALOGE("Input buffer size must be at most %zu bytes", + ALOGE("Input buffer size must be at most %d bytes", kMaxInputBufferSize); return OMX_ErrorUnsupportedSetting; } @@ -257,8 +257,8 @@ OMX_ERRORTYPE SoftFlacEncoder::internalSetParameter( } void SoftFlacEncoder::onQueueFilled(OMX_U32 portIndex) { - - ALOGV("SoftFlacEncoder::onQueueFilled(portIndex=%ld)", portIndex); + //UNUSED_UNLESS_VERBOSE(portIndex); + ALOGV("SoftFlacEncoder::onQueueFilled(portIndex=%d)", portIndex); if (mSignalledError) { return; @@ -290,7 +290,7 @@ void SoftFlacEncoder::onQueueFilled(OMX_U32 portIndex) { } if (inHeader->nFilledLen > kMaxInputBufferSize) { - ALOGE("input buffer too large (%ld).", inHeader->nFilledLen); + ALOGE("input buffer too large (%d).", inHeader->nFilledLen); mSignalledError = true; notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); return; @@ -363,7 +363,7 @@ FLAC__StreamEncoderWriteStatus SoftFlacEncoder::onEncodedFlacAvailable( if ((samples == 0) || !mEncoderWriteData) { // called by the encoder because there's header data to save, but it's not the role // of this component (unless WRITE_FLAC_HEADER_IN_FIRST_BUFFER is defined) - ALOGV("ignoring %d bytes of header data (samples=%d)", bytes, samples); + ALOGV("ignoring %zu bytes of header data (samples=%d)", bytes, samples); return FLAC__STREAM_ENCODER_WRITE_STATUS_OK; } @@ -384,9 +384,9 @@ FLAC__StreamEncoderWriteStatus SoftFlacEncoder::onEncodedFlacAvailable( #endif // write encoded data - ALOGV(" writing %d bytes of encoded data on output port", bytes); + ALOGV(" writing %zu bytes of encoded data on output port", bytes); if (bytes > outHeader->nAllocLen - outHeader->nOffset - outHeader->nFilledLen) { - ALOGE(" not enough space left to write encoded data, dropping %u bytes", bytes); + ALOGE(" not enough space left to write encoded data, dropping %zu bytes", bytes); // a fatal error would stop the encoding return FLAC__STREAM_ENCODER_WRITE_STATUS_OK; } @@ -405,7 +405,7 @@ FLAC__StreamEncoderWriteStatus SoftFlacEncoder::onEncodedFlacAvailable( OMX_ERRORTYPE SoftFlacEncoder::configureEncoder() { - ALOGV("SoftFlacEncoder::configureEncoder() numChannel=%ld, sampleRate=%ld", + ALOGV("SoftFlacEncoder::configureEncoder() numChannel=%d, sampleRate=%d", mNumChannels, mSampleRate); if (mSignalledError || (mFlacStreamEncoder == NULL)) { diff --git a/media/libstagefright/codecs/g711/dec/SoftG711.cpp b/media/libstagefright/codecs/g711/dec/SoftG711.cpp index bcdd3c7..240c0c1 100644 --- a/media/libstagefright/codecs/g711/dec/SoftG711.cpp +++ b/media/libstagefright/codecs/g711/dec/SoftG711.cpp @@ -182,7 +182,7 @@ OMX_ERRORTYPE SoftG711::internalSetParameter( } } -void SoftG711::onQueueFilled(OMX_U32 portIndex) { +void SoftG711::onQueueFilled(OMX_U32 /* portIndex */) { if (mSignalledError) { return; } @@ -212,7 +212,7 @@ void SoftG711::onQueueFilled(OMX_U32 portIndex) { } if (inHeader->nFilledLen > kMaxNumSamplesPerFrame) { - ALOGE("input buffer too large (%ld).", inHeader->nFilledLen); + ALOGE("input buffer too large (%d).", inHeader->nFilledLen); notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); mSignalledError = true; diff --git a/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp b/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp index 00e0c85..4debc48 100644 --- a/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp +++ b/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp @@ -172,7 +172,7 @@ OMX_ERRORTYPE SoftGSM::internalSetParameter( } } -void SoftGSM::onQueueFilled(OMX_U32 portIndex) { +void SoftGSM::onQueueFilled(OMX_U32 /* portIndex */) { if (mSignalledError) { return; } @@ -202,13 +202,13 @@ void SoftGSM::onQueueFilled(OMX_U32 portIndex) { } if (inHeader->nFilledLen > kMaxNumSamplesPerFrame) { - ALOGE("input buffer too large (%ld).", inHeader->nFilledLen); + ALOGE("input buffer too large (%d).", inHeader->nFilledLen); notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); mSignalledError = true; } if(((inHeader->nFilledLen / 65) * 65) != inHeader->nFilledLen) { - ALOGE("input buffer not multiple of 65 (%ld).", inHeader->nFilledLen); + ALOGE("input buffer not multiple of 65 (%d).", inHeader->nFilledLen); notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); mSignalledError = true; } diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp index fb2a430..0d1ab71 100644 --- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp +++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp @@ -91,7 +91,7 @@ status_t SoftMPEG4::initDecoder() { return OK; } -void SoftMPEG4::onQueueFilled(OMX_U32 portIndex) { +void SoftMPEG4::onQueueFilled(OMX_U32 /* portIndex */) { if (mSignalledError || mOutputPortSettingsChange != NONE) { return; } diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/get_pred_adv_b_add.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/get_pred_adv_b_add.cpp index e23f23d..fe9e7dc 100644 --- a/media/libstagefright/codecs/m4v_h263/dec/src/get_pred_adv_b_add.cpp +++ b/media/libstagefright/codecs/m4v_h263/dec/src/get_pred_adv_b_add.cpp @@ -96,7 +96,7 @@ int GetPredAdvancedBy0x0( offset = width - B_SIZE; /* offset for prev */ offset2 = (pred_width_rnd >> 1) - 4; /* offset for pred_block */ - tmp = (uint32)prev & 0x3; + tmp = (uintptr_t)prev & 0x3; pred_block -= offset2; /* preset */ if (tmp == 0) /* word-aligned */ @@ -203,7 +203,7 @@ int GetPredAdvancedBy0x1( /* Branch based on pixel location (half-pel or full-pel) for x and y */ pred_block -= offset2; /* preset */ - tmp = (uint32)prev & 3; + tmp = (uintptr_t)prev & 3; mask = 254; mask |= (mask << 8); mask |= (mask << 16); /* 0xFEFEFEFE */ @@ -532,7 +532,7 @@ int GetPredAdvancedBy1x0( /* Branch based on pixel location (half-pel or full-pel) for x and y */ pred_block -= offset2; /* preset */ - tmp = (uint32)prev & 3; + tmp = (uintptr_t)prev & 3; mask = 254; mask |= (mask << 8); mask |= (mask << 16); /* 0xFEFEFEFE */ @@ -884,7 +884,7 @@ int GetPredAdvancedBy1x1( mask |= (mask << 8); mask |= (mask << 16); /* 0x3f3f3f3f */ - tmp = (uint32)prev & 3; + tmp = (uintptr_t)prev & 3; pred_block -= 4; /* preset */ diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp index e02af90..bf77f4a 100644 --- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp +++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp @@ -33,6 +33,8 @@ #include "SoftMPEG4Encoder.h" +#include <inttypes.h> + namespace android { template<class T> @@ -620,7 +622,7 @@ OMX_ERRORTYPE SoftMPEG4Encoder::internalSetParameter( } } -void SoftMPEG4Encoder::onQueueFilled(OMX_U32 portIndex) { +void SoftMPEG4Encoder::onQueueFilled(OMX_U32 /* portIndex */) { if (mSignalledError || mSawInputEOS) { return; } @@ -683,7 +685,7 @@ void SoftMPEG4Encoder::onQueueFilled(OMX_U32 portIndex) { if (mStoreMetaDataInBuffers) { if (inHeader->nFilledLen != 8) { ALOGE("MetaData buffer is wrong size! " - "(got %lu bytes, expected 8)", inHeader->nFilledLen); + "(got %u bytes, expected 8)", inHeader->nFilledLen); mSignalledError = true; notify(OMX_EventError, OMX_ErrorUndefined, 0, 0); return; @@ -719,13 +721,13 @@ void SoftMPEG4Encoder::onQueueFilled(OMX_U32 portIndex) { vin.uChan = vin.yChan + vin.height * vin.pitch; vin.vChan = vin.uChan + ((vin.height * vin.pitch) >> 2); - unsigned long modTimeMs = 0; + ULong modTimeMs = 0; int32_t nLayer = 0; MP4HintTrack hintTrack; if (!PVEncodeVideoFrame(mHandle, &vin, &vout, &modTimeMs, outPtr, &dataLength, &nLayer) || !PVGetHintTrack(mHandle, &hintTrack)) { - ALOGE("Failed to encode frame or get hink track at frame %lld", + ALOGE("Failed to encode frame or get hink track at frame %" PRId64, mNumInputFrames); mSignalledError = true; notify(OMX_EventError, OMX_ErrorUndefined, 0, 0); @@ -771,7 +773,7 @@ uint8_t *SoftMPEG4Encoder::extractGrallocData(void *data, buffer_handle_t *buffe status_t res; if (type != kMetadataBufferTypeGrallocSource) { ALOGE("Data passed in with metadata mode does not have type " - "kMetadataBufferTypeGrallocSource (%d), has type %ld instead", + "kMetadataBufferTypeGrallocSource (%d), has type %d instead", kMetadataBufferTypeGrallocSource, type); return NULL; } diff --git a/media/libstagefright/codecs/m4v_h263/enc/include/mp4enc_api.h b/media/libstagefright/codecs/m4v_h263/enc/include/mp4enc_api.h index a54fd8b..9451479 100644 --- a/media/libstagefright/codecs/m4v_h263/enc/include/mp4enc_api.h +++ b/media/libstagefright/codecs/m4v_h263/enc/include/mp4enc_api.h @@ -29,7 +29,7 @@ typedef int Int; typedef unsigned short UShort; typedef short Short; typedef unsigned int Bool; -typedef unsigned long ULong; +typedef uint32_t ULong; #define PV_CODEC_INIT 0 #define PV_CODEC_STOP 1 diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/dct.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/dct.cpp index fa50eeb..fa4ae23 100644 --- a/media/libstagefright/codecs/m4v_h263/enc/src/dct.cpp +++ b/media/libstagefright/codecs/m4v_h263/enc/src/dct.cpp @@ -250,7 +250,7 @@ extern "C" out[40] = k4 ; /* row 5 */ out++; } - while ((UInt)out < (UInt)dst) ; + while ((uintptr_t)out < (uintptr_t)dst) ; return ; } @@ -455,7 +455,7 @@ extern "C" out[8] = k5 ; /* row 1 */ out++; } - while ((UInt)out < (UInt)dst) ; + while ((uintptr_t)out < (uintptr_t)dst) ; return ; } @@ -635,7 +635,7 @@ extern "C" out[8] = k5 ; /* row 1 */ out++; } - while ((UInt)out < (UInt)dst) ; + while ((uintptr_t)out < (uintptr_t)dst) ; return ; } @@ -846,7 +846,7 @@ extern "C" out[40] = k4 ; /* row 5 */ out++; } - while ((UInt)out < (UInt)dst) ; + while ((uintptr_t)out < (uintptr_t)dst) ; return ; } @@ -1033,7 +1033,7 @@ extern "C" out[8] = k5 ; /* row 1 */ out++; } - while ((UInt)out < (UInt)dst) ; + while ((uintptr_t)out < (uintptr_t)dst) ; return ; } @@ -1195,7 +1195,7 @@ extern "C" out[8] = k5 ; /* row 1 */ out++; } - while ((UInt)out < (UInt)dst) ; + while ((uintptr_t)out < (uintptr_t)dst) ; return ; } diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.cpp index 6fd41c3..0ad39a6 100644 --- a/media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.cpp +++ b/media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.cpp @@ -572,7 +572,7 @@ Int Sad8x8(UChar *cur, UChar *prev, Int width) cur2 = cur2 & (mask << 8); /* mask first and third bytes */ sum2 = sum2 + ((UInt)cur2 >> 8); } - while ((UInt)curInt < (UInt)end); + while ((uintptr_t)curInt < (uintptr_t)end); cur1 = sum4 - (sum2 << 8); /* get even-sum */ cur1 = cur1 + sum2; /* add 16 bit even-sum and odd-sum*/ @@ -611,7 +611,7 @@ Int getBlockSum(UChar *cur, Int width) load2 = load2 & (mask << 8); /* even bytes */ sum2 += ((UInt)load2 >> 8); /* sum even bytes, 16 bit */ } - while ((UInt)curInt < (UInt)end); + while ((uintptr_t)curInt < (uintptr_t)end); load1 = sum4 - (sum2 << 8); /* get even-sum */ load1 = load1 + sum2; /* add 16 bit even-sum and odd-sum*/ load1 = load1 + (load1 << 16); /* add upper and lower 16 bit sum */ diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/motion_comp.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/motion_comp.cpp index b81d278..9a967c2 100644 --- a/media/libstagefright/codecs/m4v_h263/enc/src/motion_comp.cpp +++ b/media/libstagefright/codecs/m4v_h263/enc/src/motion_comp.cpp @@ -363,7 +363,7 @@ Int GetPredAdvBy0x0( /* initialize offset to adjust pixel counter */ /* the next row; full-pel resolution */ - tmp = (ULong)prev & 0x3; + tmp = (uintptr_t)prev & 0x3; if (tmp == 0) /* word-aligned */ { @@ -466,7 +466,7 @@ Int GetPredAdvBy0x1( /* Branch based on pixel location (half-pel or full-pel) for x and y */ rec -= 12; /* preset */ - tmp = (ULong)prev & 3; + tmp = (uintptr_t)prev & 3; mask = 254; mask |= (mask << 8); mask |= (mask << 16); /* 0xFEFEFEFE */ @@ -791,7 +791,7 @@ Int GetPredAdvBy1x0( /* Branch based on pixel location (half-pel or full-pel) for x and y */ rec -= 12; /* preset */ - tmp = (ULong)prev & 3; + tmp = (uintptr_t)prev & 3; mask = 254; mask |= (mask << 8); mask |= (mask << 16); /* 0xFEFEFEFE */ @@ -1140,7 +1140,7 @@ Int GetPredAdvBy1x1( mask |= (mask << 8); mask |= (mask << 16); /* 0x3f3f3f3f */ - tmp = (ULong)prev & 3; + tmp = (uintptr_t)prev & 3; rec -= 4; /* preset */ @@ -1959,7 +1959,7 @@ void PutSkippedBlock(UChar *rec, UChar *prev, Int lx) dst += offset; src += offset; } - while ((UInt)src < (UInt)end); + while ((uintptr_t)src < (uintptr_t)end); return ; } diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/mp4def.h b/media/libstagefright/codecs/m4v_h263/enc/src/mp4def.h index 0d5a3e8..2d44482 100644 --- a/media/libstagefright/codecs/m4v_h263/enc/src/mp4def.h +++ b/media/libstagefright/codecs/m4v_h263/enc/src/mp4def.h @@ -60,7 +60,7 @@ typedef unsigned short UShort; typedef short Short; typedef short int SInt; typedef unsigned int Bool; -typedef unsigned long ULong; +typedef uint32_t ULong; typedef void Void; #define PV_CODEC_INIT 0 diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/sad_inline.h b/media/libstagefright/codecs/m4v_h263/enc/src/sad_inline.h index ba77dfd..b865f23 100644 --- a/media/libstagefright/codecs/m4v_h263/enc/src/sad_inline.h +++ b/media/libstagefright/codecs/m4v_h263/enc/src/sad_inline.h @@ -85,7 +85,7 @@ extern "C" x9 = 0x80808080; /* const. */ - x8 = (uint32)ref & 0x3; + x8 = (uintptr_t)ref & 0x3; if (x8 == 3) goto SadMBOffset3; if (x8 == 2) diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp index 7c382fb..4d864df 100644 --- a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp +++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp @@ -49,6 +49,8 @@ SoftMP3::SoftMP3( mNumChannels(2), mSamplingRate(44100), mSignalledError(false), + mSawInputEos(false), + mSignalledOutputEos(false), mOutputPortSettingsChange(NONE) { initPorts(); initDecoder(); @@ -186,7 +188,7 @@ OMX_ERRORTYPE SoftMP3::internalSetParameter( } } -void SoftMP3::onQueueFilled(OMX_U32 portIndex) { +void SoftMP3::onQueueFilled(OMX_U32 /* portIndex */) { if (mSignalledError || mOutputPortSettingsChange != NONE) { return; } @@ -194,48 +196,36 @@ void SoftMP3::onQueueFilled(OMX_U32 portIndex) { List<BufferInfo *> &inQueue = getPortQueue(0); List<BufferInfo *> &outQueue = getPortQueue(1); - while (!inQueue.empty() && !outQueue.empty()) { - BufferInfo *inInfo = *inQueue.begin(); - OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; + while ((!inQueue.empty() || (mSawInputEos && !mSignalledOutputEos)) && !outQueue.empty()) { + BufferInfo *inInfo = NULL; + OMX_BUFFERHEADERTYPE *inHeader = NULL; + if (!inQueue.empty()) { + inInfo = *inQueue.begin(); + inHeader = inInfo->mHeader; + } BufferInfo *outInfo = *outQueue.begin(); OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; + outHeader->nFlags = 0; - if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { - inQueue.erase(inQueue.begin()); - inInfo->mOwnedByUs = false; - notifyEmptyBufferDone(inHeader); - - if (!mIsFirst) { - // pad the end of the stream with 529 samples, since that many samples - // were trimmed off the beginning when decoding started - outHeader->nFilledLen = - kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t); + if (inHeader) { + if (inHeader->nOffset == 0 && inHeader->nFilledLen) { + mAnchorTimeUs = inHeader->nTimeStamp; + mNumFramesOutput = 0; + } - memset(outHeader->pBuffer, 0, outHeader->nFilledLen); - } else { - // Since we never discarded frames from the start, we won't have - // to add any padding at the end either. - outHeader->nFilledLen = 0; + if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { + mSawInputEos = true; } - outHeader->nFlags = OMX_BUFFERFLAG_EOS; + mConfig->pInputBuffer = + inHeader->pBuffer + inHeader->nOffset; - outQueue.erase(outQueue.begin()); - outInfo->mOwnedByUs = false; - notifyFillBufferDone(outHeader); - return; - } - - if (inHeader->nOffset == 0) { - mAnchorTimeUs = inHeader->nTimeStamp; - mNumFramesOutput = 0; + mConfig->inputBufferCurrentLength = inHeader->nFilledLen; + } else { + mConfig->pInputBuffer = NULL; + mConfig->inputBufferCurrentLength = 0; } - - mConfig->pInputBuffer = - inHeader->pBuffer + inHeader->nOffset; - - mConfig->inputBufferCurrentLength = inHeader->nFilledLen; mConfig->inputBufferMaxLength = 0; mConfig->inputBufferUsedLength = 0; @@ -262,13 +252,28 @@ void SoftMP3::onQueueFilled(OMX_U32 portIndex) { mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t); } - // This is recoverable, just ignore the current frame and - // play silence instead. - memset(outHeader->pBuffer, - 0, - mConfig->outputFrameSize * sizeof(int16_t)); - - mConfig->inputBufferUsedLength = inHeader->nFilledLen; + if (decoderErr == NO_ENOUGH_MAIN_DATA_ERROR && mSawInputEos) { + if (!mIsFirst) { + // pad the end of the stream with 529 samples, since that many samples + // were trimmed off the beginning when decoding started + outHeader->nOffset = 0; + outHeader->nFilledLen = kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t); + + memset(outHeader->pBuffer, 0, outHeader->nFilledLen); + } + outHeader->nFlags = OMX_BUFFERFLAG_EOS; + mSignalledOutputEos = true; + } else { + // This is recoverable, just ignore the current frame and + // play silence instead. + memset(outHeader->pBuffer, + 0, + mConfig->outputFrameSize * sizeof(int16_t)); + + if (inHeader) { + mConfig->inputBufferUsedLength = inHeader->nFilledLen; + } + } } else if (mConfig->samplingRate != mSamplingRate || mConfig->num_channels != mNumChannels) { mSamplingRate = mConfig->samplingRate; @@ -289,7 +294,7 @@ void SoftMP3::onQueueFilled(OMX_U32 portIndex) { outHeader->nFilledLen = mConfig->outputFrameSize * sizeof(int16_t) - outHeader->nOffset; - } else { + } else if (!mSignalledOutputEos) { outHeader->nOffset = 0; outHeader->nFilledLen = mConfig->outputFrameSize * sizeof(int16_t); } @@ -298,23 +303,24 @@ void SoftMP3::onQueueFilled(OMX_U32 portIndex) { mAnchorTimeUs + (mNumFramesOutput * 1000000ll) / mConfig->samplingRate; - outHeader->nFlags = 0; - - CHECK_GE(inHeader->nFilledLen, mConfig->inputBufferUsedLength); + if (inHeader) { + CHECK_GE(inHeader->nFilledLen, mConfig->inputBufferUsedLength); - inHeader->nOffset += mConfig->inputBufferUsedLength; - inHeader->nFilledLen -= mConfig->inputBufferUsedLength; + inHeader->nOffset += mConfig->inputBufferUsedLength; + inHeader->nFilledLen -= mConfig->inputBufferUsedLength; - mNumFramesOutput += mConfig->outputFrameSize / mNumChannels; - if (inHeader->nFilledLen == 0) { - inInfo->mOwnedByUs = false; - inQueue.erase(inQueue.begin()); - inInfo = NULL; - notifyEmptyBufferDone(inHeader); - inHeader = NULL; + if (inHeader->nFilledLen == 0) { + inInfo->mOwnedByUs = false; + inQueue.erase(inQueue.begin()); + inInfo = NULL; + notifyEmptyBufferDone(inHeader); + inHeader = NULL; + } } + mNumFramesOutput += mConfig->outputFrameSize / mNumChannels; + outInfo->mOwnedByUs = false; outQueue.erase(outQueue.begin()); outInfo = NULL; @@ -362,6 +368,8 @@ void SoftMP3::onReset() { pvmp3_InitDecoder(mConfig, mDecoderBuf); mIsFirst = true; mSignalledError = false; + mSawInputEos = false; + mSignalledOutputEos = false; mOutputPortSettingsChange = NONE; } diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.h b/media/libstagefright/codecs/mp3dec/SoftMP3.h index 4af91ea..f9e7b53 100644 --- a/media/libstagefright/codecs/mp3dec/SoftMP3.h +++ b/media/libstagefright/codecs/mp3dec/SoftMP3.h @@ -61,6 +61,8 @@ private: bool mIsFirst; bool mSignalledError; + bool mSawInputEos; + bool mSignalledOutputEos; enum { NONE, diff --git a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_dct_9_arm.s b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_dct_9_arm.s deleted file mode 100644 index 3a6dd4f..0000000 --- a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_dct_9_arm.s +++ /dev/null @@ -1,210 +0,0 @@ -; ------------------------------------------------------------------ -; Copyright (C) 1998-2009 PacketVideo -; -; Licensed under the Apache License, Version 2.0 (the "License"); -; you may not use this file except in compliance with the License. -; You may obtain a copy of the License at -; -; http://www.apache.org/licenses/LICENSE-2.0 -; -; Unless required by applicable law or agreed to in writing, software -; distributed under the License is distributed on an "AS IS" BASIS, -; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -; express or implied. -; See the License for the specific language governing permissions -; and limitations under the License. -; ------------------------------------------------------------------- - -; -; -; Filename: pvmp3_dct_9.s -; -;------------------------------------------------------------------------------ -; REVISION HISTORY -; -; -; Who: Date: MM/DD/YYYY -; Description: -; -;------------------------------------------------------------------------------ - - AREA |.drectve|, DRECTVE - - DCB "-defaultlib:coredll.lib " - DCB "-defaultlib:corelibc.lib " - - IMPORT pvmp3_mdct_18 ; pvmp3_mdct_18.cpp - -;------------------------------------------------------------------------------ - - AREA |.rdata|, DATA, READONLY - % 4 - - -;------------------------------------------------------------------------------ - - AREA |.text|, CODE, READONLY - - -;------------------------------------------------------------------------------ - - EXPORT |pvmp3_dct_9| - -|pvmp3_dct_9| PROC - stmfd sp!,{r4-r10,lr} - ldr r2, [r0, #0x20] - ldr r3, [r0] - ldr r12,[r0, #4] - add r1,r2,r3 - sub lr,r2,r3 - ldr r3,[r0, #0x1c] - ldr r4,[r0, #0x18] - add r2,r3,r12 - ldr r5,[r0,#8] - sub r3,r3,r12 - add r12,r4,r5 - sub r4,r4,r5 - ldr r5,[r0, #0x14] - ldr r7,[r0, #0xc] - ldr r9,[r0, #0x10] - add r6,r5,r7 - sub r5,r5,r7 - add r7,r1,r12 - add r8,r9,r2 - add r7,r7,r6 - add r10,r7,r8 - rsb r7,r8,r7,asr #1 - str r7,[r0, #0x18] - rsb r2,r9,r2,asr #1 - str r10,[r0] - ldr r11,|cos_2pi_9| - rsb r7,r2,#0 - - mov r9,r1,lsl #1 - mov r1,r9 ;;;;;; !!!!!! - mov r8,r7 - -; vec[4] = fxp_mac32_Q32( vec[4], tmp0<<1, cos_2pi_9); - - smlal r1,r8,r11,r9 - ldr r10,|cos_4pi_9| - ldr r11,|cos_pi_9| - -; vec[8] = fxp_mac32_Q32( vec[8], tmp0<<1, cos_4pi_9); - - smlal r1,r7,r10,r9 - - - -; vec[2] = fxp_mac32_Q32( vec[2], tmp0<<1, cos_pi_9); - - smlal r9,r2,r11,r9 - mov r1,r12,lsl #1 - rsb r9,r10,#0 - ldr r11,|cos_5pi_9| - - smlal r12,r2,r9,r1 - - - -; vec[2] = fxp_mac32_Q32( vec[2], tmp2<<1, cos_5pi_9); - - ldr r9,|cos_2pi_9| - mov r12,r1 ;;;;;; !!!!!! - smlal r12,r8,r11,r1 - - -; vec[8] = fxp_mac32_Q32( vec[8], tmp2<<1, cos_2pi_9); - - smlal r1,r7,r9,r1 - mov r1,r6,lsl #1 - smlal r12,r7,r11,r1 - and r6,r10,r11,asr #14 - smlal r12,r8,r6,r1 - ldr r10,|cos_11pi_18| - add r12,r11,r6 - smlal r1,r2,r12,r1 - ldr r9,|cos_8pi_9| - str r2,[r0,#8] - mov r1,r5,lsl #1 - -; vec[8] = fxp_mac32_Q32( vec[8], tmp3<<1, cos_8pi_9); - - smull r2,r6,r9,r1 - str r7,[r0,#0x20] - mov r2,r4,lsl #1 - ldr r7,|cos_13pi_18| - smlal r12,r6,r10,r2 - - mov r3,r3,lsl #1 - -; vec[5] = fxp_mac32_Q32( vec[5], tmp8<<1, cos_13pi_18); - - smlal r12,r6,r7,r3 - add r4,r5,r4 - mov r12,lr,lsl #1 - sub lr,r4,lr - ldr r7,|cos_17pi_18| - str r8,[r0, #0x10] - ldr r4,|cos_pi_6| - - mov lr,lr,lsl #1 - -; vec[1] = fxp_mac32_Q32( vec[1], tmp8<<1, cos_17pi_18); - - smlal r8,r6,r7,r12 - -; vec[3] = fxp_mul32_Q32((tmp5 + tmp6 - tmp8)<<1, cos_pi_6); - - smull r5,lr,r4,lr - str r6,[r0, #4] - str lr,[r0, #0xc] - - -; vec[5] = fxp_mul32_Q32(tmp5<<1, cos_17pi_18); - smull r5,lr,r7,r1 - rsb r6,r9,#0 -; vec[5] = fxp_mac32_Q32( vec[5], tmp6<<1, cos_7pi_18); - smlal r5,lr,r6,r2 -; vec[5] = fxp_mac32_Q32( vec[5], tmp7<<1, cos_pi_6); - smlal r5,lr,r4,r3 -; vec[5] = fxp_mac32_Q32( vec[5], tmp8<<1, cos_13pi_18); - smlal r5,lr,r10,r12 - str lr,[r0, #0x14] - rsb lr,r10,#0 - -; vec[7] = fxp_mul32_Q32(tmp5<<1, cos_5pi_18); - smull r5,r1,lr,r1 -; vec[7] = fxp_mac32_Q32( vec[7], tmp6<<1, cos_17pi_18); - smlal r2,r1,r7,r2 -; vec[7] = fxp_mac32_Q32( vec[7], tmp7<<1, cos_pi_6); - smlal r3,r1,r4,r3 -; vec[7] = fxp_mac32_Q32( vec[7], tmp8<<1, cos_11pi_18); - smlal r12,r1,r9,r12 - str r1,[r0, #0x1c] - ldmfd sp!,{r4-r10,pc} -|cos_2pi_9| - DCD 0x620dbe80 -|cos_4pi_9| - DCD 0x163a1a80 -|cos_pi_9| - DCD 0x7847d900 -|cos_5pi_9| - DCD 0x87b82700 -|cos_8pi_9| - DCD 0xd438af00 -|cos_11pi_18| - DCD 0xadb92280 -|cos_13pi_18| - DCD 0x91261480 -|cos_17pi_18| - DCD 0x81f1d200 -|cos_pi_6| - DCD 0x6ed9eb80 - ENDP - - - - - - END diff --git a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_arm.s b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_arm.s deleted file mode 100644 index 9401d8c..0000000 --- a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_arm.s +++ /dev/null @@ -1,369 +0,0 @@ -; ------------------------------------------------------------------ -; Copyright (C) 1998-2009 PacketVideo -; -; Licensed under the Apache License, Version 2.0 (the "License"); -; you may not use this file except in compliance with the License. -; You may obtain a copy of the License at -; -; http://www.apache.org/licenses/LICENSE-2.0 -; -; Unless required by applicable law or agreed to in writing, software -; distributed under the License is distributed on an "AS IS" BASIS, -; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -; express or implied. -; See the License for the specific language governing permissions -; and limitations under the License. -; ------------------------------------------------------------------- - -; -; -; Filename: pvmp3_dct_18.s -; -;------------------------------------------------------------------------------ -; REVISION HISTORY -; -; -; Who: Date: MM/DD/YYYY -; Description: -; -;------------------------------------------------------------------------------ - - EXPORT pvmp3_mdct_18 - - IMPORT ||Lib$$Request$$armlib|| [WEAK] - IMPORT ||Lib$$Request$$cpplib|| [WEAK] - IMPORT pvmp3_dct_9 - - -;------------------------------------------------------------------------------ - - AREA |.text|, CODE, READONLY, ALIGN=2 - - -;------------------------------------------------------------------------------ - -|pvmp3_mdct_18| PROC - stmfd sp!,{r4-r10,lr} - mov r7,r2 - ldr r2,table - mov r6,r1 - add r3,r2,#0x24 - add r12,r3,#0x44 - add r1,r0,#0x44 - mov r5,r0 - -; for ( i=9; i!=0; i--) -; { - - mov r4,#9 -Loop_1 - -; tmp = *(pt_vec); -; tmp1 = *(pt_vec_o); - - ldr lr,[r0] ;; tmp == lr - ldr r8,[r3],#4 ;; tmp1 == r8 - -; tmp = fxp_mul32_Q32( tmp<<1, *(pt_cos++ )); -; tmp1 = fxp_mul32_Q27( tmp1, *(pt_cos_x--)); - - mov lr,lr,lsl #1 - smull r10,lr,r8,lr - ldr r8,[r12],#-4 - ldr r9,[r1] - subs r4,r4,#1 - smull r9,r10,r8,r9 - mov r8,r9,lsr #27 - add r8,r8,r10,lsl #5 - -; *(pt_vec++) = tmp + tmp1 ; -; *(pt_vec_o--) = fxp_mul32_Q28( (tmp - tmp1), *(pt_cos_split++)); - - add r9,lr,r8 - sub r8,lr,r8 - ldr lr,[r2],#4 - str r9,[r0],#4 - smull r8,r9,lr,r8 - mov lr,r8,lsr #28 - add lr,lr,r9,lsl #4 - str lr,[r1],#-4 - bne Loop_1 - -; } - - mov r0,r5 ;; r0 = vec - bl pvmp3_dct_9 - add r0,r5,#0x24 ;; r0 = &vec[9] - bl pvmp3_dct_9 - - ldr r0,[r5,#0x20] - ldr r2,[r5,#0x40] - str r0,[r5,#0x40] - ldr r0,[r5,#0x1c] - ldr r3,[r5,#0x38] - str r0,[r5,#0x38] - ldr r1,[r5,#0x18] - ldr r0,[r5,#0x30] - str r1,[r5,#0x30] - ldr r12,[r5,#0x14] - ldr r1,[r5,#0x28] - str r12,[r5,#0x28] - ldr r12,[r5,#0x10] - str r12,[r5,#0x20] - ldr r12,[r5,#0xc] - str r12,[r5,#0x18] - ldr r12,[r5,#8] - str r12,[r5,#0x10] - ldr r12,[r5,#4] - str r12,[r5,#8] - ldr r12,[r5,#0x24] - sub r12,r12,r1 - str r12,[r5,#4] - ldr r12,[r5,#0x2c] - sub r1,r12,r1 - str r1,[r5,#0xc] - sub r1,r12,r0 - str r1,[r5,#0x14] - ldr r1,[r5,#0x34] - sub r0,r1,r0 - str r0,[r5,#0x1c] - sub r0,r1,r3 - str r0,[r5,#0x24] - ldr r1,[r5,#0x3c] - sub r3,r1,r3 - sub r1,r1,r2 - str r1,[r5,#0x34] - str r3,[r5,#0x2c] - ldr r1,[r5,#0x44] - sub r1,r1,r2 - str r1,[r5,#0x3c] - ldr r12,[r5,#0] - -Loop_2 - add r1,r5,r4,lsl #2 - ldr r2,[r1,#0x28] - ldr r3,[r6,r4,lsl #2] - add r0,r0,r2 - str r0,[r1,#0x28] - ldr lr,[r7,r4,lsl #2] - ldr r1,[r1,#4] - smlal r0,r3,lr,r0 - mov r0,r2 - add r2,r12,r1 - rsb r2,r2,#0 - str r3,[r5,r4,lsl #2] - str r2,[r6,r4,lsl #2] - add r4,r4,#1 - cmp r4,#6 - mov r12,r1 - - blt Loop_2 - - ldr r1,[r5,#0x40] - ldr r2,[r6,#0x18] - add r3,r0,r1 - str r3,[r5,#0x40] - ldr lr,[r7,r4,lsl #2] - mov r3,r3,lsl #1 - ldr r0,[r5,#0x1c] - smlal r3,r2,lr,r3 - add r3,r12,r0 - str r2,[r5,#0x18] - ldr r2,[r6,#0x1c] - rsb r3,r3,#0 - str r3,[r6,#0x18] - ldr r3,[r5,#0x20] - add r0,r3,r0 - rsb r0,r0,#0 - str r0,[r6,#0x1c] - ldr r3,[r5,#0x44] - ldr r0,[r6,#0x20] - add r3,r3,r1 - mov r1,r2 - ldr r10,[r7,#0x1c] - mov r2,r3,lsl #1 - smlal r12,r1,r10,r2 - str r1,[r5,#0x1c] - ldr r1,[r5,#0x20] - ldr r3,[r5,#0x24] - add r1,r1,r3 - rsb r1,r1,#0 - str r1,[r6,#0x20] - ldr r1,[r5,#0x44] - ldr r3,[r7,#0x20] - mov r1,r1,lsl #1 - smlal r12,r0,r3,r1 - ldr lr,[r7,#0x24] - ldr r3,[r6,#0x24] - str r0,[r5,#0x20] - smlal r1,r3,lr,r1 - ldr r0,[r6,#0x40] - ldr r12,[r6,#0x44] - str r3,[r5,#0x24] - ldr r1,[r5,#0x28] - ldr r3,[r7,#0x44] - mov r1,r1,lsl #1 - smlal r1,r12,r3,r1 - ldr r1,[r5,#0x40] - str r12,[r5,#0x44] - rsb r8,r1,#0 - str r8,[r5,#0x28] - ldr r1,[r5,#0x2c] - ldr r3,[r7,#0x40] - mov r1,r1,lsl #1 - smlal r1,r0,r3,r1 - str r0,[r5,#0x40] - ldr r0,[r5,#0x3c] - ldr r1,[r6,#0x38] - ldr r3,[r6,#0x3c] - rsb r9,r0,#0 - str r9,[r5,#0x2c] - ldr r0,[r5,#0x30] - ldr r12,[r7,#0x3c] - mov r0,r0,lsl #1 - smlal r0,r3,r12,r0 - str r3,[r5,#0x3c] - ldr r0,[r5,#0x38] - rsb r0,r0,#0 - str r0,[r5,#0x30] - ldr r3,[r5,#0x34] - ldr r12,[r7,#0x38] - mov r3,r3,lsl #1 - smlal r3,r1,r12,r3 - mov r0,r0,lsl #1 - str r1,[r5,#0x38] - ldr r4,[r7,#0x34] - ldr r1,[r6,#0x34] - ldr r3,[r6,#0x30] - smlal r0,r1,r4,r0 - ldr r12,[r6,#0x2c] - ldr lr,[r6,#0x28] - str r1,[r5,#0x34] - ldr r1,[r7,#0x30] - mov r0,r9,lsl #1 - smlal r0,r3,r1,r0 - mov r0,r8,lsl #1 - ldr r1,[r7,#0x2c] - str r3,[r5,#0x30] - smlal r0,r12,r1,r0 - ldr r0,[r7,#0x28] - str r12,[r5,#0x2c] - smlal r2,lr,r0,r2 - str lr,[r5,#0x28] - ldr r1,[r6,#4] - ldr r12,[r7,#0x48] - mov r2,r1,lsl #1 - ldr r1,[r6,#0x20] - ldr r0,[r6] - mov r1,r1,lsl #1 - smull r4,lr,r12,r1 - ldr r3,[r6,#0x1c] - str lr,[r6] - ldr r12,[r7,#0x4c] - mov r3,r3,lsl #1 - smull r4,lr,r12,r3 - mov r0,r0,lsl #1 - ldr r12,[r7,#0x64] - str lr,[r6,#4] - smull r4,lr,r12,r2 - ldr r12,[r7,#0x68] - str lr,[r6,#0x1c] - smull r4,lr,r12,r0 - ldr r12,[r7,#0x6c] - str lr,[r6,#0x20] - smull lr,r0,r12,r0 - ldr r12,[r7,#0x70] - str r0,[r6,#0x24] - smull r0,r2,r12,r2 - ldr r0,[r7,#0x88] - str r2,[r6,#0x28] - smull r3,r2,r0,r3 - ldr r0,[r7,#0x8c] - str r2,[r6,#0x40] - smull r2,r1,r0,r1 - str r1,[r6,#0x44] - ldr r0,[r6,#0x18] - ldr lr,[r7,#0x50] - mov r1,r0,lsl #1 - ldr r0,[r6,#0x14] - smull r5,r4,lr,r1 - ldr r12,[r6,#0x10] - mov r3,r0,lsl #1 - ldr r0,[r6,#0xc] - mov r12,r12,lsl #1 - mov r2,r0,lsl #1 - ldr r0,[r6,#8] - str r4,[r6,#8] - ldr lr,[r7,#0x54] - mov r0,r0,lsl #1 - smull r5,r4,lr,r3 - ldr lr,[r7,#0x58] - str r4,[r6,#0xc] - smull r5,r4,lr,r12 - ldr lr,[r7,#0x5c] - str r4,[r6,#0x10] - smull r5,r4,lr,r2 - ldr lr,[r7,#0x60] - str r4,[r6,#0x14] - smull r5,r4,lr,r0 - ldr lr,[r7,#0x74] - str r4,[r6,#0x18] - smull r4,r0,lr,r0 - ldr lr,[r7,#0x78] - str r0,[r6,#0x2c] - smull r0,r2,lr,r2 - ldr r0,[r7,#0x7c] - str r2,[r6,#0x30] - smull r12,r2,r0,r12 - ldr r0,[r7,#0x80] - str r2,[r6,#0x34] - smull r3,r2,r0,r3 - ldr r0,[r7,#0x84] - str r2,[r6,#0x38] - smull r2,r1,r0,r1 - str r1,[r6,#0x3c] - ldmfd sp!,{r4-r10,pc} -table - DCD ||.constdata$1|| - ENDP - -;------------------------------------------------------------------------------ - - AREA |.constdata|, DATA, READONLY, ALIGN=2 - -;------------------------------------------------------------------------------ - -||.constdata$1|| -cosTerms_dct18 - DCD 0x0807d2b0 - DCD 0x08483ee0 - DCD 0x08d3b7d0 - DCD 0x09c42570 - DCD 0x0b504f30 - DCD 0x0df29440 - DCD 0x12edfb20 - DCD 0x1ee8dd40 - DCD 0x5bca2a00 -cosTerms_1_ov_cos_phi - DCD 0x400f9c00 - DCD 0x408d6080 - DCD 0x418dcb80 - DCD 0x431b1a00 - DCD 0x4545ea00 - DCD 0x48270680 - DCD 0x4be25480 - DCD 0x50ab9480 - DCD 0x56ce4d80 - DCD 0x05ebb630 - DCD 0x06921a98 - DCD 0x0771d3a8 - DCD 0x08a9a830 - DCD 0x0a73d750 - DCD 0x0d4d5260 - DCD 0x127b1ca0 - DCD 0x1ea52b40 - DCD 0x5bb3cc80 - - - - END diff --git a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_wm.asm b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_wm.asm deleted file mode 100644 index 5be75d4..0000000 --- a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_wm.asm +++ /dev/null @@ -1,366 +0,0 @@ -; ------------------------------------------------------------------ -; Copyright (C) 1998-2009 PacketVideo -; -; Licensed under the Apache License, Version 2.0 (the "License"); -; you may not use this file except in compliance with the License. -; You may obtain a copy of the License at -; -; http://www.apache.org/licenses/LICENSE-2.0 -; -; Unless required by applicable law or agreed to in writing, software -; distributed under the License is distributed on an "AS IS" BASIS, -; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -; express or implied. -; See the License for the specific language governing permissions -; and limitations under the License. -; ------------------------------------------------------------------- - -; -; -; Filename: pvmp3_dct_18.s -; -;------------------------------------------------------------------------------ -; REVISION HISTORY -; -; -; Who: Date: MM/DD/YYYY -; Description: -; -;------------------------------------------------------------------------------ - - EXPORT |pvmp3_mdct_18| - - IMPORT pvmp3_dct_9 - - -;------------------------------------------------------------------------------ - - AREA |.text|, CODE, READONLY, ALIGN=2 - - -;------------------------------------------------------------------------------ - -|pvmp3_mdct_18| PROC - stmfd sp!,{r4-r10,lr} - mov r7,r2 - ldr r2,table - mov r6,r1 - add r3,r2,#0x24 - add r12,r3,#0x44 - add r1,r0,#0x44 - mov r5,r0 - -; for ( i=9; i!=0; i--) -; { - - mov r4,#9 -Loop_1 - -; tmp = *(pt_vec); -; tmp1 = *(pt_vec_o); - - ldr lr,[r0] ;; tmp == lr - ldr r8,[r3],#4 ;; tmp1 == r8 - -; tmp = fxp_mul32_Q32( tmp<<1, *(pt_cos++ )); -; tmp1 = fxp_mul32_Q27( tmp1, *(pt_cos_x--)); - - mov lr,lr,lsl #1 - smull r10,lr,r8,lr - ldr r8,[r12],#-4 - ldr r9,[r1] - subs r4,r4,#1 - smull r9,r10,r8,r9 - mov r8,r9,lsr #27 - add r8,r8,r10,lsl #5 - -; *(pt_vec++) = tmp + tmp1 ; -; *(pt_vec_o--) = fxp_mul32_Q28( (tmp - tmp1), *(pt_cos_split++)); - - add r9,lr,r8 - sub r8,lr,r8 - ldr lr,[r2],#4 - str r9,[r0],#4 - smull r8,r9,lr,r8 - mov lr,r8,lsr #28 - add lr,lr,r9,lsl #4 - str lr,[r1],#-4 - bne Loop_1 - -; } - - mov r0,r5 ;; r0 = vec - bl pvmp3_dct_9 - add r0,r5,#0x24 ;; r0 = &vec[9] - bl pvmp3_dct_9 - - ldr r0,[r5,#0x20] - ldr r2,[r5,#0x40] - str r0,[r5,#0x40] - ldr r0,[r5,#0x1c] - ldr r3,[r5,#0x38] - str r0,[r5,#0x38] - ldr r1,[r5,#0x18] - ldr r0,[r5,#0x30] - str r1,[r5,#0x30] - ldr r12,[r5,#0x14] - ldr r1,[r5,#0x28] - str r12,[r5,#0x28] - ldr r12,[r5,#0x10] - str r12,[r5,#0x20] - ldr r12,[r5,#0xc] - str r12,[r5,#0x18] - ldr r12,[r5,#8] - str r12,[r5,#0x10] - ldr r12,[r5,#4] - str r12,[r5,#8] - ldr r12,[r5,#0x24] - sub r12,r12,r1 - str r12,[r5,#4] - ldr r12,[r5,#0x2c] - sub r1,r12,r1 - str r1,[r5,#0xc] - sub r1,r12,r0 - str r1,[r5,#0x14] - ldr r1,[r5,#0x34] - sub r0,r1,r0 - str r0,[r5,#0x1c] - sub r0,r1,r3 - str r0,[r5,#0x24] - ldr r1,[r5,#0x3c] - sub r3,r1,r3 - sub r1,r1,r2 - str r1,[r5,#0x34] - str r3,[r5,#0x2c] - ldr r1,[r5,#0x44] - sub r1,r1,r2 - str r1,[r5,#0x3c] - ldr r12,[r5,#0] - -Loop_2 - add r1,r5,r4,lsl #2 - ldr r2,[r1,#0x28] - ldr r3,[r6,r4,lsl #2] - add r0,r0,r2 - str r0,[r1,#0x28] - ldr lr,[r7,r4,lsl #2] - ldr r1,[r1,#4] - smlal r0,r3,lr,r0 - mov r0,r2 - add r2,r12,r1 - rsb r2,r2,#0 - str r3,[r5,r4,lsl #2] - str r2,[r6,r4,lsl #2] - add r4,r4,#1 - cmp r4,#6 - mov r12,r1 - - blt Loop_2 - - ldr r1,[r5,#0x40] - ldr r2,[r6,#0x18] - add r3,r0,r1 - str r3,[r5,#0x40] - ldr lr,[r7,r4,lsl #2] - mov r3,r3,lsl #1 - ldr r0,[r5,#0x1c] - smlal r3,r2,lr,r3 - add r3,r12,r0 - str r2,[r5,#0x18] - ldr r2,[r6,#0x1c] - rsb r3,r3,#0 - str r3,[r6,#0x18] - ldr r3,[r5,#0x20] - add r0,r3,r0 - rsb r0,r0,#0 - str r0,[r6,#0x1c] - ldr r3,[r5,#0x44] - ldr r0,[r6,#0x20] - add r3,r3,r1 - mov r1,r2 - ldr r10,[r7,#0x1c] - mov r2,r3,lsl #1 - smlal r12,r1,r10,r2 - str r1,[r5,#0x1c] - ldr r1,[r5,#0x20] - ldr r3,[r5,#0x24] - add r1,r1,r3 - rsb r1,r1,#0 - str r1,[r6,#0x20] - ldr r1,[r5,#0x44] - ldr r3,[r7,#0x20] - mov r1,r1,lsl #1 - smlal r12,r0,r3,r1 - ldr lr,[r7,#0x24] - ldr r3,[r6,#0x24] - str r0,[r5,#0x20] - smlal r1,r3,lr,r1 - ldr r0,[r6,#0x40] - ldr r12,[r6,#0x44] - str r3,[r5,#0x24] - ldr r1,[r5,#0x28] - ldr r3,[r7,#0x44] - mov r1,r1,lsl #1 - smlal r1,r12,r3,r1 - ldr r1,[r5,#0x40] - str r12,[r5,#0x44] - rsb r8,r1,#0 - str r8,[r5,#0x28] - ldr r1,[r5,#0x2c] - ldr r3,[r7,#0x40] - mov r1,r1,lsl #1 - smlal r1,r0,r3,r1 - str r0,[r5,#0x40] - ldr r0,[r5,#0x3c] - ldr r1,[r6,#0x38] - ldr r3,[r6,#0x3c] - rsb r9,r0,#0 - str r9,[r5,#0x2c] - ldr r0,[r5,#0x30] - ldr r12,[r7,#0x3c] - mov r0,r0,lsl #1 - smlal r0,r3,r12,r0 - str r3,[r5,#0x3c] - ldr r0,[r5,#0x38] - rsb r0,r0,#0 - str r0,[r5,#0x30] - ldr r3,[r5,#0x34] - ldr r12,[r7,#0x38] - mov r3,r3,lsl #1 - smlal r3,r1,r12,r3 - mov r0,r0,lsl #1 - str r1,[r5,#0x38] - ldr r4,[r7,#0x34] - ldr r1,[r6,#0x34] - ldr r3,[r6,#0x30] - smlal r0,r1,r4,r0 - ldr r12,[r6,#0x2c] - ldr lr,[r6,#0x28] - str r1,[r5,#0x34] - ldr r1,[r7,#0x30] - mov r0,r9,lsl #1 - smlal r0,r3,r1,r0 - mov r0,r8,lsl #1 - ldr r1,[r7,#0x2c] - str r3,[r5,#0x30] - smlal r0,r12,r1,r0 - ldr r0,[r7,#0x28] - str r12,[r5,#0x2c] - smlal r2,lr,r0,r2 - str lr,[r5,#0x28] - ldr r1,[r6,#4] - ldr r12,[r7,#0x48] - mov r2,r1,lsl #1 - ldr r1,[r6,#0x20] - ldr r0,[r6] - mov r1,r1,lsl #1 - smull r4,lr,r12,r1 - ldr r3,[r6,#0x1c] - str lr,[r6] - ldr r12,[r7,#0x4c] - mov r3,r3,lsl #1 - smull r4,lr,r12,r3 - mov r0,r0,lsl #1 - ldr r12,[r7,#0x64] - str lr,[r6,#4] - smull r4,lr,r12,r2 - ldr r12,[r7,#0x68] - str lr,[r6,#0x1c] - smull r4,lr,r12,r0 - ldr r12,[r7,#0x6c] - str lr,[r6,#0x20] - smull lr,r0,r12,r0 - ldr r12,[r7,#0x70] - str r0,[r6,#0x24] - smull r0,r2,r12,r2 - ldr r0,[r7,#0x88] - str r2,[r6,#0x28] - smull r3,r2,r0,r3 - ldr r0,[r7,#0x8c] - str r2,[r6,#0x40] - smull r2,r1,r0,r1 - str r1,[r6,#0x44] - ldr r0,[r6,#0x18] - ldr lr,[r7,#0x50] - mov r1,r0,lsl #1 - ldr r0,[r6,#0x14] - smull r5,r4,lr,r1 - ldr r12,[r6,#0x10] - mov r3,r0,lsl #1 - ldr r0,[r6,#0xc] - mov r12,r12,lsl #1 - mov r2,r0,lsl #1 - ldr r0,[r6,#8] - str r4,[r6,#8] - ldr lr,[r7,#0x54] - mov r0,r0,lsl #1 - smull r5,r4,lr,r3 - ldr lr,[r7,#0x58] - str r4,[r6,#0xc] - smull r5,r4,lr,r12 - ldr lr,[r7,#0x5c] - str r4,[r6,#0x10] - smull r5,r4,lr,r2 - ldr lr,[r7,#0x60] - str r4,[r6,#0x14] - smull r5,r4,lr,r0 - ldr lr,[r7,#0x74] - str r4,[r6,#0x18] - smull r4,r0,lr,r0 - ldr lr,[r7,#0x78] - str r0,[r6,#0x2c] - smull r0,r2,lr,r2 - ldr r0,[r7,#0x7c] - str r2,[r6,#0x30] - smull r12,r2,r0,r12 - ldr r0,[r7,#0x80] - str r2,[r6,#0x34] - smull r3,r2,r0,r3 - ldr r0,[r7,#0x84] - str r2,[r6,#0x38] - smull r2,r1,r0,r1 - str r1,[r6,#0x3c] - ldmfd sp!,{r4-r10,pc} -table - DCD cosTerms_dct18 - ENDP - -;------------------------------------------------------------------------------ - - AREA |.constdata|, DATA, READONLY, ALIGN=2 - -;------------------------------------------------------------------------------ - -cosTerms_dct18 - DCD 0x0807d2b0 - DCD 0x08483ee0 - DCD 0x08d3b7d0 - DCD 0x09c42570 - DCD 0x0b504f30 - DCD 0x0df29440 - DCD 0x12edfb20 - DCD 0x1ee8dd40 - DCD 0x5bca2a00 -cosTerms_1_ov_cos_phi - DCD 0x400f9c00 - DCD 0x408d6080 - DCD 0x418dcb80 - DCD 0x431b1a00 - DCD 0x4545ea00 - DCD 0x48270680 - DCD 0x4be25480 - DCD 0x50ab9480 - DCD 0x56ce4d80 - DCD 0x05ebb630 - DCD 0x06921a98 - DCD 0x0771d3a8 - DCD 0x08a9a830 - DCD 0x0a73d750 - DCD 0x0d4d5260 - DCD 0x127b1ca0 - DCD 0x1ea52b40 - DCD 0x5bb3cc80 - - - - END diff --git a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_arm.s b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_arm.s deleted file mode 100644 index abec599..0000000 --- a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_arm.s +++ /dev/null @@ -1,237 +0,0 @@ -; ------------------------------------------------------------------ -; Copyright (C) 1998-2009 PacketVideo -; -; Licensed under the Apache License, Version 2.0 (the "License"); -; you may not use this file except in compliance with the License. -; You may obtain a copy of the License at -; -; http://www.apache.org/licenses/LICENSE-2.0 -; -; Unless required by applicable law or agreed to in writing, software -; distributed under the License is distributed on an "AS IS" BASIS, -; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -; express or implied. -; See the License for the specific language governing permissions -; and limitations under the License. -; ------------------------------------------------------------------- - -; -; -; Filename: pvmp3_polyphase_filter_window.s -; -;------------------------------------------------------------------------------ -; REVISION HISTORY -; -; -; Who: Date: MM/DD/YYYY -; Description: -; -;------------------------------------------------------------------------------ - - EXPORT pvmp3_polyphase_filter_window - - IMPORT ||Lib$$Request$$armlib|| [WEAK] - IMPORT ||Lib$$Request$$cpplib|| [WEAK] - IMPORT pqmfSynthWin - - - -;------------------------------------------------------------------------------ - - AREA |.text|, CODE, READONLY, ALIGN=2 - - -;------------------------------------------------------------------------------ - -|pvmp3_polyphase_filter_window| PROC - - stmfd sp!,{r0-r2,r4-r11,lr} - - sub sp,sp,#4 - ldr r2,[sp,#0xc] - ldr r1,PolyPh_filter_coeff - - sub r2,r2,#1 - mov r10,#1 - str r2,[sp] - -; Accumulators r9, r11::> Initialization - -Loop_j - mov r9, #0x20 - mov r11, #0x20 - mov r4, #0x10 -Loop_i - add r2,r4,r10 - add r3,r0,r2,lsl #2 - sub r2,r4,r10 - ldr r5,[r3] - ldr lr,[r1] - add r12,r0,r2,lsl #2 - ldr r6,[r12,#0x780] - smlal r2,r9,lr,r5 - smlal r2,r11,lr,r6 - ldr r2,[r1,#4] - ldr r7,[r12,#0x80] - smlal r5,r11,r2,r5 - smull r6,r5,r2,r6 - sub r9,r9,r5 - ldr r5,[r1,#8] - ldr r8,[r3,#0x700] - add r4,r4,#0x200 - smlal r6,r9,r5,r7 - smull r6,r2,r5,r8 - ldr r5,[r1,#0xc] - sub r11,r11,r2 - smlal r8,r9,r5,r8 - smlal r7,r11,r5,r7 - ldr r5,[r3,#0x100] - ldr r2,[r1,#0x10] - ldr r6,[r12,#0x680] - smlal lr,r9,r2,r5 - smlal lr,r11,r2,r6 - ldr r2,[r1,#0x14] - ldr r7,[r12,#0x180] - smlal r5,r11,r2,r5 - smull r6,r5,r2,r6 - ldr r6,[r1,#0x18] - ldr r8,[r3,#0x600] - sub r9,r9,r5 - smlal r5,r9,r6,r7 - smull r2,r5,r6,r8 - ldr r6,[r1,#0x1c] - sub r11,r11,r5 - smlal r8,r9,r6,r8 - ldr r2,[r1,#0x20] - ldr r5,[r3,#0x200] - smlal r7,r11,r6,r7 - ldr r6,[r12,#0x580] - smlal lr,r9,r2,r5 - smlal lr,r11,r2,r6 - ldr r2,[r1,#0x24] - ldr r7,[r12,#0x280] - smlal r5,r11,r2,r5 - smull r6,r5,r2,r6 - ldr r6,[r1,#0x28] - ldr r8,[r3,#0x500] - sub r9,r9,r5 - smlal r5,r9,r6,r7 - smull r2,r5,r6,r8 - ldr r6,[r1,#0x2c] - sub r11,r11,r5 - - smlal r8,r9,r6,r8 - smlal r7,r11,r6,r7 - ldr r5,[r3,#0x300] - ldr r8,[r1,#0x30] - ldr r6,[r12,#0x480] - smlal r7,r9,r8,r5 - smlal r7,r11,r8,r6 - ldr r8,[r1,#0x34] - ldr r12,[r12,#0x380] - smlal r5,r11,r8,r5 - smull r6,r5,r8,r6 - ldr r6,[r1,#0x38] - - - ldr r3,[r3,#0x400] - sub r9,r9,r5 - smlal r7,r9,r6,r12 - smull r8,r7,r6,r3 - cmp r4,#0x210 - sub r11,r11,r7 - - ldr r2,[r1,#0x3c] - add r1,r1,#0x40 - smlal r3,r9,r2,r3 - smlal r12,r11,r2,r12 - - blt Loop_i - - mov r3,r9, asr #6 - mov r4,r3, asr #15 - teq r4,r3, asr #31 - ldr r12,LOW_16BITS - ldr r2,[sp] - eorne r3,r12,r3,asr #31 - ldr r4,[sp,#8] - mov r2,r10,lsl r2 - add r4,r4,r2,lsl #1 - strh r3,[r4] - - mov r3,r11,asr #6 - mov r4,r3,asr #15 - teq r4,r3,asr #31 - eorne r3,r12,r3,asr #31 - ldr r12,[sp,#0xc] - ldr r11,[sp,#8] - rsb r2,r2,r12,lsl #5 - add r2,r11,r2,lsl #1 - strh r3,[r2] - - add r10,r10,#1 - cmp r10,#0x10 - blt Loop_j - -; Accumulators r4, r5 Initialization - - mov r4,#0x20 - mov r5,#0x20 - mov r3,#0x10 -PolyPh_filter_loop2 - add r2,r0,r3,lsl #2 - ldr r12,[r2] - ldr r8,[r1] - ldr r6,[r2,#0x80] - smlal r12,r4,r8,r12 - ldr r12,[r1,#4] - ldr r7,[r2,#0x40] - smlal r6,r4,r12,r6 - - ldr r12,[r1,#8] - ldr r6,[r2,#0x180] - smlal r7,r5,r12,r7 - ldr r12,[r2,#0x100] - ldr r7,[r1,#0xc] - ldr r2,[r2,#0x140] - smlal r12,r4,r7,r12 - ldr r12,[r1,#0x10] - add r3,r3,#0x80 - smlal r6,r4,r12,r6 - ldr r6,[r1,#0x14] - cmp r3,#0x210 - smlal r2,r5,r6,r2 - add r1,r1,#0x18 - - blt PolyPh_filter_loop2 - mov r0,r4,asr #6 - mov r2,r0,asr #15 - teq r2,r0,asr #31 - ldrne r12,LOW_16BITS - ldr r1,[sp,#8] - eorne r0,r12,r0,asr #31 - strh r0,[r1,#0] - mov r0,r5,asr #6 - mov r2,r0,asr #15 - teq r2,r0,asr #31 - ldrne r12,LOW_16BITS - ldr r2,[sp] - mov r1,#0x10 - eorne r0,r12,r0,asr #31 - ldr r12,[sp,#8] - mov r1,r1,lsl r2 - add r1,r12,r1,lsl #1 - strh r0,[r1] - add sp,sp,#0x10 - ldmfd sp!,{r4-r11,pc} - - -PolyPh_filter_coeff - DCD pqmfSynthWin -LOW_16BITS - DCD 0x00007fff - - ENDP - - - END diff --git a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_gcc.s b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_gcc.s index b74c849..1140ed7 100644 --- a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_gcc.s +++ b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_gcc.s @@ -35,6 +35,7 @@ .text .extern pqmfSynthWin +.hidden pqmfSynthWin diff --git a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_wm.asm b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_wm.asm deleted file mode 100644 index f957267..0000000 --- a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_wm.asm +++ /dev/null @@ -1,231 +0,0 @@ -; ------------------------------------------------------------------ -; Copyright (C) 1998-2009 PacketVideo -; -; Licensed under the Apache License, Version 2.0 (the "License"); -; you may not use this file except in compliance with the License. -; You may obtain a copy of the License at -; -; http://www.apache.org/licenses/LICENSE-2.0 -; -; Unless required by applicable law or agreed to in writing, software -; distributed under the License is distributed on an "AS IS" BASIS, -; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -; express or implied. -; See the License for the specific language governing permissions -; and limitations under the License. -; ------------------------------------------------------------------- - -; -; -; Filename: pvmp3_polyphase_filter_window.s -; -;------------------------------------------------------------------------------ -; REVISION HISTORY -; -; -; Who: Date: MM/DD/YYYY -; Description: -; -;------------------------------------------------------------------------------ - - CODE32 - - AREA |.drectve|, DRECTVE - - EXPORT |pvmp3_polyphase_filter_window| - IMPORT |pqmfSynthWin| - - AREA |.pdata|, PDATA - - AREA |.text|, CODE, ARM - -|pvmp3_polyphase_filter_window| PROC - stmfd sp!,{r0-r2,r4-r11,lr} - - sub sp,sp,#4 - ldr r2,[sp,#0xc] - ldr r1,PolyPh_filter_coeff - - sub r2,r2,#1 - mov r10,#1 - str r2,[sp] - -; Accumulators r9, r11::> Initialization - -Loop_j - mov r9, #0x20 - mov r11, #0x20 - mov r4, #0x10 -Loop_i - add r2,r4,r10 - add r3,r0,r2,lsl #2 - sub r2,r4,r10 - ldr r5,[r3] - ldr lr,[r1] - add r12,r0,r2,lsl #2 - ldr r6,[r12,#0x780] - smlal r2,r9,lr,r5 - smlal r2,r11,lr,r6 - ldr r2,[r1,#4] - ldr r7,[r12,#0x80] - smlal r5,r11,r2,r5 - smull r6,r5,r2,r6 - sub r9,r9,r5 - ldr r5,[r1,#8] - ldr r8,[r3,#0x700] - add r4,r4,#0x200 - smlal r6,r9,r5,r7 - smull r6,r2,r5,r8 - ldr r5,[r1,#0xc] - sub r11,r11,r2 - smlal r8,r9,r5,r8 - smlal r7,r11,r5,r7 - ldr r5,[r3,#0x100] - ldr r2,[r1,#0x10] - ldr r6,[r12,#0x680] - smlal lr,r9,r2,r5 - smlal lr,r11,r2,r6 - ldr r2,[r1,#0x14] - ldr r7,[r12,#0x180] - smlal r5,r11,r2,r5 - smull r6,r5,r2,r6 - ldr r6,[r1,#0x18] - ldr r8,[r3,#0x600] - sub r9,r9,r5 - smlal r5,r9,r6,r7 - smull r2,r5,r6,r8 - ldr r6,[r1,#0x1c] - sub r11,r11,r5 - smlal r8,r9,r6,r8 - ldr r2,[r1,#0x20] - ldr r5,[r3,#0x200] - smlal r7,r11,r6,r7 - ldr r6,[r12,#0x580] - smlal lr,r9,r2,r5 - smlal lr,r11,r2,r6 - ldr r2,[r1,#0x24] - ldr r7,[r12,#0x280] - smlal r5,r11,r2,r5 - smull r6,r5,r2,r6 - ldr r6,[r1,#0x28] - ldr r8,[r3,#0x500] - sub r9,r9,r5 - smlal r5,r9,r6,r7 - smull r2,r5,r6,r8 - ldr r6,[r1,#0x2c] - sub r11,r11,r5 - - smlal r8,r9,r6,r8 - smlal r7,r11,r6,r7 - ldr r5,[r3,#0x300] - ldr r8,[r1,#0x30] - ldr r6,[r12,#0x480] - smlal r7,r9,r8,r5 - smlal r7,r11,r8,r6 - ldr r8,[r1,#0x34] - ldr r12,[r12,#0x380] - smlal r5,r11,r8,r5 - smull r6,r5,r8,r6 - ldr r6,[r1,#0x38] - - - ldr r3,[r3,#0x400] - sub r9,r9,r5 - smlal r7,r9,r6,r12 - smull r8,r7,r6,r3 - cmp r4,#0x210 - sub r11,r11,r7 - - ldr r2,[r1,#0x3c] - add r1,r1,#0x40 - smlal r3,r9,r2,r3 - smlal r12,r11,r2,r12 - - blt Loop_i - - mov r3,r9, asr #6 - mov r4,r3, asr #15 - teq r4,r3, asr #31 - ldr r12,LOW_16BITS - ldr r2,[sp] - eorne r3,r12,r3,asr #31 - ldr r4,[sp,#8] - mov r2,r10,lsl r2 - add r4,r4,r2,lsl #1 - strh r3,[r4] - - mov r3,r11,asr #6 - mov r4,r3,asr #15 - teq r4,r3,asr #31 - eorne r3,r12,r3,asr #31 - ldr r12,[sp,#0xc] - ldr r11,[sp,#8] - rsb r2,r2,r12,lsl #5 - add r2,r11,r2,lsl #1 - strh r3,[r2] - - add r10,r10,#1 - cmp r10,#0x10 - blt Loop_j - -; Accumulators r4, r5 Initialization - - mov r4,#0x20 - mov r5,#0x20 - mov r3,#0x10 -PolyPh_filter_loop2 - add r2,r0,r3,lsl #2 - ldr r12,[r2] - ldr r8,[r1] - ldr r6,[r2,#0x80] - smlal r12,r4,r8,r12 - ldr r12,[r1,#4] - ldr r7,[r2,#0x40] - smlal r6,r4,r12,r6 - - ldr r12,[r1,#8] - ldr r6,[r2,#0x180] - smlal r7,r5,r12,r7 - ldr r12,[r2,#0x100] - ldr r7,[r1,#0xc] - ldr r2,[r2,#0x140] - smlal r12,r4,r7,r12 - ldr r12,[r1,#0x10] - add r3,r3,#0x80 - smlal r6,r4,r12,r6 - ldr r6,[r1,#0x14] - cmp r3,#0x210 - smlal r2,r5,r6,r2 - add r1,r1,#0x18 - - blt PolyPh_filter_loop2 - mov r0,r4,asr #6 - mov r2,r0,asr #15 - teq r2,r0,asr #31 - ldrne r12,LOW_16BITS - ldr r1,[sp,#8] - eorne r0,r12,r0,asr #31 - strh r0,[r1,#0] - mov r0,r5,asr #6 - mov r2,r0,asr #15 - teq r2,r0,asr #31 - ldrne r12,LOW_16BITS - ldr r2,[sp] - mov r1,#0x10 - eorne r0,r12,r0,asr #31 - ldr r12,[sp,#8] - mov r1,r1,lsl r2 - add r1,r12,r1,lsl #1 - strh r0,[r1] - add sp,sp,#0x10 - ldmfd sp!,{r4-r11,pc} - - -PolyPh_filter_coeff - DCD pqmfSynthWin -LOW_16BITS - DCD 0x00007fff - - ENDP ; |pvmp3_polyphase_filter_window| - END - diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.cpp index ee42dc5..499672b 100644 --- a/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.cpp +++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.cpp @@ -139,7 +139,7 @@ void pvmp3_mpeg2_get_scale_data(mp3SideInfo *si, int16 blocknumber = 0; granuleInfo *gr_info = &(si->ch[ch].gran[gr]); - uint32 scalefac_comp, int_scalefac_comp, new_slen[4]; + uint32 scalefac_comp, int_scalefac_comp, new_slen[4] = { 0,0,0,0 }; scalefac_comp = gr_info->scalefac_compress; diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp index 476e986..423a057 100644 --- a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp +++ b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp @@ -85,7 +85,7 @@ status_t SoftVPX::initDecoder() { return OK; } -void SoftVPX::onQueueFilled(OMX_U32 portIndex) { +void SoftVPX::onQueueFilled(OMX_U32 /* portIndex */) { if (mOutputPortSettingsChange != NONE) { return; } diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp index 8375cac..5efe022 100644 --- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp +++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp @@ -677,6 +677,9 @@ OMX_ERRORTYPE SoftVPXEncoder::internalSetPortParams( def->format.video.nFrameHeight = mHeight; def->format.video.xFramerate = port->format.video.xFramerate; def->format.video.eColorFormat = mColorFormat; + def = &editPortInfo(kOutputPortIndex)->mDef; + def->format.video.nFrameWidth = mWidth; + def->format.video.nFrameHeight = mHeight; return OMX_ErrorNone; } else if (port->nPortIndex == kOutputPortIndex) { diff --git a/media/libstagefright/codecs/on2/h264dec/Android.mk b/media/libstagefright/codecs/on2/h264dec/Android.mk index 655b2ab..bf03ad9 100644 --- a/media/libstagefright/codecs/on2/h264dec/Android.mk +++ b/media/libstagefright/codecs/on2/h264dec/Android.mk @@ -84,8 +84,8 @@ MY_OMXDL_ASM_SRC := \ ./omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.S \ ./omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantChromaDCFromPair_s.S \ - -ifeq ($(ARCH_ARM_HAVE_NEON),true) +ifeq ($(TARGET_ARCH),arm) + ifeq ($(ARCH_ARM_HAVE_NEON),true) LOCAL_ARM_NEON := true # LOCAL_CFLAGS := -std=c99 -D._NEON -D._OMXDL LOCAL_CFLAGS := -DH264DEC_NEON -DH264DEC_OMXDL @@ -94,6 +94,7 @@ ifeq ($(ARCH_ARM_HAVE_NEON),true) LOCAL_C_INCLUDES += $(LOCAL_PATH)/./omxdl/arm_neon/api \ $(LOCAL_PATH)/./omxdl/arm_neon/vc/api \ $(LOCAL_PATH)/./omxdl/arm_neon/vc/m4p10/api + endif endif LOCAL_SHARED_LIBRARIES := \ diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp index 7ddb13c..a7bde97 100644 --- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp +++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp @@ -98,7 +98,7 @@ status_t SoftAVC::initDecoder() { return UNKNOWN_ERROR; } -void SoftAVC::onQueueFilled(OMX_U32 portIndex) { +void SoftAVC::onQueueFilled(OMX_U32 /* portIndex */) { if (mSignalledError || mOutputPortSettingsChange != NONE) { return; } diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/omxtypes.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/omxtypes.h index 8b295a6..912cb0d 100644 --- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/omxtypes.h +++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/omxtypes.h @@ -32,6 +32,7 @@ #define _OMXTYPES_H_ #include <limits.h> +#include <stdint.h> #define OMX_IN #define OMX_OUT @@ -75,64 +76,22 @@ typedef enum { /* OMX_U8 */ -#if UCHAR_MAX == 0xff -typedef unsigned char OMX_U8; -#elif USHRT_MAX == 0xff -typedef unsigned short int OMX_U8; -#else -#error OMX_U8 undefined -#endif - +typedef uint8_t OMX_U8; /* OMX_S8 */ -#if SCHAR_MAX == 0x7f -typedef signed char OMX_S8; -#elif SHRT_MAX == 0x7f -typedef signed short int OMX_S8; -#else -#error OMX_S8 undefined -#endif - +typedef int8_t OMX_S8; /* OMX_U16 */ -#if USHRT_MAX == 0xffff -typedef unsigned short int OMX_U16; -#elif UINT_MAX == 0xffff -typedef unsigned int OMX_U16; -#else -#error OMX_U16 undefined -#endif - +typedef uint16_t OMX_U16; /* OMX_S16 */ -#if SHRT_MAX == 0x7fff -typedef signed short int OMX_S16; -#elif INT_MAX == 0x7fff -typedef signed int OMX_S16; -#else -#error OMX_S16 undefined -#endif - +typedef int16_t OMX_S16; /* OMX_U32 */ -#if UINT_MAX == 0xffffffff -typedef unsigned int OMX_U32; -#elif LONG_MAX == 0xffffffff -typedef unsigned long int OMX_U32; -#else -#error OMX_U32 undefined -#endif - +typedef uint32_t OMX_U32; /* OMX_S32 */ -#if INT_MAX == 0x7fffffff -typedef signed int OMX_S32; -#elif LONG_MAX == 0x7fffffff -typedef long signed int OMX_S32; -#else -#error OMX_S32 undefined -#endif - +typedef int32_t OMX_S32; /* OMX_U64 & OMX_S64 */ #if defined( _WIN32 ) || defined ( _WIN64 ) @@ -143,15 +102,14 @@ typedef long signed int OMX_S32; #define OMX_MAX_S64 (0x7FFFFFFFFFFFFFFFi64) #define OMX_MAX_U64 (0xFFFFFFFFFFFFFFFFi64) #else - typedef long long OMX_S64; /** Signed 64-bit integer */ - typedef unsigned long long OMX_U64; /** Unsigned 64-bit integer */ + typedef int64_t OMX_S64; /** Signed 64-bit integer */ + typedef uint64_t OMX_U64; /** Unsigned 64-bit integer */ #define OMX_MIN_S64 (0x8000000000000000LL) #define OMX_MIN_U64 (0x0000000000000000LL) #define OMX_MAX_S64 (0x7FFFFFFFFFFFFFFFLL) #define OMX_MAX_U64 (0xFFFFFFFFFFFFFFFFLL) #endif - /* OMX_SC8 */ typedef struct { diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/omxtypes.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/omxtypes.h index 8b295a6..912cb0d 100755 --- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/omxtypes.h +++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/omxtypes.h @@ -32,6 +32,7 @@ #define _OMXTYPES_H_ #include <limits.h> +#include <stdint.h> #define OMX_IN #define OMX_OUT @@ -75,64 +76,22 @@ typedef enum { /* OMX_U8 */ -#if UCHAR_MAX == 0xff -typedef unsigned char OMX_U8; -#elif USHRT_MAX == 0xff -typedef unsigned short int OMX_U8; -#else -#error OMX_U8 undefined -#endif - +typedef uint8_t OMX_U8; /* OMX_S8 */ -#if SCHAR_MAX == 0x7f -typedef signed char OMX_S8; -#elif SHRT_MAX == 0x7f -typedef signed short int OMX_S8; -#else -#error OMX_S8 undefined -#endif - +typedef int8_t OMX_S8; /* OMX_U16 */ -#if USHRT_MAX == 0xffff -typedef unsigned short int OMX_U16; -#elif UINT_MAX == 0xffff -typedef unsigned int OMX_U16; -#else -#error OMX_U16 undefined -#endif - +typedef uint16_t OMX_U16; /* OMX_S16 */ -#if SHRT_MAX == 0x7fff -typedef signed short int OMX_S16; -#elif INT_MAX == 0x7fff -typedef signed int OMX_S16; -#else -#error OMX_S16 undefined -#endif - +typedef int16_t OMX_S16; /* OMX_U32 */ -#if UINT_MAX == 0xffffffff -typedef unsigned int OMX_U32; -#elif LONG_MAX == 0xffffffff -typedef unsigned long int OMX_U32; -#else -#error OMX_U32 undefined -#endif - +typedef uint32_t OMX_U32; /* OMX_S32 */ -#if INT_MAX == 0x7fffffff -typedef signed int OMX_S32; -#elif LONG_MAX == 0x7fffffff -typedef long signed int OMX_S32; -#else -#error OMX_S32 undefined -#endif - +typedef int32_t OMX_S32; /* OMX_U64 & OMX_S64 */ #if defined( _WIN32 ) || defined ( _WIN64 ) @@ -143,15 +102,14 @@ typedef long signed int OMX_S32; #define OMX_MAX_S64 (0x7FFFFFFFFFFFFFFFi64) #define OMX_MAX_U64 (0xFFFFFFFFFFFFFFFFi64) #else - typedef long long OMX_S64; /** Signed 64-bit integer */ - typedef unsigned long long OMX_U64; /** Unsigned 64-bit integer */ + typedef int64_t OMX_S64; /** Signed 64-bit integer */ + typedef uint64_t OMX_U64; /** Unsigned 64-bit integer */ #define OMX_MIN_S64 (0x8000000000000000LL) #define OMX_MIN_U64 (0x0000000000000000LL) #define OMX_MAX_S64 (0x7FFFFFFFFFFFFFFFLL) #define OMX_MAX_U64 (0xFFFFFFFFFFFFFFFFLL) #endif - /* OMX_SC8 */ typedef struct { diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DecodeCoeffsToPair_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DecodeCoeffsToPair_s.S index 073dbba..bcc6b6b 100644 --- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DecodeCoeffsToPair_s.S +++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DecodeCoeffsToPair_s.S @@ -10,6 +10,22 @@ .fpu neon .text + .extern armVCM4P10_CAVLCCoeffTokenTables + .extern armVCM4P10_SuffixToLevel + .extern armVCM4P10_CAVLCTotalZeros2x2Tables + .extern armVCM4P10_CAVLCTotalZeroTables + .extern armVCM4P10_CAVLCRunBeforeTables + .extern armVCM4P10_ZigZag_2x2 + .extern armVCM4P10_ZigZag_4x4 + + .hidden armVCM4P10_CAVLCCoeffTokenTables + .hidden armVCM4P10_SuffixToLevel + .hidden armVCM4P10_CAVLCTotalZeros2x2Tables + .hidden armVCM4P10_CAVLCTotalZeroTables + .hidden armVCM4P10_CAVLCRunBeforeTables + .hidden armVCM4P10_ZigZag_2x2 + .hidden armVCM4P10_ZigZag_4x4 + .global armVCM4P10_DecodeCoeffsToPair .func armVCM4P10_DecodeCoeffsToPair armVCM4P10_DecodeCoeffsToPair: diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DequantTables_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DequantTables_s.S index 44eb428..5bc7875 100644 --- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DequantTables_s.S +++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DequantTables_s.S @@ -20,6 +20,14 @@ .global armVCM4P10_QPModuloTable .global armVCM4P10_VMatrixU16 + .hidden armVCM4P10_QPDivTable + .hidden armVCM4P10_VMatrixQPModTable + .hidden armVCM4P10_PosToVCol4x4 + .hidden armVCM4P10_PosToVCol2x2 + .hidden armVCM4P10_VMatrix + .hidden armVCM4P10_QPModuloTable + .hidden armVCM4P10_VMatrixU16 + armVCM4P10_PosToVCol4x4: .byte 0, 2, 0, 2 .byte 2, 1, 2, 1 diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/omxtypes.h b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/omxtypes.h index 8b295a6..912cb0d 100644 --- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/omxtypes.h +++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/omxtypes.h @@ -32,6 +32,7 @@ #define _OMXTYPES_H_ #include <limits.h> +#include <stdint.h> #define OMX_IN #define OMX_OUT @@ -75,64 +76,22 @@ typedef enum { /* OMX_U8 */ -#if UCHAR_MAX == 0xff -typedef unsigned char OMX_U8; -#elif USHRT_MAX == 0xff -typedef unsigned short int OMX_U8; -#else -#error OMX_U8 undefined -#endif - +typedef uint8_t OMX_U8; /* OMX_S8 */ -#if SCHAR_MAX == 0x7f -typedef signed char OMX_S8; -#elif SHRT_MAX == 0x7f -typedef signed short int OMX_S8; -#else -#error OMX_S8 undefined -#endif - +typedef int8_t OMX_S8; /* OMX_U16 */ -#if USHRT_MAX == 0xffff -typedef unsigned short int OMX_U16; -#elif UINT_MAX == 0xffff -typedef unsigned int OMX_U16; -#else -#error OMX_U16 undefined -#endif - +typedef uint16_t OMX_U16; /* OMX_S16 */ -#if SHRT_MAX == 0x7fff -typedef signed short int OMX_S16; -#elif INT_MAX == 0x7fff -typedef signed int OMX_S16; -#else -#error OMX_S16 undefined -#endif - +typedef int16_t OMX_S16; /* OMX_U32 */ -#if UINT_MAX == 0xffffffff -typedef unsigned int OMX_U32; -#elif LONG_MAX == 0xffffffff -typedef unsigned long int OMX_U32; -#else -#error OMX_U32 undefined -#endif - +typedef uint32_t OMX_U32; /* OMX_S32 */ -#if INT_MAX == 0x7fffffff -typedef signed int OMX_S32; -#elif LONG_MAX == 0x7fffffff -typedef long signed int OMX_S32; -#else -#error OMX_S32 undefined -#endif - +typedef int32_t OMX_S32; /* OMX_U64 & OMX_S64 */ #if defined( _WIN32 ) || defined ( _WIN64 ) @@ -143,15 +102,14 @@ typedef long signed int OMX_S32; #define OMX_MAX_S64 (0x7FFFFFFFFFFFFFFFi64) #define OMX_MAX_U64 (0xFFFFFFFFFFFFFFFFi64) #else - typedef long long OMX_S64; /** Signed 64-bit integer */ - typedef unsigned long long OMX_U64; /** Unsigned 64-bit integer */ + typedef int64_t OMX_S64; /** Signed 64-bit integer */ + typedef uint64_t OMX_U64; /** Unsigned 64-bit integer */ #define OMX_MIN_S64 (0x8000000000000000LL) #define OMX_MIN_U64 (0x0000000000000000LL) #define OMX_MAX_S64 (0x7FFFFFFFFFFFFFFFLL) #define OMX_MAX_U64 (0xFFFFFFFFFFFFFFFFLL) #endif - /* OMX_SC8 */ typedef struct { diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.c index 493fb9e..7a262ed 100755 --- a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.c +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.c @@ -267,7 +267,7 @@ u32 ConcealMb(mbStorage_t *pMb, image_t *currImage, u32 row, u32 col, i32 firstPhase[16]; i32 *pTmp; /* neighbours above, below, left and right */ - i32 a[4], b[4], l[4], r[4]; + i32 a[4] = { 0,0,0,0 }, b[4], l[4] = { 0,0,0,0 }, r[4]; u32 A, B, L, R; #ifdef H264DEC_OMXDL u8 fillBuff[32*21 + 15 + 32]; diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_intra_prediction.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_intra_prediction.c index 15eabfb..52c85e5 100755 --- a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_intra_prediction.c +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_intra_prediction.c @@ -1110,7 +1110,7 @@ void Intra16x16PlanePrediction(u8 *data, u8 *above, u8 *left) /* Variables */ - u32 i, j; + i32 i, j; i32 a, b, c; i32 tmp; @@ -1123,20 +1123,20 @@ void Intra16x16PlanePrediction(u8 *data, u8 *above, u8 *left) a = 16 * (above[15] + left[15]); for (i = 0, b = 0; i < 8; i++) - b += ((i32)i + 1) * (above[8+i] - above[6-i]); + b += (i + 1) * (above[8+i] - above[6-i]); b = (5 * b + 32) >> 6; for (i = 0, c = 0; i < 7; i++) - c += ((i32)i + 1) * (left[8+i] - left[6-i]); + c += (i + 1) * (left[8+i] - left[6-i]); /* p[-1,-1] has to be accessed through above pointer */ - c += ((i32)i + 1) * (left[8+i] - above[-1]); + c += (i + 1) * (left[8+i] - above[-1]); c = (5 * c + 32) >> 6; for (i = 0; i < 16; i++) { for (j = 0; j < 16; j++) { - tmp = (a + b * ((i32)j - 7) + c * ((i32)i - 7) + 16) >> 5; + tmp = (a + b * (j - 7) + c * (i - 7) + 16) >> 5; data[i*16+j] = (u8)CLIP1(tmp); } } diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.c index cc838fd..fb97a28 100755 --- a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.c +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.c @@ -186,7 +186,7 @@ u32 h264bsdMoreRbspData(strmData_t *pStrmData) return(HANTRO_FALSE); if ( (bits > 8) || - ((h264bsdShowBits32(pStrmData)>>(32-bits)) != (1 << (bits-1))) ) + ((h264bsdShowBits32(pStrmData)>>(32-bits)) != (1ul << (bits-1))) ) return(HANTRO_TRUE); else return(HANTRO_FALSE); diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.h index cb3adda..216ad04 100755 --- a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.h +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.h @@ -42,6 +42,7 @@ #include <stdio.h> #endif +#include <stdint.h> #include "basetype.h" #include "h264bsd_stream.h" #include "h264bsd_image.h" @@ -150,7 +151,7 @@ } #define ALIGN(ptr, bytePos) \ - (ptr + ( ((bytePos - (int)ptr) & (bytePos - 1)) / sizeof(*ptr) )) + (ptr + ( ((bytePos - (uintptr_t)ptr) & (bytePos - 1)) / sizeof(*ptr) )) extern const u32 h264bsdQpC[52]; diff --git a/media/libstagefright/codecs/raw/SoftRaw.cpp b/media/libstagefright/codecs/raw/SoftRaw.cpp index 19d6f13..9d514a6 100644 --- a/media/libstagefright/codecs/raw/SoftRaw.cpp +++ b/media/libstagefright/codecs/raw/SoftRaw.cpp @@ -163,7 +163,7 @@ OMX_ERRORTYPE SoftRaw::internalSetParameter( } } -void SoftRaw::onQueueFilled(OMX_U32 portIndex) { +void SoftRaw::onQueueFilled(OMX_U32 /* portIndex */) { if (mSignalledError) { return; } diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp index 51bb958..8f356b6 100644 --- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp +++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp @@ -54,6 +54,8 @@ SoftVorbis::SoftVorbis( mAnchorTimeUs(0), mNumFramesOutput(0), mNumFramesLeftOnPage(-1), + mSawInputEos(false), + mSignalledOutputEos(false), mOutputPortSettingsChange(NONE) { initPorts(); CHECK_EQ(initDecoder(), (status_t)OK); @@ -290,48 +292,47 @@ void SoftVorbis::onQueueFilled(OMX_U32 portIndex) { return; } - while (!inQueue.empty() && !outQueue.empty()) { - BufferInfo *inInfo = *inQueue.begin(); - OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; + while ((!inQueue.empty() || (mSawInputEos && !mSignalledOutputEos)) && !outQueue.empty()) { + BufferInfo *inInfo = NULL; + OMX_BUFFERHEADERTYPE *inHeader = NULL; + if (!inQueue.empty()) { + inInfo = *inQueue.begin(); + inHeader = inInfo->mHeader; + } BufferInfo *outInfo = *outQueue.begin(); OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; - if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { - inQueue.erase(inQueue.begin()); - inInfo->mOwnedByUs = false; - notifyEmptyBufferDone(inHeader); + int32_t numPageSamples = 0; - outHeader->nFilledLen = 0; - outHeader->nFlags = OMX_BUFFERFLAG_EOS; + if (inHeader) { + if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { + mSawInputEos = true; + } - outQueue.erase(outQueue.begin()); - outInfo->mOwnedByUs = false; - notifyFillBufferDone(outHeader); - return; - } + if (inHeader->nFilledLen || !mSawInputEos) { + CHECK_GE(inHeader->nFilledLen, sizeof(numPageSamples)); + memcpy(&numPageSamples, + inHeader->pBuffer + + inHeader->nOffset + inHeader->nFilledLen - 4, + sizeof(numPageSamples)); - int32_t numPageSamples; - CHECK_GE(inHeader->nFilledLen, sizeof(numPageSamples)); - memcpy(&numPageSamples, - inHeader->pBuffer - + inHeader->nOffset + inHeader->nFilledLen - 4, - sizeof(numPageSamples)); + if (inHeader->nOffset == 0) { + mAnchorTimeUs = inHeader->nTimeStamp; + mNumFramesOutput = 0; + } - if (numPageSamples >= 0) { - mNumFramesLeftOnPage = numPageSamples; + inHeader->nFilledLen -= sizeof(numPageSamples);; + } } - if (inHeader->nOffset == 0) { - mAnchorTimeUs = inHeader->nTimeStamp; - mNumFramesOutput = 0; + if (numPageSamples >= 0) { + mNumFramesLeftOnPage = numPageSamples; } - inHeader->nFilledLen -= sizeof(numPageSamples);; - ogg_buffer buf; - buf.data = inHeader->pBuffer + inHeader->nOffset; - buf.size = inHeader->nFilledLen; + buf.data = inHeader ? inHeader->pBuffer + inHeader->nOffset : NULL; + buf.size = inHeader ? inHeader->nFilledLen : 0; buf.refcount = 1; buf.ptr.owner = NULL; @@ -351,9 +352,15 @@ void SoftVorbis::onQueueFilled(OMX_U32 portIndex) { int numFrames = 0; + outHeader->nFlags = 0; int err = vorbis_dsp_synthesis(mState, &pack, 1); if (err != 0) { + // FIXME temporary workaround for log spam +#if !defined(__arm__) && !defined(__aarch64__) + ALOGV("vorbis_dsp_synthesis returned %d", err); +#else ALOGW("vorbis_dsp_synthesis returned %d", err); +#endif } else { numFrames = vorbis_dsp_pcmout( mState, (int16_t *)outHeader->pBuffer, @@ -370,13 +377,16 @@ void SoftVorbis::onQueueFilled(OMX_U32 portIndex) { ALOGV("discarding %d frames at end of page", numFrames - mNumFramesLeftOnPage); numFrames = mNumFramesLeftOnPage; + if (mSawInputEos) { + outHeader->nFlags = OMX_BUFFERFLAG_EOS; + mSignalledOutputEos = true; + } } mNumFramesLeftOnPage -= numFrames; } outHeader->nFilledLen = numFrames * sizeof(int16_t) * mVi->channels; outHeader->nOffset = 0; - outHeader->nFlags = 0; outHeader->nTimeStamp = mAnchorTimeUs @@ -384,11 +394,13 @@ void SoftVorbis::onQueueFilled(OMX_U32 portIndex) { mNumFramesOutput += numFrames; - inInfo->mOwnedByUs = false; - inQueue.erase(inQueue.begin()); - inInfo = NULL; - notifyEmptyBufferDone(inHeader); - inHeader = NULL; + if (inHeader) { + inInfo->mOwnedByUs = false; + inQueue.erase(inQueue.begin()); + inInfo = NULL; + notifyEmptyBufferDone(inHeader); + inHeader = NULL; + } outInfo->mOwnedByUs = false; outQueue.erase(outQueue.begin()); @@ -425,6 +437,8 @@ void SoftVorbis::onReset() { mVi = NULL; } + mSawInputEos = false; + mSignalledOutputEos = false; mOutputPortSettingsChange = NONE; } diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h index cb628a0..1d00816 100644 --- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h +++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h @@ -59,6 +59,8 @@ private: int64_t mAnchorTimeUs; int64_t mNumFramesOutput; int32_t mNumFramesLeftOnPage; + bool mSawInputEos; + bool mSignalledOutputEos; enum { NONE, diff --git a/media/libstagefright/foundation/ANetworkSession.cpp b/media/libstagefright/foundation/ANetworkSession.cpp index e629588..4504c2b 100644 --- a/media/libstagefright/foundation/ANetworkSession.cpp +++ b/media/libstagefright/foundation/ANetworkSession.cpp @@ -521,7 +521,7 @@ status_t ANetworkSession::Session::readMore() { return err; } -void ANetworkSession::Session::dumpFragmentStats(const Fragment &frag) { +void ANetworkSession::Session::dumpFragmentStats(const Fragment & /* frag */) { #if 0 int64_t nowUs = ALooper::GetNowUs(); int64_t delayMs = (nowUs - frag.mTimeUs) / 1000ll; @@ -579,7 +579,7 @@ status_t ANetworkSession::Session::writeMore() { if (err == -EAGAIN) { if (!mOutFragments.empty()) { - ALOGI("%d datagrams remain queued.", mOutFragments.size()); + ALOGI("%zu datagrams remain queued.", mOutFragments.size()); } err = OK; } @@ -623,7 +623,7 @@ status_t ANetworkSession::Session::writeMore() { CHECK_EQ(mState, CONNECTED); CHECK(!mOutFragments.empty()); - ssize_t n; + ssize_t n = -1; while (!mOutFragments.empty()) { const Fragment &frag = *mOutFragments.begin(); diff --git a/media/libstagefright/foundation/AString.cpp b/media/libstagefright/foundation/AString.cpp index dee786d..b6b21f1 100644 --- a/media/libstagefright/foundation/AString.cpp +++ b/media/libstagefright/foundation/AString.cpp @@ -189,64 +189,64 @@ void AString::append(const AString &from, size_t offset, size_t n) { void AString::append(int x) { char s[16]; - sprintf(s, "%d", x); - + int result = snprintf(s, sizeof(s), "%d", x); + CHECK((result > 0) && ((size_t) result) < sizeof(s)); append(s); } void AString::append(unsigned x) { char s[16]; - sprintf(s, "%u", x); - + int result = snprintf(s, sizeof(s), "%u", x); + CHECK((result > 0) && ((size_t) result) < sizeof(s)); append(s); } void AString::append(long x) { - char s[16]; - sprintf(s, "%ld", x); - + char s[32]; + int result = snprintf(s, sizeof(s), "%ld", x); + CHECK((result > 0) && ((size_t) result) < sizeof(s)); append(s); } void AString::append(unsigned long x) { - char s[16]; - sprintf(s, "%lu", x); - + char s[32]; + int result = snprintf(s, sizeof(s), "%lu", x); + CHECK((result > 0) && ((size_t) result) < sizeof(s)); append(s); } void AString::append(long long x) { char s[32]; - sprintf(s, "%lld", x); - + int result = snprintf(s, sizeof(s), "%lld", x); + CHECK((result > 0) && ((size_t) result) < sizeof(s)); append(s); } void AString::append(unsigned long long x) { char s[32]; - sprintf(s, "%llu", x); - + int result = snprintf(s, sizeof(s), "%llu", x); + CHECK((result > 0) && ((size_t) result) < sizeof(s)); append(s); } void AString::append(float x) { char s[16]; - sprintf(s, "%f", x); - + int result = snprintf(s, sizeof(s), "%f", x); + CHECK((result > 0) && ((size_t) result) < sizeof(s)); append(s); } void AString::append(double x) { char s[16]; - sprintf(s, "%f", x); - + int result = snprintf(s, sizeof(s), "%f", x); + CHECK((result > 0) && ((size_t) result) < sizeof(s)); append(s); } void AString::append(void *x) { - char s[16]; - sprintf(s, "%p", x); - + char s[32]; + int result = snprintf(s, sizeof(s), "%p", x); + CHECK((result > 0) && ((size_t) result) < sizeof(s)); append(s); } diff --git a/media/libstagefright/foundation/Android.mk b/media/libstagefright/foundation/Android.mk index ad2dab5..90a6a23 100644 --- a/media/libstagefright/foundation/Android.mk +++ b/media/libstagefright/foundation/Android.mk @@ -24,7 +24,7 @@ LOCAL_SHARED_LIBRARIES := \ libutils \ liblog -LOCAL_CFLAGS += -Wno-multichar +LOCAL_CFLAGS += -Wno-multichar -Werror LOCAL_MODULE:= libstagefright_foundation diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp index bd12ddc..6d48ab7 100644 --- a/media/libstagefright/httplive/LiveSession.cpp +++ b/media/libstagefright/httplive/LiveSession.cpp @@ -37,7 +37,10 @@ #include <media/stagefright/MetaData.h> #include <media/stagefright/Utils.h> +#include <utils/Mutex.h> + #include <ctype.h> +#include <inttypes.h> #include <openssl/aes.h> #include <openssl/md5.h> @@ -57,32 +60,57 @@ LiveSession::LiveSession( : 0)), mPrevBandwidthIndex(-1), mStreamMask(0), + mNewStreamMask(0), + mSwapMask(0), mCheckBandwidthGeneration(0), + mSwitchGeneration(0), mLastDequeuedTimeUs(0ll), mRealTimeBaseUs(0ll), mReconfigurationInProgress(false), - mDisconnectReplyID(0) { + mSwitchInProgress(false), + mDisconnectReplyID(0), + mSeekReplyID(0) { if (mUIDValid) { mHTTPDataSource->setUID(mUID); } - mPacketSources.add( - STREAMTYPE_AUDIO, new AnotherPacketSource(NULL /* meta */)); - - mPacketSources.add( - STREAMTYPE_VIDEO, new AnotherPacketSource(NULL /* meta */)); + mStreams[kAudioIndex] = StreamItem("audio"); + mStreams[kVideoIndex] = StreamItem("video"); + mStreams[kSubtitleIndex] = StreamItem("subtitles"); - mPacketSources.add( - STREAMTYPE_SUBTITLES, new AnotherPacketSource(NULL /* meta */)); + for (size_t i = 0; i < kMaxStreams; ++i) { + mPacketSources.add(indexToType(i), new AnotherPacketSource(NULL /* meta */)); + mPacketSources2.add(indexToType(i), new AnotherPacketSource(NULL /* meta */)); + } } LiveSession::~LiveSession() { } +sp<ABuffer> LiveSession::createFormatChangeBuffer(bool swap) { + ABuffer *discontinuity = new ABuffer(0); + discontinuity->meta()->setInt32("discontinuity", ATSParser::DISCONTINUITY_FORMATCHANGE); + discontinuity->meta()->setInt32("swapPacketSource", swap); + discontinuity->meta()->setInt32("switchGeneration", mSwitchGeneration); + discontinuity->meta()->setInt64("timeUs", -1); + return discontinuity; +} + +void LiveSession::swapPacketSource(StreamType stream) { + sp<AnotherPacketSource> &aps = mPacketSources.editValueFor(stream); + sp<AnotherPacketSource> &aps2 = mPacketSources2.editValueFor(stream); + sp<AnotherPacketSource> tmp = aps; + aps = aps2; + aps2 = tmp; + aps2->clear(); +} + status_t LiveSession::dequeueAccessUnit( StreamType stream, sp<ABuffer> *accessUnit) { if (!(mStreamMask & stream)) { - return UNKNOWN_ERROR; + // return -EWOULDBLOCK to avoid halting the decoder + // when switching between audio/video and audio only. + return -EWOULDBLOCK; } sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream); @@ -122,11 +150,30 @@ status_t LiveSession::dequeueAccessUnit( streamStr, type, extra == NULL ? "NULL" : extra->debugString().c_str()); + + int32_t swap; + if (type == ATSParser::DISCONTINUITY_FORMATCHANGE + && (*accessUnit)->meta()->findInt32("swapPacketSource", &swap) + && swap) { + + int32_t switchGeneration; + CHECK((*accessUnit)->meta()->findInt32("switchGeneration", &switchGeneration)); + { + Mutex::Autolock lock(mSwapMutex); + if (switchGeneration == mSwitchGeneration) { + swapPacketSource(stream); + sp<AMessage> msg = new AMessage(kWhatSwapped, id()); + msg->setInt32("stream", stream); + msg->setInt32("switchGeneration", switchGeneration); + msg->post(); + } + } + } } else if (err == OK) { if (stream == STREAMTYPE_AUDIO || stream == STREAMTYPE_VIDEO) { int64_t timeUs; CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs)); - ALOGV("[%s] read buffer at time %lld us", streamStr, timeUs); + ALOGV("[%s] read buffer at time %" PRId64 " us", streamStr, timeUs); mLastDequeuedTimeUs = timeUs; mRealTimeBaseUs = ALooper::GetNowUs() - timeUs; @@ -143,6 +190,7 @@ status_t LiveSession::dequeueAccessUnit( } status_t LiveSession::getStreamFormat(StreamType stream, sp<AMessage> *format) { + // No swapPacketSource race condition; called from the same thread as dequeueAccessUnit. if (!(mStreamMask & stream)) { return UNKNOWN_ERROR; } @@ -188,6 +236,10 @@ status_t LiveSession::seekTo(int64_t timeUs) { sp<AMessage> response; status_t err = msg->postAndAwaitResponse(&response); + uint32_t replyID; + CHECK(response == mSeekReply && 0 != mSeekReplyID); + mSeekReply.clear(); + mSeekReplyID = 0; return err; } @@ -213,15 +265,12 @@ void LiveSession::onMessageReceived(const sp<AMessage> &msg) { case kWhatSeek: { - uint32_t replyID; - CHECK(msg->senderAwaitsResponse(&replyID)); + CHECK(msg->senderAwaitsResponse(&mSeekReplyID)); status_t err = onSeek(msg); - sp<AMessage> response = new AMessage; - response->setInt32("err", err); - - response->postReply(replyID); + mSeekReply = new AMessage; + mSeekReply->setInt32("err", err); break; } @@ -239,13 +288,23 @@ void LiveSession::onMessageReceived(const sp<AMessage> &msg) { if (what == PlaylistFetcher::kWhatStopped) { AString uri; CHECK(msg->findString("uri", &uri)); - mFetcherInfos.removeItem(uri); + if (mFetcherInfos.removeItem(uri) < 0) { + // ignore duplicated kWhatStopped messages. + break; + } + + tryToFinishBandwidthSwitch(); } if (mContinuation != NULL) { CHECK_GT(mContinuationCounter, 0); if (--mContinuationCounter == 0) { mContinuation->post(); + + if (mSeekReplyID != 0) { + CHECK(mSeekReply != NULL); + mSeekReply->postReply(mSeekReplyID); + } } } break; @@ -275,6 +334,8 @@ void LiveSession::onMessageReceived(const sp<AMessage> &msg) { postPrepared(err); } + cancelBandwidthSwitch(); + mPacketSources.valueFor(STREAMTYPE_AUDIO)->signalEOS(err); mPacketSources.valueFor(STREAMTYPE_VIDEO)->signalEOS(err); @@ -313,6 +374,27 @@ void LiveSession::onMessageReceived(const sp<AMessage> &msg) { break; } + case PlaylistFetcher::kWhatStartedAt: + { + int32_t switchGeneration; + CHECK(msg->findInt32("switchGeneration", &switchGeneration)); + + if (switchGeneration != mSwitchGeneration) { + break; + } + + // Resume fetcher for the original variant; the resumed fetcher should + // continue until the timestamps found in msg, which is stored by the + // new fetcher to indicate where the new variant has started buffering. + for (size_t i = 0; i < mFetcherInfos.size(); i++) { + const FetcherInfo info = mFetcherInfos.valueAt(i); + if (info.mToBeRemoved) { + info.mFetcher->resumeUntilAsync(msg); + } + } + break; + } + default: TRESPASS(); } @@ -357,6 +439,11 @@ void LiveSession::onMessageReceived(const sp<AMessage> &msg) { break; } + case kWhatSwapped: + { + onSwapped(msg); + break; + } default: TRESPASS(); break; @@ -374,6 +461,12 @@ int LiveSession::SortByBandwidth(const BandwidthItem *a, const BandwidthItem *b) return 1; } +// static +LiveSession::StreamType LiveSession::indexToType(int idx) { + CHECK(idx >= 0 && idx < kMaxStreams); + return (StreamType)(1 << idx); +} + void LiveSession::onConnect(const sp<AMessage> &msg) { AString url; CHECK(msg->findString("url", &url)); @@ -400,7 +493,7 @@ void LiveSession::onConnect(const sp<AMessage> &msg) { mPlaylist = fetchPlaylist(url.c_str(), NULL /* curPlaylistHash */, &dummy); if (mPlaylist == NULL) { - ALOGE("unable to fetch master playlist '%s'.", url.c_str()); + ALOGE("unable to fetch master playlist <URL suppressed>."); postPrepared(ERROR_IO); return; @@ -461,6 +554,10 @@ void LiveSession::finishDisconnect() { // during disconnection either. cancelCheckBandwidthEvent(); + // Protect mPacketSources from a swapPacketSource race condition through disconnect. + // (finishDisconnect, onFinishDisconnect2) + cancelBandwidthSwitch(); + for (size_t i = 0; i < mFetcherInfos.size(); ++i) { mFetcherInfos.valueAt(i).mFetcher->stopAsync(); } @@ -500,11 +597,13 @@ sp<PlaylistFetcher> LiveSession::addFetcher(const char *uri) { sp<AMessage> notify = new AMessage(kWhatFetcherNotify, id()); notify->setString("uri", uri); + notify->setInt32("switchGeneration", mSwitchGeneration); FetcherInfo info; info.mFetcher = new PlaylistFetcher(notify, this, uri); info.mDurationUs = -1ll; info.mIsPrepared = false; + info.mToBeRemoved = false; looper()->registerHandler(info.mFetcher); mFetcherInfos.add(uri, info); @@ -512,56 +611,85 @@ sp<PlaylistFetcher> LiveSession::addFetcher(const char *uri) { return info.mFetcher; } -status_t LiveSession::fetchFile( +/* + * Illustration of parameters: + * + * 0 `range_offset` + * +------------+-------------------------------------------------------+--+--+ + * | | | next block to fetch | | | + * | | `source` handle => `out` buffer | | | | + * | `url` file |<--------- buffer size --------->|<--- `block_size` -->| | | + * | |<----------- `range_length` / buffer capacity ----------->| | + * |<------------------------------ file_size ------------------------------->| + * + * Special parameter values: + * - range_length == -1 means entire file + * - block_size == 0 means entire range + * + */ +ssize_t LiveSession::fetchFile( const char *url, sp<ABuffer> *out, - int64_t range_offset, int64_t range_length) { - *out = NULL; + int64_t range_offset, int64_t range_length, + uint32_t block_size, /* download block size */ + sp<DataSource> *source, /* to return and reuse source */ + String8 *actualUrl) { + off64_t size; + sp<DataSource> temp_source; + if (source == NULL) { + source = &temp_source; + } - sp<DataSource> source; + if (*source == NULL) { + if (!strncasecmp(url, "file://", 7)) { + *source = new FileSource(url + 7); + } else if (strncasecmp(url, "http://", 7) + && strncasecmp(url, "https://", 8)) { + return ERROR_UNSUPPORTED; + } else { + KeyedVector<String8, String8> headers = mExtraHeaders; + if (range_offset > 0 || range_length >= 0) { + headers.add( + String8("Range"), + String8( + StringPrintf( + "bytes=%lld-%s", + range_offset, + range_length < 0 + ? "" : StringPrintf("%lld", + range_offset + range_length - 1).c_str()).c_str())); + } + status_t err = mHTTPDataSource->connect(url, &headers); - if (!strncasecmp(url, "file://", 7)) { - source = new FileSource(url + 7); - } else if (strncasecmp(url, "http://", 7) - && strncasecmp(url, "https://", 8)) { - return ERROR_UNSUPPORTED; - } else { - KeyedVector<String8, String8> headers = mExtraHeaders; - if (range_offset > 0 || range_length >= 0) { - headers.add( - String8("Range"), - String8( - StringPrintf( - "bytes=%lld-%s", - range_offset, - range_length < 0 - ? "" : StringPrintf("%lld", range_offset + range_length - 1).c_str()).c_str())); - } - status_t err = mHTTPDataSource->connect(url, &headers); + if (err != OK) { + return err; + } - if (err != OK) { - return err; + *source = mHTTPDataSource; } - - source = mHTTPDataSource; } - off64_t size; - status_t err = source->getSize(&size); - - if (err != OK) { + status_t getSizeErr = (*source)->getSize(&size); + if (getSizeErr != OK) { size = 65536; } - sp<ABuffer> buffer = new ABuffer(size); - buffer->setRange(0, 0); + sp<ABuffer> buffer = *out != NULL ? *out : new ABuffer(size); + if (*out == NULL) { + buffer->setRange(0, 0); + } + ssize_t bytesRead = 0; + // adjust range_length if only reading partial block + if (block_size > 0 && (range_length == -1 || buffer->size() + block_size < range_length)) { + range_length = buffer->size() + block_size; + } for (;;) { + // Only resize when we don't know the size. size_t bufferRemaining = buffer->capacity() - buffer->size(); - - if (bufferRemaining == 0) { + if (bufferRemaining == 0 && getSizeErr != OK) { bufferRemaining = 32768; - ALOGV("increasing download buffer to %d bytes", + ALOGV("increasing download buffer to %zu bytes", buffer->size() + bufferRemaining); sp<ABuffer> copy = new ABuffer(buffer->size() + bufferRemaining); @@ -574,7 +702,7 @@ status_t LiveSession::fetchFile( size_t maxBytesToRead = bufferRemaining; if (range_length >= 0) { int64_t bytesLeftInRange = range_length - buffer->size(); - if (bytesLeftInRange < maxBytesToRead) { + if (bytesLeftInRange < (int64_t)maxBytesToRead) { maxBytesToRead = bytesLeftInRange; if (bytesLeftInRange == 0) { @@ -583,7 +711,9 @@ status_t LiveSession::fetchFile( } } - ssize_t n = source->readAt( + // The DataSource is responsible for informing us of error (n < 0) or eof (n == 0) + // to help us break out of the loop. + ssize_t n = (*source)->readAt( buffer->size(), buffer->data() + buffer->size(), maxBytesToRead); @@ -596,11 +726,18 @@ status_t LiveSession::fetchFile( } buffer->setRange(0, buffer->size() + (size_t)n); + bytesRead += n; } *out = buffer; + if (actualUrl != NULL) { + *actualUrl = (*source)->getUri(); + if (actualUrl->isEmpty()) { + *actualUrl = url; + } + } - return OK; + return bytesRead; } sp<M3UParser> LiveSession::fetchPlaylist( @@ -610,9 +747,10 @@ sp<M3UParser> LiveSession::fetchPlaylist( *unchanged = false; sp<ABuffer> buffer; - status_t err = fetchFile(url, &buffer); + String8 actualUrl; + ssize_t err = fetchFile(url, &buffer, 0, -1, 0, NULL, &actualUrl); - if (err != OK) { + if (err <= 0) { return NULL; } @@ -632,9 +770,6 @@ sp<M3UParser> LiveSession::fetchPlaylist( // playlist unchanged *unchanged = true; - ALOGV("Playlist unchanged, refresh state is now %d", - (int)mRefreshState); - return NULL; } @@ -644,7 +779,7 @@ sp<M3UParser> LiveSession::fetchPlaylist( #endif sp<M3UParser> playlist = - new M3UParser(url, buffer->data(), buffer->size()); + new M3UParser(actualUrl.string(), buffer->data(), buffer->size()); if (playlist->initCheck() != OK) { ALOGE("failed to parse .m3u8 playlist"); @@ -810,14 +945,31 @@ status_t LiveSession::selectTrack(size_t index, bool select) { return err; } +bool LiveSession::canSwitchUp() { + // Allow upwards bandwidth switch when a stream has buffered at least 10 seconds. + status_t err = OK; + for (size_t i = 0; i < mPacketSources.size(); ++i) { + sp<AnotherPacketSource> source = mPacketSources.valueAt(i); + int64_t dur = source->getBufferedDurationUs(&err); + if (err == OK && dur > 10000000) { + return true; + } + } + return false; +} + void LiveSession::changeConfiguration( int64_t timeUs, size_t bandwidthIndex, bool pickTrack) { + // Protect mPacketSources from a swapPacketSource race condition through reconfiguration. + // (changeConfiguration, onChangeConfiguration2, onChangeConfiguration3). + cancelBandwidthSwitch(); + CHECK(!mReconfigurationInProgress); mReconfigurationInProgress = true; mPrevBandwidthIndex = bandwidthIndex; - ALOGV("changeConfiguration => timeUs:%lld us, bwIndex:%d, pickTrack:%d", + ALOGV("changeConfiguration => timeUs:%" PRId64 " us, bwIndex:%zu, pickTrack:%d", timeUs, bandwidthIndex, pickTrack); if (pickTrack) { @@ -827,21 +979,14 @@ void LiveSession::changeConfiguration( CHECK_LT(bandwidthIndex, mBandwidthItems.size()); const BandwidthItem &item = mBandwidthItems.itemAt(bandwidthIndex); - uint32_t streamMask = 0; - - AString audioURI; - if (mPlaylist->getAudioURI(item.mPlaylistIndex, &audioURI)) { - streamMask |= STREAMTYPE_AUDIO; - } - - AString videoURI; - if (mPlaylist->getVideoURI(item.mPlaylistIndex, &videoURI)) { - streamMask |= STREAMTYPE_VIDEO; - } + uint32_t streamMask = 0; // streams that should be fetched by the new fetcher + uint32_t resumeMask = 0; // streams that should be fetched by the original fetcher - AString subtitleURI; - if (mPlaylist->getSubtitleURI(item.mPlaylistIndex, &subtitleURI)) { - streamMask |= STREAMTYPE_SUBTITLES; + AString URIs[kMaxStreams]; + for (size_t i = 0; i < kMaxStreams; ++i) { + if (mPlaylist->getTypeURI(item.mPlaylistIndex, mStreams[i].mType, &URIs[i])) { + streamMask |= indexToType(i); + } } // Step 1, stop and discard fetchers that are no longer needed. @@ -853,10 +998,15 @@ void LiveSession::changeConfiguration( // If we're seeking all current fetchers are discarded. if (timeUs < 0ll) { - if (((streamMask & STREAMTYPE_AUDIO) && uri == audioURI) - || ((streamMask & STREAMTYPE_VIDEO) && uri == videoURI) - || ((streamMask & STREAMTYPE_SUBTITLES) && uri == subtitleURI)) { - discardFetcher = false; + // delay fetcher removal + discardFetcher = false; + + for (size_t j = 0; j < kMaxStreams; ++j) { + StreamType type = indexToType(j); + if ((streamMask & type) && uri == URIs[j]) { + resumeMask |= type; + streamMask &= ~type; + } } } @@ -867,17 +1017,20 @@ void LiveSession::changeConfiguration( } } - sp<AMessage> msg = new AMessage(kWhatChangeConfiguration2, id()); + sp<AMessage> msg; + if (timeUs < 0ll) { + // skip onChangeConfiguration2 (decoder destruction) if switching. + msg = new AMessage(kWhatChangeConfiguration3, id()); + } else { + msg = new AMessage(kWhatChangeConfiguration2, id()); + } msg->setInt32("streamMask", streamMask); + msg->setInt32("resumeMask", resumeMask); msg->setInt64("timeUs", timeUs); - if (streamMask & STREAMTYPE_AUDIO) { - msg->setString("audioURI", audioURI.c_str()); - } - if (streamMask & STREAMTYPE_VIDEO) { - msg->setString("videoURI", videoURI.c_str()); - } - if (streamMask & STREAMTYPE_SUBTITLES) { - msg->setString("subtitleURI", subtitleURI.c_str()); + for (size_t i = 0; i < kMaxStreams; ++i) { + if (streamMask & indexToType(i)) { + msg->setString(mStreams[i].uriKey().c_str(), URIs[i].c_str()); + } } // Every time a fetcher acknowledges the stopAsync or pauseAsync request @@ -889,6 +1042,11 @@ void LiveSession::changeConfiguration( if (mContinuationCounter == 0) { msg->post(); + + if (mSeekReplyID != 0) { + CHECK(mSeekReply != NULL); + mSeekReply->postReply(mSeekReplyID); + } } } @@ -908,18 +1066,13 @@ void LiveSession::onChangeConfiguration2(const sp<AMessage> &msg) { uint32_t streamMask; CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask)); - AString audioURI, videoURI, subtitleURI; - if (streamMask & STREAMTYPE_AUDIO) { - CHECK(msg->findString("audioURI", &audioURI)); - ALOGV("audioURI = '%s'", audioURI.c_str()); - } - if (streamMask & STREAMTYPE_VIDEO) { - CHECK(msg->findString("videoURI", &videoURI)); - ALOGV("videoURI = '%s'", videoURI.c_str()); - } - if (streamMask & STREAMTYPE_SUBTITLES) { - CHECK(msg->findString("subtitleURI", &subtitleURI)); - ALOGV("subtitleURI = '%s'", subtitleURI.c_str()); + AString URIs[kMaxStreams]; + for (size_t i = 0; i < kMaxStreams; ++i) { + if (streamMask & indexToType(i)) { + const AString &uriKey = mStreams[i].uriKey(); + CHECK(msg->findString(uriKey.c_str(), &URIs[i])); + ALOGV("%s = '%s'", uriKey.c_str(), URIs[i].c_str()); + } } // Determine which decoders to shutdown on the player side, @@ -929,15 +1082,12 @@ void LiveSession::onChangeConfiguration2(const sp<AMessage> &msg) { // 2) its streamtype was already active and still is but the URI // has changed. uint32_t changedMask = 0; - if (((mStreamMask & streamMask & STREAMTYPE_AUDIO) - && !(audioURI == mAudioURI)) - || (mStreamMask & ~streamMask & STREAMTYPE_AUDIO)) { - changedMask |= STREAMTYPE_AUDIO; - } - if (((mStreamMask & streamMask & STREAMTYPE_VIDEO) - && !(videoURI == mVideoURI)) - || (mStreamMask & ~streamMask & STREAMTYPE_VIDEO)) { - changedMask |= STREAMTYPE_VIDEO; + for (size_t i = 0; i < kMaxStreams && i != kSubtitleIndex; ++i) { + if (((mStreamMask & streamMask & indexToType(i)) + && !(URIs[i] == mStreams[i].mUri)) + || (mStreamMask & ~streamMask & indexToType(i))) { + changedMask |= indexToType(i); + } } if (changedMask == 0) { @@ -963,68 +1113,54 @@ void LiveSession::onChangeConfiguration2(const sp<AMessage> &msg) { } void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) { + mContinuation.clear(); // All remaining fetchers are still suspended, the player has shutdown // any decoders that needed it. - uint32_t streamMask; + uint32_t streamMask, resumeMask; CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask)); + CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask)); - AString audioURI, videoURI, subtitleURI; - if (streamMask & STREAMTYPE_AUDIO) { - CHECK(msg->findString("audioURI", &audioURI)); - } - if (streamMask & STREAMTYPE_VIDEO) { - CHECK(msg->findString("videoURI", &videoURI)); - } - if (streamMask & STREAMTYPE_SUBTITLES) { - CHECK(msg->findString("subtitleURI", &subtitleURI)); + for (size_t i = 0; i < kMaxStreams; ++i) { + if (streamMask & indexToType(i)) { + CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mUri)); + } } int64_t timeUs; + bool switching = false; CHECK(msg->findInt64("timeUs", &timeUs)); if (timeUs < 0ll) { timeUs = mLastDequeuedTimeUs; + switching = true; } mRealTimeBaseUs = ALooper::GetNowUs() - timeUs; - mStreamMask = streamMask; - mAudioURI = audioURI; - mVideoURI = videoURI; - mSubtitleURI = subtitleURI; + mNewStreamMask = streamMask; - // Resume all existing fetchers and assign them packet sources. + // Of all existing fetchers: + // * Resume fetchers that are still needed and assign them original packet sources. + // * Mark otherwise unneeded fetchers for removal. + ALOGV("resuming fetchers for mask 0x%08x", resumeMask); for (size_t i = 0; i < mFetcherInfos.size(); ++i) { const AString &uri = mFetcherInfos.keyAt(i); - uint32_t resumeMask = 0; - - sp<AnotherPacketSource> audioSource; - if ((streamMask & STREAMTYPE_AUDIO) && uri == audioURI) { - audioSource = mPacketSources.valueFor(STREAMTYPE_AUDIO); - resumeMask |= STREAMTYPE_AUDIO; - } - - sp<AnotherPacketSource> videoSource; - if ((streamMask & STREAMTYPE_VIDEO) && uri == videoURI) { - videoSource = mPacketSources.valueFor(STREAMTYPE_VIDEO); - resumeMask |= STREAMTYPE_VIDEO; + sp<AnotherPacketSource> sources[kMaxStreams]; + for (size_t j = 0; j < kMaxStreams; ++j) { + if ((resumeMask & indexToType(j)) && uri == mStreams[j].mUri) { + sources[j] = mPacketSources.valueFor(indexToType(j)); + } } - sp<AnotherPacketSource> subtitleSource; - if ((streamMask & STREAMTYPE_SUBTITLES) && uri == subtitleURI) { - subtitleSource = mPacketSources.valueFor(STREAMTYPE_SUBTITLES); - resumeMask |= STREAMTYPE_SUBTITLES; + FetcherInfo &info = mFetcherInfos.editValueAt(i); + if (sources[kAudioIndex] != NULL || sources[kVideoIndex] != NULL + || sources[kSubtitleIndex] != NULL) { + info.mFetcher->startAsync( + sources[kAudioIndex], sources[kVideoIndex], sources[kSubtitleIndex]); + } else { + info.mToBeRemoved = true; } - - CHECK_NE(resumeMask, 0u); - - ALOGV("resuming fetchers for mask 0x%08x", resumeMask); - - streamMask &= ~resumeMask; - - mFetcherInfos.valueAt(i).mFetcher->startAsync( - audioSource, videoSource, subtitleSource); } // streamMask now only contains the types that need a new fetcher created. @@ -1033,52 +1169,65 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) { ALOGV("creating new fetchers for mask 0x%08x", streamMask); } - while (streamMask != 0) { - StreamType streamType = (StreamType)(streamMask & ~(streamMask - 1)); + // Find out when the original fetchers have buffered up to and start the new fetchers + // at a later timestamp. + for (size_t i = 0; i < kMaxStreams; i++) { + if (!(indexToType(i) & streamMask)) { + continue; + } AString uri; - switch (streamType) { - case STREAMTYPE_AUDIO: - uri = audioURI; - break; - case STREAMTYPE_VIDEO: - uri = videoURI; - break; - case STREAMTYPE_SUBTITLES: - uri = subtitleURI; - break; - default: - TRESPASS(); - } + uri = mStreams[i].mUri; sp<PlaylistFetcher> fetcher = addFetcher(uri.c_str()); CHECK(fetcher != NULL); - sp<AnotherPacketSource> audioSource; - if ((streamMask & STREAMTYPE_AUDIO) && uri == audioURI) { - audioSource = mPacketSources.valueFor(STREAMTYPE_AUDIO); - audioSource->clear(); - - streamMask &= ~STREAMTYPE_AUDIO; - } - - sp<AnotherPacketSource> videoSource; - if ((streamMask & STREAMTYPE_VIDEO) && uri == videoURI) { - videoSource = mPacketSources.valueFor(STREAMTYPE_VIDEO); - videoSource->clear(); - - streamMask &= ~STREAMTYPE_VIDEO; - } + int32_t latestSeq = -1; + int64_t latestTimeUs = 0ll; + sp<AnotherPacketSource> sources[kMaxStreams]; + + // TRICKY: looping from i as earlier streams are already removed from streamMask + for (size_t j = i; j < kMaxStreams; ++j) { + if ((streamMask & indexToType(j)) && uri == mStreams[j].mUri) { + sources[j] = mPacketSources.valueFor(indexToType(j)); + + if (!switching) { + sources[j]->clear(); + } else { + int32_t type, seq; + int64_t srcTimeUs; + sp<AMessage> meta = sources[j]->getLatestMeta(); + + if (meta != NULL && !meta->findInt32("discontinuity", &type)) { + CHECK(meta->findInt32("seq", &seq)); + if (seq > latestSeq) { + latestSeq = seq; + } + CHECK(meta->findInt64("timeUs", &srcTimeUs)); + if (srcTimeUs > latestTimeUs) { + latestTimeUs = srcTimeUs; + } + } - sp<AnotherPacketSource> subtitleSource; - if ((streamMask & STREAMTYPE_SUBTITLES) && uri == subtitleURI) { - subtitleSource = mPacketSources.valueFor(STREAMTYPE_SUBTITLES); - subtitleSource->clear(); + sources[j] = mPacketSources2.valueFor(indexToType(j)); + sources[j]->clear(); + uint32_t extraStreams = mNewStreamMask & (~mStreamMask); + if (extraStreams & indexToType(j)) { + sources[j]->queueAccessUnit(createFormatChangeBuffer(/* swap = */ false)); + } + } - streamMask &= ~STREAMTYPE_SUBTITLES; + streamMask &= ~indexToType(j); + } } - fetcher->startAsync(audioSource, videoSource, subtitleSource, timeUs); + fetcher->startAsync( + sources[kAudioIndex], + sources[kVideoIndex], + sources[kSubtitleIndex], + timeUs, + latestTimeUs /* min start time(us) */, + latestSeq >= 0 ? latestSeq + 1 : -1 /* starting sequence number hint */ ); } // All fetchers have now been started, the configuration change @@ -1087,14 +1236,61 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) { scheduleCheckBandwidthEvent(); ALOGV("XXX configuration change completed."); - mReconfigurationInProgress = false; + if (switching) { + mSwitchInProgress = true; + } else { + mStreamMask = mNewStreamMask; + } if (mDisconnectReplyID != 0) { finishDisconnect(); } } +void LiveSession::onSwapped(const sp<AMessage> &msg) { + int32_t switchGeneration; + CHECK(msg->findInt32("switchGeneration", &switchGeneration)); + if (switchGeneration != mSwitchGeneration) { + return; + } + + int32_t stream; + CHECK(msg->findInt32("stream", &stream)); + mSwapMask |= stream; + if (mSwapMask != mStreamMask) { + return; + } + + // Check if new variant contains extra streams. + uint32_t extraStreams = mNewStreamMask & (~mStreamMask); + while (extraStreams) { + StreamType extraStream = (StreamType) (extraStreams & ~(extraStreams - 1)); + swapPacketSource(extraStream); + extraStreams &= ~extraStream; + } + + tryToFinishBandwidthSwitch(); +} + +// Mark switch done when: +// 1. all old buffers are swapped out, AND +// 2. all old fetchers are removed. +void LiveSession::tryToFinishBandwidthSwitch() { + bool needToRemoveFetchers = false; + for (size_t i = 0; i < mFetcherInfos.size(); ++i) { + if (mFetcherInfos.valueAt(i).mToBeRemoved) { + needToRemoveFetchers = true; + break; + } + } + if (!needToRemoveFetchers && mSwapMask == mStreamMask) { + mStreamMask = mNewStreamMask; + mSwitchInProgress = false; + mSwapMask = 0; + } +} + void LiveSession::scheduleCheckBandwidthEvent() { sp<AMessage> msg = new AMessage(kWhatCheckBandwidth, id()); msg->setInt32("generation", mCheckBandwidthGeneration); @@ -1105,16 +1301,37 @@ void LiveSession::cancelCheckBandwidthEvent() { ++mCheckBandwidthGeneration; } -void LiveSession::onCheckBandwidth() { - if (mReconfigurationInProgress) { - scheduleCheckBandwidthEvent(); - return; +void LiveSession::cancelBandwidthSwitch() { + Mutex::Autolock lock(mSwapMutex); + mSwitchGeneration++; + mSwitchInProgress = false; + mSwapMask = 0; +} + +bool LiveSession::canSwitchBandwidthTo(size_t bandwidthIndex) { + if (mReconfigurationInProgress || mSwitchInProgress) { + return false; + } + + if (mPrevBandwidthIndex < 0) { + return true; } + if (bandwidthIndex == (size_t)mPrevBandwidthIndex) { + return false; + } else if (bandwidthIndex > (size_t)mPrevBandwidthIndex) { + return canSwitchUp(); + } else { + return true; + } +} + +void LiveSession::onCheckBandwidth() { size_t bandwidthIndex = getBandwidthIndex(); - if (mPrevBandwidthIndex < 0 - || bandwidthIndex != (size_t)mPrevBandwidthIndex) { + if (canSwitchBandwidthTo(bandwidthIndex)) { changeConfiguration(-1ll /* timeUs */, bandwidthIndex); + } else { + scheduleCheckBandwidthEvent(); } // Handling the kWhatCheckBandwidth even here does _not_ automatically diff --git a/media/libstagefright/httplive/LiveSession.h b/media/libstagefright/httplive/LiveSession.h index 99b480a8..3f8fee5 100644 --- a/media/libstagefright/httplive/LiveSession.h +++ b/media/libstagefright/httplive/LiveSession.h @@ -42,10 +42,17 @@ struct LiveSession : public AHandler { const sp<AMessage> ¬ify, uint32_t flags = 0, bool uidValid = false, uid_t uid = 0); + enum StreamIndex { + kAudioIndex = 0, + kVideoIndex = 1, + kSubtitleIndex = 2, + kMaxStreams = 3, + }; + enum StreamType { - STREAMTYPE_AUDIO = 1, - STREAMTYPE_VIDEO = 2, - STREAMTYPE_SUBTITLES = 4, + STREAMTYPE_AUDIO = 1 << kAudioIndex, + STREAMTYPE_VIDEO = 1 << kVideoIndex, + STREAMTYPE_SUBTITLES = 1 << kSubtitleIndex, }; status_t dequeueAccessUnit(StreamType stream, sp<ABuffer> *accessUnit); @@ -74,6 +81,11 @@ struct LiveSession : public AHandler { kWhatPreparationFailed, }; + // create a format-change discontinuity + // + // swap: + // whether is format-change discontinuity should trigger a buffer swap + sp<ABuffer> createFormatChangeBuffer(bool swap = true); protected: virtual ~LiveSession(); @@ -92,6 +104,7 @@ private: kWhatChangeConfiguration2 = 'chC2', kWhatChangeConfiguration3 = 'chC3', kWhatFinishDisconnect2 = 'fin2', + kWhatSwapped = 'swap', }; struct BandwidthItem { @@ -103,8 +116,22 @@ private: sp<PlaylistFetcher> mFetcher; int64_t mDurationUs; bool mIsPrepared; + bool mToBeRemoved; }; + struct StreamItem { + const char *mType; + AString mUri; + StreamItem() : mType("") {} + StreamItem(const char *type) : mType(type) {} + AString uriKey() { + AString key(mType); + key.append("URI"); + return key; + } + }; + StreamItem mStreams[kMaxStreams]; + sp<AMessage> mNotify; uint32_t mFlags; bool mUIDValid; @@ -123,21 +150,40 @@ private: sp<M3UParser> mPlaylist; KeyedVector<AString, FetcherInfo> mFetcherInfos; - AString mAudioURI, mVideoURI, mSubtitleURI; uint32_t mStreamMask; + // Masks used during reconfiguration: + // mNewStreamMask: streams in the variant playlist we're switching to; + // we don't want to immediately overwrite the original value. + uint32_t mNewStreamMask; + + // mSwapMask: streams that have started to playback content in the new variant playlist; + // we use this to track reconfiguration progress. + uint32_t mSwapMask; + KeyedVector<StreamType, sp<AnotherPacketSource> > mPacketSources; + // A second set of packet sources that buffer content for the variant we're switching to. + KeyedVector<StreamType, sp<AnotherPacketSource> > mPacketSources2; + + // A mutex used to serialize two sets of events: + // * the swapping of packet sources in dequeueAccessUnit on the player thread, AND + // * a forced bandwidth switch termination in cancelSwitch on the live looper. + Mutex mSwapMutex; int32_t mCheckBandwidthGeneration; + int32_t mSwitchGeneration; size_t mContinuationCounter; sp<AMessage> mContinuation; + sp<AMessage> mSeekReply; int64_t mLastDequeuedTimeUs; int64_t mRealTimeBaseUs; bool mReconfigurationInProgress; + bool mSwitchInProgress; uint32_t mDisconnectReplyID; + uint32_t mSeekReplyID; sp<PlaylistFetcher> addFetcher(const char *uri); @@ -145,9 +191,26 @@ private: status_t onSeek(const sp<AMessage> &msg); void onFinishDisconnect2(); - status_t fetchFile( + // If given a non-zero block_size (default 0), it is used to cap the number of + // bytes read in from the DataSource. If given a non-NULL buffer, new content + // is read into the end. + // + // The DataSource we read from is responsible for signaling error or EOF to help us + // break out of the read loop. The DataSource can be returned to the caller, so + // that the caller can reuse it for subsequent fetches (within the initially + // requested range). + // + // For reused HTTP sources, the caller must download a file sequentially without + // any overlaps or gaps to prevent reconnection. + ssize_t fetchFile( const char *url, sp<ABuffer> *out, - int64_t range_offset = 0, int64_t range_length = -1); + /* request/open a file starting at range_offset for range_length bytes */ + int64_t range_offset = 0, int64_t range_length = -1, + /* download block size */ + uint32_t block_size = 0, + /* reuse DataSource if doing partial fetch */ + sp<DataSource> *source = NULL, + String8 *actualUrl = NULL); sp<M3UParser> fetchPlaylist( const char *url, uint8_t *curPlaylistHash, bool *unchanged); @@ -155,22 +218,34 @@ private: size_t getBandwidthIndex(); static int SortByBandwidth(const BandwidthItem *, const BandwidthItem *); + static StreamType indexToType(int idx); void changeConfiguration( int64_t timeUs, size_t bandwidthIndex, bool pickTrack = false); void onChangeConfiguration(const sp<AMessage> &msg); void onChangeConfiguration2(const sp<AMessage> &msg); void onChangeConfiguration3(const sp<AMessage> &msg); + void onSwapped(const sp<AMessage> &msg); + void tryToFinishBandwidthSwitch(); void scheduleCheckBandwidthEvent(); void cancelCheckBandwidthEvent(); + // cancelBandwidthSwitch is atomic wrt swapPacketSource; call it to prevent packet sources + // from being swapped out on stale discontinuities while manipulating + // mPacketSources/mPacketSources2. + void cancelBandwidthSwitch(); + + bool canSwitchBandwidthTo(size_t bandwidthIndex); void onCheckBandwidth(); void finishDisconnect(); void postPrepared(status_t err); + void swapPacketSource(StreamType stream); + bool canSwitchUp(); + DISALLOW_EVIL_CONSTRUCTORS(LiveSession); }; diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp index 243888c..0700de0 100644 --- a/media/libstagefright/httplive/M3UParser.cpp +++ b/media/libstagefright/httplive/M3UParser.cpp @@ -24,6 +24,7 @@ #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/AMessage.h> #include <media/stagefright/MediaErrors.h> +#include <media/stagefright/Utils.h> #include <media/mediaplayer.h> namespace android { @@ -125,7 +126,7 @@ void M3UParser::MediaGroup::pickRandomMediaItems() { mSelectedIndex = strtoul(value, &end, 10); CHECK(end > value && *end == '\0'); - if (mSelectedIndex >= mMediaItems.size()) { + if (mSelectedIndex >= (ssize_t)mMediaItems.size()) { mSelectedIndex = mMediaItems.size() - 1; } } else { @@ -162,18 +163,18 @@ status_t M3UParser::MediaGroup::selectTrack(size_t index, bool select) { if (select) { if (index >= mMediaItems.size()) { - ALOGE("track %d does not exist", index); + ALOGE("track %zu does not exist", index); return INVALID_OPERATION; } - if (mSelectedIndex == index) { - ALOGE("track %d already selected", index); + if (mSelectedIndex == (ssize_t)index) { + ALOGE("track %zu already selected", index); return BAD_VALUE; } ALOGV("selected track %d", index); mSelectedIndex = index; } else { - if (mSelectedIndex != index) { - ALOGE("track %d is not selected", index); + if (mSelectedIndex != (ssize_t)index) { + ALOGE("track %zu is not selected", index); return BAD_VALUE; } ALOGV("unselected track %d", index); @@ -352,9 +353,28 @@ bool M3UParser::getTypeURI(size_t index, const char *key, AString *uri) const { if (!meta->findString(key, &groupID)) { *uri = mItems.itemAt(index).mURI; - // Assume media without any more specific attribute contains - // audio and video, but no subtitles. - return !strcmp("audio", key) || !strcmp("video", key); + AString codecs; + if (!meta->findString("codecs", &codecs)) { + // Assume media without any more specific attribute contains + // audio and video, but no subtitles. + return !strcmp("audio", key) || !strcmp("video", key); + } else { + // Split the comma separated list of codecs. + size_t offset = 0; + ssize_t commaPos = -1; + codecs.append(','); + while ((commaPos = codecs.find(",", offset)) >= 0) { + AString codec(codecs, offset, commaPos - offset); + codec.trim(); + // return true only if a codec of type `key` ("audio"/"video") + // is found. + if (codecIsType(codec, key)) { + return true; + } + offset = commaPos + 1; + } + return false; + } } sp<MediaGroup> group = mMediaGroups.valueFor(groupID); @@ -369,18 +389,6 @@ bool M3UParser::getTypeURI(size_t index, const char *key, AString *uri) const { return true; } -bool M3UParser::getAudioURI(size_t index, AString *uri) const { - return getTypeURI(index, "audio", uri); -} - -bool M3UParser::getVideoURI(size_t index, AString *uri) const { - return getTypeURI(index, "video", uri); -} - -bool M3UParser::getSubtitleURI(size_t index, AString *uri) const { - return getTypeURI(index, "subtitles", uri); -} - static bool MakeURL(const char *baseURL, const char *url, AString *out) { out->clear(); @@ -390,6 +398,8 @@ static bool MakeURL(const char *baseURL, const char *url, AString *out) { // Base URL must be absolute return false; } + const size_t schemeEnd = (strstr(baseURL, "//") - baseURL) + 2; + CHECK(schemeEnd == 7 || schemeEnd == 8); if (!strncasecmp("http://", url, 7) || !strncasecmp("https://", url, 8)) { // "url" is already an absolute URL, ignore base URL. @@ -416,22 +426,32 @@ static bool MakeURL(const char *baseURL, const char *url, AString *out) { } else { // URL is a relative path - size_t n = strlen(baseURL); - if (baseURL[n - 1] == '/') { - out->setTo(baseURL); - out->append(url); + // Check for a possible query string + const char *qsPos = strchr(baseURL, '?'); + size_t end; + if (qsPos != NULL) { + end = qsPos - baseURL; } else { - const char *slashPos = strrchr(baseURL, '/'); - - if (slashPos > &baseURL[6]) { - out->setTo(baseURL, slashPos - baseURL); - } else { - out->setTo(baseURL); + end = strlen(baseURL); + } + // Check for the last slash before a potential query string + for (ssize_t pos = end - 1; pos >= 0; pos--) { + if (baseURL[pos] == '/') { + end = pos; + break; } + } - out->append("/"); - out->append(url); + // Check whether the found slash actually is part of the path + // and not part of the "http://". + if (end >= schemeEnd) { + out->setTo(baseURL, end); + } else { + out->setTo(baseURL); } + + out->append("/"); + out->append(url); } ALOGV("base:'%s', url:'%s' => '%s'", baseURL, url, out->c_str()); @@ -608,7 +628,7 @@ status_t M3UParser::parseMetaDataDuration( if (meta->get() == NULL) { *meta = new AMessage; } - (*meta)->setInt64(key, (int64_t)x * 1E6); + (*meta)->setInt64(key, (int64_t)(x * 1E6)); return OK; } @@ -684,12 +704,25 @@ status_t M3UParser::parseStreamInf( *meta = new AMessage; } (*meta)->setInt32("bandwidth", x); + } else if (!strcasecmp("codecs", key.c_str())) { + if (!isQuotedString(val)) { + ALOGE("Expected quoted string for %s attribute, " + "got '%s' instead.", + key.c_str(), val.c_str());; + + return ERROR_MALFORMED; + } + + key.tolower(); + const AString &codecs = unquoteString(val); + if (meta->get() == NULL) { + *meta = new AMessage; + } + (*meta)->setString(key.c_str(), codecs.c_str()); } else if (!strcasecmp("audio", key.c_str()) || !strcasecmp("video", key.c_str()) || !strcasecmp("subtitles", key.c_str())) { - if (val.size() < 2 - || val.c_str()[0] != '"' - || val.c_str()[val.size() - 1] != '"') { + if (!isQuotedString(val)) { ALOGE("Expected quoted string for %s attribute, " "got '%s' instead.", key.c_str(), val.c_str()); @@ -697,7 +730,7 @@ status_t M3UParser::parseStreamInf( return ERROR_MALFORMED; } - AString groupID(val, 1, val.size() - 2); + const AString &groupID = unquoteString(val); ssize_t groupIndex = mMediaGroups.indexOfKey(groupID); if (groupIndex < 0) { @@ -708,6 +741,9 @@ status_t M3UParser::parseStreamInf( } key.tolower(); + if (meta->get() == NULL) { + *meta = new AMessage; + } (*meta)->setString(key.c_str(), groupID.c_str()); } } @@ -770,8 +806,7 @@ status_t M3UParser::parseCipherInfo( if (MakeURL(baseURI.c_str(), val.c_str(), &absURI)) { val = absURI; } else { - ALOGE("failed to make absolute url for '%s'.", - val.c_str()); + ALOGE("failed to make absolute url for <URL suppressed>."); } } @@ -1086,4 +1121,121 @@ status_t M3UParser::ParseDouble(const char *s, double *x) { return OK; } +// static +bool M3UParser::isQuotedString(const AString &str) { + if (str.size() < 2 + || str.c_str()[0] != '"' + || str.c_str()[str.size() - 1] != '"') { + return false; + } + return true; +} + +// static +AString M3UParser::unquoteString(const AString &str) { + if (!isQuotedString(str)) { + return str; + } + return AString(str, 1, str.size() - 2); +} + +// static +bool M3UParser::codecIsType(const AString &codec, const char *type) { + if (codec.size() < 4) { + return false; + } + const char *c = codec.c_str(); + switch (FOURCC(c[0], c[1], c[2], c[3])) { + // List extracted from http://www.mp4ra.org/codecs.html + case 'ac-3': + case 'alac': + case 'dra1': + case 'dtsc': + case 'dtse': + case 'dtsh': + case 'dtsl': + case 'ec-3': + case 'enca': + case 'g719': + case 'g726': + case 'm4ae': + case 'mlpa': + case 'mp4a': + case 'raw ': + case 'samr': + case 'sawb': + case 'sawp': + case 'sevc': + case 'sqcp': + case 'ssmv': + case 'twos': + case 'agsm': + case 'alaw': + case 'dvi ': + case 'fl32': + case 'fl64': + case 'ima4': + case 'in24': + case 'in32': + case 'lpcm': + case 'Qclp': + case 'QDM2': + case 'QDMC': + case 'ulaw': + case 'vdva': + return !strcmp("audio", type); + + case 'avc1': + case 'avc2': + case 'avcp': + case 'drac': + case 'encv': + case 'mjp2': + case 'mp4v': + case 'mvc1': + case 'mvc2': + case 'resv': + case 's263': + case 'svc1': + case 'vc-1': + case 'CFHD': + case 'civd': + case 'DV10': + case 'dvh5': + case 'dvh6': + case 'dvhp': + case 'DVOO': + case 'DVOR': + case 'DVTV': + case 'DVVT': + case 'flic': + case 'gif ': + case 'h261': + case 'h263': + case 'HD10': + case 'jpeg': + case 'M105': + case 'mjpa': + case 'mjpb': + case 'png ': + case 'PNTG': + case 'rle ': + case 'rpza': + case 'Shr0': + case 'Shr1': + case 'Shr2': + case 'Shr3': + case 'Shr4': + case 'SVQ1': + case 'SVQ3': + case 'tga ': + case 'tiff': + case 'WRLE': + return !strcmp("video", type); + + default: + return false; + } +} + } // namespace android diff --git a/media/libstagefright/httplive/M3UParser.h b/media/libstagefright/httplive/M3UParser.h index 5248004..ccd6556 100644 --- a/media/libstagefright/httplive/M3UParser.h +++ b/media/libstagefright/httplive/M3UParser.h @@ -45,9 +45,7 @@ struct M3UParser : public RefBase { status_t getTrackInfo(Parcel* reply) const; ssize_t getSelectedIndex() const; - bool getAudioURI(size_t index, AString *uri) const; - bool getVideoURI(size_t index, AString *uri) const; - bool getSubtitleURI(size_t index, AString *uri) const; + bool getTypeURI(size_t index, const char *key, AString *uri) const; protected: virtual ~M3UParser(); @@ -95,11 +93,13 @@ private: status_t parseMedia(const AString &line); - bool getTypeURI(size_t index, const char *key, AString *uri) const; - static status_t ParseInt32(const char *s, int32_t *x); static status_t ParseDouble(const char *s, double *x); + static bool isQuotedString(const AString &str); + static AString unquoteString(const AString &str); + static bool codecIsType(const AString &codec, const char *type); + DISALLOW_EVIL_CONSTRUCTORS(M3UParser); }; diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp index 973b779..513f114 100644 --- a/media/libstagefright/httplive/PlaylistFetcher.cpp +++ b/media/libstagefright/httplive/PlaylistFetcher.cpp @@ -40,6 +40,7 @@ #include <media/stagefright/Utils.h> #include <ctype.h> +#include <inttypes.h> #include <openssl/aes.h> #include <openssl/md5.h> @@ -47,26 +48,35 @@ namespace android { // static const int64_t PlaylistFetcher::kMinBufferedDurationUs = 10000000ll; +const int64_t PlaylistFetcher::kMaxMonitorDelayUs = 3000000ll; +const int32_t PlaylistFetcher::kDownloadBlockSize = 192; +const int32_t PlaylistFetcher::kNumSkipFrames = 10; PlaylistFetcher::PlaylistFetcher( const sp<AMessage> ¬ify, const sp<LiveSession> &session, const char *uri) : mNotify(notify), + mStartTimeUsNotify(notify->dup()), mSession(session), mURI(uri), mStreamTypeMask(0), mStartTimeUs(-1ll), + mMinStartTimeUs(0ll), + mStopParams(NULL), mLastPlaylistFetchTimeUs(-1ll), mSeqNumber(-1), mNumRetries(0), mStartup(true), + mPrepared(false), mNextPTSTimeUs(-1ll), mMonitorQueueGeneration(0), mRefreshState(INITIAL_MINIMUM_RELOAD_DELAY), mFirstPTSValid(false), mAbsoluteTimeAnchorUs(0ll) { memset(mPlaylistHash, 0, sizeof(mPlaylistHash)); + mStartTimeUsNotify->setInt32("what", kWhatStartedAt); + mStartTimeUsNotify->setInt32("streamMask", 0); } PlaylistFetcher::~PlaylistFetcher() { @@ -103,10 +113,16 @@ int64_t PlaylistFetcher::getSegmentStartTimeUs(int32_t seqNumber) const { return segmentStartUs; } -bool PlaylistFetcher::timeToRefreshPlaylist(int64_t nowUs) const { - if (mPlaylist == NULL) { +int64_t PlaylistFetcher::delayUsToRefreshPlaylist() const { + int64_t nowUs = ALooper::GetNowUs(); + + if (mPlaylist == NULL || mLastPlaylistFetchTimeUs < 0ll) { CHECK_EQ((int)mRefreshState, (int)INITIAL_MINIMUM_RELOAD_DELAY); - return true; + return 0ll; + } + + if (mPlaylist->isComplete()) { + return (~0llu >> 1); } int32_t targetDurationSecs; @@ -157,11 +173,13 @@ bool PlaylistFetcher::timeToRefreshPlaylist(int64_t nowUs) const { break; } - return mLastPlaylistFetchTimeUs + minPlaylistAgeUs <= nowUs; + int64_t delayUs = mLastPlaylistFetchTimeUs + minPlaylistAgeUs - nowUs; + return delayUs > 0ll ? delayUs : 0ll; } status_t PlaylistFetcher::decryptBuffer( - size_t playlistIndex, const sp<ABuffer> &buffer) { + size_t playlistIndex, const sp<ABuffer> &buffer, + bool first) { sp<AMessage> itemMeta; bool found = false; AString method; @@ -179,6 +197,7 @@ status_t PlaylistFetcher::decryptBuffer( if (!found) { method = "NONE"; } + buffer->meta()->setString("cipher-method", method.c_str()); if (method == "NONE") { return OK; @@ -199,9 +218,9 @@ status_t PlaylistFetcher::decryptBuffer( if (index >= 0) { key = mAESKeyForURI.valueAt(index); } else { - status_t err = mSession->fetchFile(keyURI.c_str(), &key); + ssize_t err = mSession->fetchFile(keyURI.c_str(), &key); - if (err != OK) { + if (err < 0) { ALOGE("failed to fetch cipher key from '%s'.", keyURI.c_str()); return ERROR_IO; } else if (key->size() != 16) { @@ -218,63 +237,89 @@ status_t PlaylistFetcher::decryptBuffer( return UNKNOWN_ERROR; } - unsigned char aes_ivec[16]; + size_t n = buffer->size(); + if (!n) { + return OK; + } + CHECK(n % 16 == 0); - AString iv; - if (itemMeta->findString("cipher-iv", &iv)) { - if ((!iv.startsWith("0x") && !iv.startsWith("0X")) - || iv.size() != 16 * 2 + 2) { - ALOGE("malformed cipher IV '%s'.", iv.c_str()); - return ERROR_MALFORMED; - } + if (first) { + // If decrypting the first block in a file, read the iv from the manifest + // or derive the iv from the file's sequence number. - memset(aes_ivec, 0, sizeof(aes_ivec)); - for (size_t i = 0; i < 16; ++i) { - char c1 = tolower(iv.c_str()[2 + 2 * i]); - char c2 = tolower(iv.c_str()[3 + 2 * i]); - if (!isxdigit(c1) || !isxdigit(c2)) { + AString iv; + if (itemMeta->findString("cipher-iv", &iv)) { + if ((!iv.startsWith("0x") && !iv.startsWith("0X")) + || iv.size() != 16 * 2 + 2) { ALOGE("malformed cipher IV '%s'.", iv.c_str()); return ERROR_MALFORMED; } - uint8_t nibble1 = isdigit(c1) ? c1 - '0' : c1 - 'a' + 10; - uint8_t nibble2 = isdigit(c2) ? c2 - '0' : c2 - 'a' + 10; - aes_ivec[i] = nibble1 << 4 | nibble2; + memset(mAESInitVec, 0, sizeof(mAESInitVec)); + for (size_t i = 0; i < 16; ++i) { + char c1 = tolower(iv.c_str()[2 + 2 * i]); + char c2 = tolower(iv.c_str()[3 + 2 * i]); + if (!isxdigit(c1) || !isxdigit(c2)) { + ALOGE("malformed cipher IV '%s'.", iv.c_str()); + return ERROR_MALFORMED; + } + uint8_t nibble1 = isdigit(c1) ? c1 - '0' : c1 - 'a' + 10; + uint8_t nibble2 = isdigit(c2) ? c2 - '0' : c2 - 'a' + 10; + + mAESInitVec[i] = nibble1 << 4 | nibble2; + } + } else { + memset(mAESInitVec, 0, sizeof(mAESInitVec)); + mAESInitVec[15] = mSeqNumber & 0xff; + mAESInitVec[14] = (mSeqNumber >> 8) & 0xff; + mAESInitVec[13] = (mSeqNumber >> 16) & 0xff; + mAESInitVec[12] = (mSeqNumber >> 24) & 0xff; } - } else { - memset(aes_ivec, 0, sizeof(aes_ivec)); - aes_ivec[15] = mSeqNumber & 0xff; - aes_ivec[14] = (mSeqNumber >> 8) & 0xff; - aes_ivec[13] = (mSeqNumber >> 16) & 0xff; - aes_ivec[12] = (mSeqNumber >> 24) & 0xff; } AES_cbc_encrypt( buffer->data(), buffer->data(), buffer->size(), - &aes_key, aes_ivec, AES_DECRYPT); - - // hexdump(buffer->data(), buffer->size()); + &aes_key, mAESInitVec, AES_DECRYPT); - size_t n = buffer->size(); - CHECK_GT(n, 0u); + return OK; +} - size_t pad = buffer->data()[n - 1]; +status_t PlaylistFetcher::checkDecryptPadding(const sp<ABuffer> &buffer) { + status_t err; + AString method; + CHECK(buffer->meta()->findString("cipher-method", &method)); + if (method == "NONE") { + return OK; + } - CHECK_GT(pad, 0u); - CHECK_LE(pad, 16u); - CHECK_GE((size_t)n, pad); - for (size_t i = 0; i < pad; ++i) { - CHECK_EQ((unsigned)buffer->data()[n - 1 - i], pad); + uint8_t padding = 0; + if (buffer->size() > 0) { + padding = buffer->data()[buffer->size() - 1]; } - n -= pad; + if (padding > 16) { + return ERROR_MALFORMED; + } - buffer->setRange(buffer->offset(), n); + for (size_t i = buffer->size() - padding; i < padding; i++) { + if (buffer->data()[i] != padding) { + return ERROR_MALFORMED; + } + } + buffer->setRange(buffer->offset(), buffer->size() - padding); return OK; } -void PlaylistFetcher::postMonitorQueue(int64_t delayUs) { +void PlaylistFetcher::postMonitorQueue(int64_t delayUs, int64_t minDelayUs) { + int64_t maxDelayUs = delayUsToRefreshPlaylist(); + if (maxDelayUs < minDelayUs) { + maxDelayUs = minDelayUs; + } + if (delayUs > maxDelayUs) { + ALOGV("Need to refresh playlist in %lld", maxDelayUs); + delayUs = maxDelayUs; + } sp<AMessage> msg = new AMessage(kWhatMonitorQueue, id()); msg->setInt32("generation", mMonitorQueueGeneration); msg->post(delayUs); @@ -288,7 +333,9 @@ void PlaylistFetcher::startAsync( const sp<AnotherPacketSource> &audioSource, const sp<AnotherPacketSource> &videoSource, const sp<AnotherPacketSource> &subtitleSource, - int64_t startTimeUs) { + int64_t startTimeUs, + int64_t minStartTimeUs, + int32_t startSeqNumberHint) { sp<AMessage> msg = new AMessage(kWhatStart, id()); uint32_t streamTypeMask = 0ul; @@ -310,6 +357,8 @@ void PlaylistFetcher::startAsync( msg->setInt32("streamTypeMask", streamTypeMask); msg->setInt64("startTimeUs", startTimeUs); + msg->setInt64("minStartTimeUs", minStartTimeUs); + msg->setInt32("startSeqNumberHint", startSeqNumberHint); msg->post(); } @@ -317,8 +366,16 @@ void PlaylistFetcher::pauseAsync() { (new AMessage(kWhatPause, id()))->post(); } -void PlaylistFetcher::stopAsync() { - (new AMessage(kWhatStop, id()))->post(); +void PlaylistFetcher::stopAsync(bool selfTriggered) { + sp<AMessage> msg = new AMessage(kWhatStop, id()); + msg->setInt32("selfTriggered", selfTriggered); + msg->post(); +} + +void PlaylistFetcher::resumeUntilAsync(const sp<AMessage> ¶ms) { + AMessage* msg = new AMessage(kWhatResumeUntil, id()); + msg->setMessage("params", params); + msg->post(); } void PlaylistFetcher::onMessageReceived(const sp<AMessage> &msg) { @@ -346,7 +403,7 @@ void PlaylistFetcher::onMessageReceived(const sp<AMessage> &msg) { case kWhatStop: { - onStop(); + onStop(msg); sp<AMessage> notify = mNotify->dup(); notify->setInt32("what", kWhatStopped); @@ -355,6 +412,7 @@ void PlaylistFetcher::onMessageReceived(const sp<AMessage> &msg) { } case kWhatMonitorQueue: + case kWhatDownloadNext: { int32_t generation; CHECK(msg->findInt32("generation", &generation)); @@ -364,7 +422,17 @@ void PlaylistFetcher::onMessageReceived(const sp<AMessage> &msg) { break; } - onMonitorQueue(); + if (msg->what() == kWhatMonitorQueue) { + onMonitorQueue(); + } else { + onDownloadNext(); + } + break; + } + + case kWhatResumeUntil: + { + onResumeUntil(msg); break; } @@ -380,7 +448,10 @@ status_t PlaylistFetcher::onStart(const sp<AMessage> &msg) { CHECK(msg->findInt32("streamTypeMask", (int32_t *)&streamTypeMask)); int64_t startTimeUs; + int32_t startSeqNumberHint; CHECK(msg->findInt64("startTimeUs", &startTimeUs)); + CHECK(msg->findInt64("minStartTimeUs", (int64_t *) &mMinStartTimeUs)); + CHECK(msg->findInt32("startSeqNumberHint", &startSeqNumberHint)); if (streamTypeMask & LiveSession::STREAMTYPE_AUDIO) { void *ptr; @@ -415,6 +486,11 @@ status_t PlaylistFetcher::onStart(const sp<AMessage> &msg) { if (mStartTimeUs >= 0ll) { mSeqNumber = -1; mStartup = true; + mPrepared = false; + } + + if (startSeqNumberHint >= 0) { + mSeqNumber = startSeqNumberHint; } postMonitorQueue(); @@ -424,22 +500,83 @@ status_t PlaylistFetcher::onStart(const sp<AMessage> &msg) { void PlaylistFetcher::onPause() { cancelMonitorQueue(); - - mPacketSources.clear(); - mStreamTypeMask = 0; } -void PlaylistFetcher::onStop() { +void PlaylistFetcher::onStop(const sp<AMessage> &msg) { cancelMonitorQueue(); - for (size_t i = 0; i < mPacketSources.size(); ++i) { - mPacketSources.valueAt(i)->clear(); + int32_t selfTriggered; + CHECK(msg->findInt32("selfTriggered", &selfTriggered)); + if (!selfTriggered) { + // Self triggered stops only happen during switching, in which case we do not want + // to clear the discontinuities queued at the end of packet sources. + for (size_t i = 0; i < mPacketSources.size(); i++) { + sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i); + packetSource->clear(); + } } mPacketSources.clear(); mStreamTypeMask = 0; } +// Resume until we have reached the boundary timestamps listed in `msg`; when +// the remaining time is too short (within a resume threshold) stop immediately +// instead. +status_t PlaylistFetcher::onResumeUntil(const sp<AMessage> &msg) { + sp<AMessage> params; + CHECK(msg->findMessage("params", ¶ms)); + + bool stop = false; + for (size_t i = 0; i < mPacketSources.size(); i++) { + sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i); + + const char *stopKey; + int streamType = mPacketSources.keyAt(i); + switch (streamType) { + case LiveSession::STREAMTYPE_VIDEO: + stopKey = "timeUsVideo"; + break; + + case LiveSession::STREAMTYPE_AUDIO: + stopKey = "timeUsAudio"; + break; + + case LiveSession::STREAMTYPE_SUBTITLES: + stopKey = "timeUsSubtitle"; + break; + + default: + TRESPASS(); + } + + // Don't resume if we would stop within a resume threshold. + int64_t latestTimeUs = 0, stopTimeUs = 0; + sp<AMessage> latestMeta = packetSource->getLatestMeta(); + if (latestMeta != NULL + && (latestMeta->findInt64("timeUs", &latestTimeUs) + && params->findInt64(stopKey, &stopTimeUs))) { + int64_t diffUs = stopTimeUs - latestTimeUs; + if (diffUs < resumeThreshold(latestMeta)) { + stop = true; + } + } + } + + if (stop) { + for (size_t i = 0; i < mPacketSources.size(); i++) { + mPacketSources.valueAt(i)->queueAccessUnit(mSession->createFormatChangeBuffer()); + } + stopAsync(/* selfTriggered = */ true); + return OK; + } + + mStopParams = params; + postMonitorQueue(); + + return OK; +} + void PlaylistFetcher::notifyError(status_t err) { sp<AMessage> notify = mNotify->dup(); notify->setInt32("what", kWhatError); @@ -456,41 +593,70 @@ void PlaylistFetcher::queueDiscontinuity( void PlaylistFetcher::onMonitorQueue() { bool downloadMore = false; + refreshPlaylist(); + + int32_t targetDurationSecs; + int64_t targetDurationUs = kMinBufferedDurationUs; + if (mPlaylist != NULL) { + CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs)); + targetDurationUs = targetDurationSecs * 1000000ll; + } - status_t finalResult; + // buffer at least 3 times the target duration, or up to 10 seconds + int64_t durationToBufferUs = targetDurationUs * 3; + if (durationToBufferUs > kMinBufferedDurationUs) { + durationToBufferUs = kMinBufferedDurationUs; + } + + int64_t bufferedDurationUs = 0ll; + status_t finalResult = NOT_ENOUGH_DATA; if (mStreamTypeMask == LiveSession::STREAMTYPE_SUBTITLES) { sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(LiveSession::STREAMTYPE_SUBTITLES); - int64_t bufferedDurationUs = + bufferedDurationUs = packetSource->getBufferedDurationUs(&finalResult); - - downloadMore = (bufferedDurationUs < kMinBufferedDurationUs); finalResult = OK; } else { - bool first = true; - int64_t minBufferedDurationUs = 0ll; - + // Use max stream duration to prevent us from waiting on a non-existent stream; + // when we cannot make out from the manifest what streams are included in a playlist + // we might assume extra streams. for (size_t i = 0; i < mPacketSources.size(); ++i) { if ((mStreamTypeMask & mPacketSources.keyAt(i)) == 0) { continue; } - int64_t bufferedDurationUs = + int64_t bufferedStreamDurationUs = mPacketSources.valueAt(i)->getBufferedDurationUs(&finalResult); - - if (first || bufferedDurationUs < minBufferedDurationUs) { - minBufferedDurationUs = bufferedDurationUs; - first = false; + ALOGV("buffered %lld for stream %d", + bufferedStreamDurationUs, mPacketSources.keyAt(i)); + if (bufferedStreamDurationUs > bufferedDurationUs) { + bufferedDurationUs = bufferedStreamDurationUs; } } + } + downloadMore = (bufferedDurationUs < durationToBufferUs); + + // signal start if buffered up at least the target size + if (!mPrepared && bufferedDurationUs > targetDurationUs && downloadMore) { + mPrepared = true; - downloadMore = - !first && (minBufferedDurationUs < kMinBufferedDurationUs); + ALOGV("prepared, buffered=%lld > %lld", + bufferedDurationUs, targetDurationUs); + sp<AMessage> msg = mNotify->dup(); + msg->setInt32("what", kWhatTemporarilyDoneFetching); + msg->post(); } if (finalResult == OK && downloadMore) { - onDownloadNext(); + ALOGV("monitoring, buffered=%lld < %lld", + bufferedDurationUs, durationToBufferUs); + // delay the next download slightly; hopefully this gives other concurrent fetchers + // a better chance to run. + // onDownloadNext(); + sp<AMessage> msg = new AMessage(kWhatDownloadNext, id()); + msg->setInt32("generation", mMonitorQueueGeneration); + msg->post(1000l); } else { // Nothing to do yet, try again in a second. @@ -498,15 +664,17 @@ void PlaylistFetcher::onMonitorQueue() { msg->setInt32("what", kWhatTemporarilyDoneFetching); msg->post(); - postMonitorQueue(1000000ll); + int64_t delayUs = mPrepared ? kMaxMonitorDelayUs : targetDurationUs / 2; + ALOGV("pausing for %lld, buffered=%lld > %lld", + delayUs, bufferedDurationUs, durationToBufferUs); + // :TRICKY: need to enforce minimum delay because the delay to + // refresh the playlist will become 0 + postMonitorQueue(delayUs, mPrepared ? targetDurationUs * 2 : 0); } } -void PlaylistFetcher::onDownloadNext() { - int64_t nowUs = ALooper::GetNowUs(); - - if (mLastPlaylistFetchTimeUs < 0ll - || (!mPlaylist->isComplete() && timeToRefreshPlaylist(nowUs))) { +status_t PlaylistFetcher::refreshPlaylist() { + if (delayUsToRefreshPlaylist() <= 0) { bool unchanged; sp<M3UParser> playlist = mSession->fetchPlaylist( mURI.c_str(), mPlaylistHash, &unchanged); @@ -522,7 +690,7 @@ void PlaylistFetcher::onDownloadNext() { } else { ALOGE("failed to load playlist at url '%s'", mURI.c_str()); notifyError(ERROR_IO); - return; + return ERROR_IO; } } else { mRefreshState = INITIAL_MINIMUM_RELOAD_DELAY; @@ -535,6 +703,18 @@ void PlaylistFetcher::onDownloadNext() { mLastPlaylistFetchTimeUs = ALooper::GetNowUs(); } + return OK; +} + +// static +bool PlaylistFetcher::bufferStartsWithTsSyncByte(const sp<ABuffer>& buffer) { + return buffer->size() > 0 && buffer->data()[0] == 0x47; +} + +void PlaylistFetcher::onDownloadNext() { + if (refreshPlaylist() != OK) { + return; + } int32_t firstSeqNumberInPlaylist; if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32( @@ -548,17 +728,29 @@ 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 (mSeqNumber < 0) { CHECK_GE(mStartTimeUs, 0ll); if (mPlaylist->isComplete() || mPlaylist->isEvent()) { mSeqNumber = getSeqNumberForTime(mStartTimeUs); + ALOGV("Initial sequence number for time %lld is %ld from (%ld .. %ld)", + mStartTimeUs, mSeqNumber, firstSeqNumberInPlaylist, + lastSeqNumberInPlaylist); } else { // If this is a live session, start 3 segments from the end. mSeqNumber = lastSeqNumberInPlaylist - 3; if (mSeqNumber < firstSeqNumberInPlaylist) { mSeqNumber = firstSeqNumberInPlaylist; } + ALOGV("Initial sequence number for live event %ld from (%ld .. %ld)", + mSeqNumber, firstSeqNumberInPlaylist, + lastSeqNumberInPlaylist); } mStartTimeUs = -1ll; @@ -570,16 +762,34 @@ void PlaylistFetcher::onDownloadNext() { ++mNumRetries; if (mSeqNumber > lastSeqNumberInPlaylist) { - mLastPlaylistFetchTimeUs = -1; - postMonitorQueue(3000000ll); + // refresh in increasing fraction (1/2, 1/3, ...) of the + // playlist's target duration or 3 seconds, whichever is less + int32_t targetDurationSecs; + CHECK(mPlaylist->meta()->findInt32( + "target-duration", &targetDurationSecs)); + int64_t delayUs = mPlaylist->size() * targetDurationSecs * + 1000000ll / (1 + mNumRetries); + if (delayUs > kMaxMonitorDelayUs) { + delayUs = kMaxMonitorDelayUs; + } + ALOGV("sequence number high: %ld from (%ld .. %ld), monitor in %lld (retry=%d)", + mSeqNumber, firstSeqNumberInPlaylist, + lastSeqNumberInPlaylist, delayUs, mNumRetries); + postMonitorQueue(delayUs); return; } // we've missed the boat, let's start from the lowest sequence // number available and signal a discontinuity. - ALOGI("We've missed the boat, restarting playback."); - mSeqNumber = lastSeqNumberInPlaylist; + ALOGI("We've missed the boat, restarting playback." + " mStartup=%d, was looking for %d in %d-%d", + mStartup, mSeqNumber, firstSeqNumberInPlaylist, + lastSeqNumberInPlaylist); + mSeqNumber = lastSeqNumberInPlaylist - 3; + if (mSeqNumber < firstSeqNumberInPlaylist) { + mSeqNumber = firstSeqNumberInPlaylist; + } explicitDiscontinuity = true; // fall through @@ -587,7 +797,7 @@ void PlaylistFetcher::onDownloadNext() { ALOGE("Cannot find sequence number %d in playlist " "(contains %d - %d)", mSeqNumber, firstSeqNumberInPlaylist, - firstSeqNumberInPlaylist + mPlaylist->size() - 1); + firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1); notifyError(ERROR_END_OF_STREAM); return; @@ -620,50 +830,160 @@ void PlaylistFetcher::onDownloadNext() { ALOGV("fetching '%s'", uri.c_str()); - sp<ABuffer> buffer; - status_t err = mSession->fetchFile( - uri.c_str(), &buffer, range_offset, range_length); - - if (err != OK) { - ALOGE("failed to fetch .ts segment at url '%s'", uri.c_str()); - notifyError(err); - return; + sp<DataSource> source; + sp<ABuffer> buffer, tsBuffer; + // decrypt a junk buffer to prefetch key; since a session uses only one http connection, + // this avoids interleaved connections to the key and segment file. + { + sp<ABuffer> junk = new ABuffer(16); + junk->setRange(0, 16); + status_t err = decryptBuffer(mSeqNumber - firstSeqNumberInPlaylist, junk, + true /* first */); + if (err != OK) { + notifyError(err); + return; + } } - CHECK(buffer != NULL); + // block-wise download + ssize_t bytesRead; + do { + bytesRead = mSession->fetchFile( + uri.c_str(), &buffer, range_offset, range_length, kDownloadBlockSize, &source); + + if (bytesRead < 0) { + status_t err = bytesRead; + ALOGE("failed to fetch .ts segment at url '%s'", uri.c_str()); + notifyError(err); + return; + } - err = decryptBuffer(mSeqNumber - firstSeqNumberInPlaylist, buffer); + CHECK(buffer != NULL); - if (err != OK) { - ALOGE("decryptBuffer failed w/ error %d", err); + size_t size = buffer->size(); + // Set decryption range. + buffer->setRange(size - bytesRead, bytesRead); + status_t err = decryptBuffer(mSeqNumber - firstSeqNumberInPlaylist, buffer, + buffer->offset() == 0 /* first */); + // Unset decryption range. + buffer->setRange(0, size); - notifyError(err); - return; - } + if (err != OK) { + ALOGE("decryptBuffer failed w/ error %d", err); - if (mStartup || seekDiscontinuity || explicitDiscontinuity) { - // Signal discontinuity. + notifyError(err); + return; + } - if (mPlaylist->isComplete() || mPlaylist->isEvent()) { - // If this was a live event this made no sense since - // we don't have access to all the segment before the current - // one. - mNextPTSTimeUs = getSegmentStartTimeUs(mSeqNumber); + if (mStartup || seekDiscontinuity || explicitDiscontinuity) { + // Signal discontinuity. + + if (mPlaylist->isComplete() || mPlaylist->isEvent()) { + // If this was a live event this made no sense since + // we don't have access to all the segment before the current + // one. + mNextPTSTimeUs = getSegmentStartTimeUs(mSeqNumber); + } + + if (seekDiscontinuity || explicitDiscontinuity) { + ALOGI("queueing discontinuity (seek=%d, explicit=%d)", + seekDiscontinuity, explicitDiscontinuity); + + queueDiscontinuity( + explicitDiscontinuity + ? ATSParser::DISCONTINUITY_FORMATCHANGE + : ATSParser::DISCONTINUITY_SEEK, + NULL /* extra */); + } + } + + err = OK; + if (bufferStartsWithTsSyncByte(buffer)) { + // Incremental extraction is only supported for MPEG2 transport streams. + if (tsBuffer == NULL) { + tsBuffer = new ABuffer(buffer->data(), buffer->capacity()); + tsBuffer->setRange(0, 0); + } else if (tsBuffer->capacity() != buffer->capacity()) { + size_t tsOff = tsBuffer->offset(), tsSize = tsBuffer->size(); + tsBuffer = new ABuffer(buffer->data(), buffer->capacity()); + tsBuffer->setRange(tsOff, tsSize); + } + tsBuffer->setRange(tsBuffer->offset(), tsBuffer->size() + bytesRead); + + err = extractAndQueueAccessUnitsFromTs(tsBuffer); + } + + if (err == -EAGAIN) { + // bad starting sequence number hint + postMonitorQueue(); + return; } - if (seekDiscontinuity || explicitDiscontinuity) { - ALOGI("queueing discontinuity (seek=%d, explicit=%d)", - seekDiscontinuity, explicitDiscontinuity); + if (err == ERROR_OUT_OF_RANGE) { + // reached stopping point + stopAsync(/* selfTriggered = */ true); + return; + } - queueDiscontinuity( - explicitDiscontinuity - ? ATSParser::DISCONTINUITY_FORMATCHANGE - : ATSParser::DISCONTINUITY_SEEK, - NULL /* extra */); + if (err != OK) { + notifyError(err); + return; } + + mStartup = false; + } while (bytesRead != 0); + + if (bufferStartsWithTsSyncByte(buffer)) { + // If we still don't see a stream after fetching a full ts segment mark it as + // nonexistent. + const size_t kNumTypes = ATSParser::NUM_SOURCE_TYPES; + ATSParser::SourceType srcTypes[kNumTypes] = + { ATSParser::VIDEO, ATSParser::AUDIO }; + LiveSession::StreamType streamTypes[kNumTypes] = + { LiveSession::STREAMTYPE_VIDEO, LiveSession::STREAMTYPE_AUDIO }; + + for (size_t i = 0; i < kNumTypes; i++) { + ATSParser::SourceType srcType = srcTypes[i]; + LiveSession::StreamType streamType = streamTypes[i]; + + sp<AnotherPacketSource> source = + static_cast<AnotherPacketSource *>( + mTSParser->getSource(srcType).get()); + + if (source == NULL) { + ALOGW("MPEG2 Transport stream does not contain %s data.", + srcType == ATSParser::VIDEO ? "video" : "audio"); + + mStreamTypeMask &= ~streamType; + mPacketSources.removeItem(streamType); + } + } + + } + + if (checkDecryptPadding(buffer) != OK) { + ALOGE("Incorrect padding bytes after decryption."); + notifyError(ERROR_MALFORMED); + return; } - err = extractAndQueueAccessUnits(buffer, itemMeta); + status_t err = OK; + if (tsBuffer != NULL) { + AString method; + CHECK(buffer->meta()->findString("cipher-method", &method)); + if ((tsBuffer->size() > 0 && method == "NONE") + || tsBuffer->size() > 16) { + ALOGE("MPEG2 transport stream is not an even multiple of 188 " + "bytes in length."); + notifyError(ERROR_MALFORMED); + return; + } + } + + // bulk extract non-ts files + if (tsBuffer == NULL) { + err = extractAndQueueAccessUnits(buffer, itemMeta); + } if (err != OK) { notifyError(err); @@ -673,8 +993,6 @@ void PlaylistFetcher::onDownloadNext() { ++mSeqNumber; postMonitorQueue(); - - mStartup = false; } int32_t PlaylistFetcher::getSeqNumberForTime(int64_t timeUs) const { @@ -709,95 +1027,163 @@ int32_t PlaylistFetcher::getSeqNumberForTime(int64_t timeUs) const { return firstSeqNumberInPlaylist + index; } -status_t PlaylistFetcher::extractAndQueueAccessUnits( - const sp<ABuffer> &buffer, const sp<AMessage> &itemMeta) { - if (buffer->size() > 0 && buffer->data()[0] == 0x47) { - // Let's assume this is an MPEG2 transport stream. +status_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &buffer) { + if (mTSParser == NULL) { + // Use TS_TIMESTAMPS_ARE_ABSOLUTE so pts carry over between fetchers. + mTSParser = new ATSParser(ATSParser::TS_TIMESTAMPS_ARE_ABSOLUTE); + } - if ((buffer->size() % 188) != 0) { - ALOGE("MPEG2 transport stream is not an even multiple of 188 " - "bytes in length."); - return ERROR_MALFORMED; - } + if (mNextPTSTimeUs >= 0ll) { + sp<AMessage> extra = new AMessage; + // Since we are using absolute timestamps, signal an offset of 0 to prevent + // ATSParser from skewing the timestamps of access units. + extra->setInt64(IStreamListener::kKeyMediaTimeUs, 0); - if (mTSParser == NULL) { - mTSParser = new ATSParser; - } + mTSParser->signalDiscontinuity( + ATSParser::DISCONTINUITY_SEEK, extra); - if (mNextPTSTimeUs >= 0ll) { - sp<AMessage> extra = new AMessage; - extra->setInt64(IStreamListener::kKeyMediaTimeUs, mNextPTSTimeUs); + mNextPTSTimeUs = -1ll; + } - mTSParser->signalDiscontinuity( - ATSParser::DISCONTINUITY_SEEK, extra); + size_t offset = 0; + while (offset + 188 <= buffer->size()) { + status_t err = mTSParser->feedTSPacket(buffer->data() + offset, 188); - mNextPTSTimeUs = -1ll; + if (err != OK) { + return err; } - size_t offset = 0; - while (offset < buffer->size()) { - status_t err = mTSParser->feedTSPacket(buffer->data() + offset, 188); + offset += 188; + } + // setRange to indicate consumed bytes. + buffer->setRange(buffer->offset() + offset, buffer->size() - offset); + + status_t err = OK; + for (size_t i = mPacketSources.size(); i-- > 0;) { + sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i); + + const char *key; + ATSParser::SourceType type; + const LiveSession::StreamType stream = mPacketSources.keyAt(i); + switch (stream) { + case LiveSession::STREAMTYPE_VIDEO: + type = ATSParser::VIDEO; + key = "timeUsVideo"; + break; + + case LiveSession::STREAMTYPE_AUDIO: + type = ATSParser::AUDIO; + key = "timeUsAudio"; + break; - if (err != OK) { - return err; + case LiveSession::STREAMTYPE_SUBTITLES: + { + ALOGE("MPEG2 Transport streams do not contain subtitles."); + return ERROR_MALFORMED; + break; } - offset += 188; + default: + TRESPASS(); } - for (size_t i = mPacketSources.size(); i-- > 0;) { - sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i); + sp<AnotherPacketSource> source = + static_cast<AnotherPacketSource *>( + mTSParser->getSource(type).get()); - ATSParser::SourceType type; - switch (mPacketSources.keyAt(i)) { - case LiveSession::STREAMTYPE_VIDEO: - type = ATSParser::VIDEO; - break; + if (source == NULL) { + continue; + } - case LiveSession::STREAMTYPE_AUDIO: - type = ATSParser::AUDIO; + int64_t timeUs; + sp<ABuffer> accessUnit; + status_t finalResult; + while (source->hasBufferAvailable(&finalResult) + && source->dequeueAccessUnit(&accessUnit) == OK) { + + CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs)); + if (mMinStartTimeUs > 0) { + if (timeUs < mMinStartTimeUs) { + // TODO untested path + // try a later ts + int32_t targetDuration; + mPlaylist->meta()->findInt32("target-duration", &targetDuration); + int32_t incr = (mMinStartTimeUs - timeUs) / 1000000 / targetDuration; + if (incr == 0) { + // increment mSeqNumber by at least one + incr = 1; + } + mSeqNumber += incr; + err = -EAGAIN; break; + } else { + int64_t startTimeUs; + if (mStartTimeUsNotify != NULL + && !mStartTimeUsNotify->findInt64(key, &startTimeUs)) { + mStartTimeUsNotify->setInt64(key, timeUs); + + uint32_t streamMask = 0; + mStartTimeUsNotify->findInt32("streamMask", (int32_t *) &streamMask); + streamMask |= mPacketSources.keyAt(i); + mStartTimeUsNotify->setInt32("streamMask", streamMask); + + if (streamMask == mStreamTypeMask) { + mStartTimeUsNotify->post(); + mStartTimeUsNotify.clear(); + } + } + } + } - case LiveSession::STREAMTYPE_SUBTITLES: - { - ALOGE("MPEG2 Transport streams do not contain subtitles."); - return ERROR_MALFORMED; + if (mStopParams != NULL) { + // Queue discontinuity in original stream. + int64_t stopTimeUs; + if (!mStopParams->findInt64(key, &stopTimeUs) || timeUs >= stopTimeUs) { + packetSource->queueAccessUnit(mSession->createFormatChangeBuffer()); + mStreamTypeMask &= ~stream; + mPacketSources.removeItemsAt(i); break; } - - default: - TRESPASS(); } - sp<AnotherPacketSource> source = - static_cast<AnotherPacketSource *>( - mTSParser->getSource(type).get()); - - if (source == NULL) { - ALOGW("MPEG2 Transport stream does not contain %s data.", - type == ATSParser::VIDEO ? "video" : "audio"); + // Note that we do NOT dequeue any discontinuities except for format change. - mStreamTypeMask &= ~mPacketSources.keyAt(i); - mPacketSources.removeItemsAt(i); - continue; + // for simplicity, store a reference to the format in each unit + sp<MetaData> format = source->getFormat(); + if (format != NULL) { + accessUnit->meta()->setObject("format", format); } - sp<ABuffer> accessUnit; - status_t finalResult; - while (source->hasBufferAvailable(&finalResult) - && source->dequeueAccessUnit(&accessUnit) == OK) { - // Note that we do NOT dequeue any discontinuities. + // Stash the sequence number so we can hint future playlist where to start at. + accessUnit->meta()->setInt32("seq", mSeqNumber); + packetSource->queueAccessUnit(accessUnit); + } - packetSource->queueAccessUnit(accessUnit); - } + if (err != OK) { + break; + } + } - if (packetSource->getFormat() == NULL) { - packetSource->setFormat(source->getFormat()); - } + if (err != OK) { + for (size_t i = mPacketSources.size(); i-- > 0;) { + sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i); + packetSource->clear(); } + return err; + } - return OK; - } else if (buffer->size() >= 7 && !memcmp("WEBVTT\n", buffer->data(), 7)) { + if (!mStreamTypeMask) { + // Signal gap is filled between original and new stream. + ALOGV("ERROR OUT OF RANGE"); + return ERROR_OUT_OF_RANGE; + } + + return OK; +} + +status_t PlaylistFetcher::extractAndQueueAccessUnits( + const sp<ABuffer> &buffer, const sp<AMessage> &itemMeta) { + if (buffer->size() >= 7 && !memcmp("WEBVTT\n", buffer->data(), 7)) { if (mStreamTypeMask != LiveSession::STREAMTYPE_SUBTITLES) { ALOGE("This stream only contains subtitles."); return ERROR_MALFORMED; @@ -810,6 +1196,7 @@ status_t PlaylistFetcher::extractAndQueueAccessUnits( CHECK(itemMeta->findInt64("durationUs", &durationUs)); buffer->meta()->setInt64("timeUs", getSegmentStartTimeUs(mSeqNumber)); buffer->meta()->setInt64("durationUs", durationUs); + buffer->meta()->setInt32("seq", mSeqNumber); packetSource->queueAccessUnit(buffer); return OK; @@ -935,6 +1322,18 @@ status_t PlaylistFetcher::extractAndQueueAccessUnits( | (adtsHeader[4] << 3) | (adtsHeader[5] >> 5); + if (aac_frame_length == 0) { + const uint8_t *id3Header = adtsHeader; + if (!memcmp(id3Header, "ID3", 3)) { + ID3 id3(id3Header, buffer->size() - offset, true); + if (id3.isValid()) { + offset += id3.rawSize(); + continue; + }; + } + return ERROR_MALFORMED; + } + CHECK_LE(offset + aac_frame_length, buffer->size()); sp<ABuffer> unit = new ABuffer(aac_frame_length); @@ -946,6 +1345,7 @@ status_t PlaylistFetcher::extractAndQueueAccessUnits( // Each AAC frame encodes 1024 samples. numSamples += 1024; + unit->meta()->setInt32("seq", mSeqNumber); packetSource->queueAccessUnit(unit); offset += aac_frame_length; @@ -973,4 +1373,33 @@ void PlaylistFetcher::updateDuration() { msg->post(); } +int64_t PlaylistFetcher::resumeThreshold(const sp<AMessage> &msg) { + int64_t durationUs, threshold; + if (msg->findInt64("durationUs", &durationUs)) { + return kNumSkipFrames * durationUs; + } + + sp<RefBase> obj; + msg->findObject("format", &obj); + MetaData *format = static_cast<MetaData *>(obj.get()); + + const char *mime; + CHECK(format->findCString(kKeyMIMEType, &mime)); + bool audio = !strncasecmp(mime, "audio/", 6); + if (audio) { + // Assumes 1000 samples per frame. + int32_t sampleRate; + CHECK(format->findInt32(kKeySampleRate, &sampleRate)); + return kNumSkipFrames /* frames */ * 1000 /* samples */ + * (1000000 / sampleRate) /* sample duration (us) */; + } else { + int32_t frameRate; + if (format->findInt32(kKeyFrameRate, &frameRate) && frameRate > 0) { + return kNumSkipFrames * (1000000 / frameRate); + } + } + + return 500000ll; +} + } // namespace android diff --git a/media/libstagefright/httplive/PlaylistFetcher.h b/media/libstagefright/httplive/PlaylistFetcher.h index 1648e02..7e21523 100644 --- a/media/libstagefright/httplive/PlaylistFetcher.h +++ b/media/libstagefright/httplive/PlaylistFetcher.h @@ -43,6 +43,7 @@ struct PlaylistFetcher : public AHandler { kWhatTemporarilyDoneFetching, kWhatPrepared, kWhatPreparationFailed, + kWhatStartedAt, }; PlaylistFetcher( @@ -56,11 +57,15 @@ struct PlaylistFetcher : public AHandler { const sp<AnotherPacketSource> &audioSource, const sp<AnotherPacketSource> &videoSource, const sp<AnotherPacketSource> &subtitleSource, - int64_t startTimeUs = -1ll); + int64_t startTimeUs = -1ll, + int64_t minStartTimeUs = 0ll /* start after this timestamp */, + int32_t startSeqNumberHint = -1 /* try starting at this sequence number */); void pauseAsync(); - void stopAsync(); + void stopAsync(bool selfTriggered = false); + + void resumeUntilAsync(const sp<AMessage> ¶ms); protected: virtual ~PlaylistFetcher(); @@ -76,16 +81,28 @@ private: kWhatPause = 'paus', kWhatStop = 'stop', kWhatMonitorQueue = 'moni', + kWhatResumeUntil = 'rsme', + kWhatDownloadNext = 'dlnx', }; static const int64_t kMinBufferedDurationUs; + static const int64_t kMaxMonitorDelayUs; + static const int32_t kDownloadBlockSize; + static const int32_t kNumSkipFrames; + + static bool bufferStartsWithTsSyncByte(const sp<ABuffer>& buffer); + // notifications to mSession sp<AMessage> mNotify; + sp<AMessage> mStartTimeUsNotify; + sp<LiveSession> mSession; AString mURI; uint32_t mStreamTypeMask; int64_t mStartTimeUs; + int64_t mMinStartTimeUs; // start fetching no earlier than this value + sp<AMessage> mStopParams; // message containing the latest timestamps we should fetch. KeyedVector<LiveSession::StreamType, sp<AnotherPacketSource> > mPacketSources; @@ -97,6 +114,7 @@ private: int32_t mSeqNumber; int32_t mNumRetries; bool mStartup; + bool mPrepared; int64_t mNextPTSTimeUs; int32_t mMonitorQueueGeneration; @@ -117,13 +135,29 @@ private: uint64_t mFirstPTS; int64_t mAbsoluteTimeAnchorUs; + // Stores the initialization vector to decrypt the next block of cipher text, which can + // either be derived from the sequence number, read from the manifest, or copied from + // the last block of cipher text (cipher-block chaining). + unsigned char mAESInitVec[16]; + + // Set first to true if decrypting the first segment of a playlist segment. When + // first is true, reset the initialization vector based on the available + // information in the manifest; otherwise, use the initialization vector as + // updated by the last call to AES_cbc_encrypt. + // + // For the input to decrypt correctly, decryptBuffer must be called on + // consecutive byte ranges on block boundaries, e.g. 0..15, 16..47, 48..63, + // and so on. status_t decryptBuffer( - size_t playlistIndex, const sp<ABuffer> &buffer); + size_t playlistIndex, const sp<ABuffer> &buffer, + bool first = true); + status_t checkDecryptPadding(const sp<ABuffer> &buffer); - void postMonitorQueue(int64_t delayUs = 0); + void postMonitorQueue(int64_t delayUs = 0, int64_t minDelayUs = 0); void cancelMonitorQueue(); - bool timeToRefreshPlaylist(int64_t nowUs) const; + int64_t delayUsToRefreshPlaylist() const; + status_t refreshPlaylist(); // Returns the media time in us of the segment specified by seqNumber. // This is computed by summing the durations of all segments before it. @@ -131,10 +165,15 @@ private: status_t onStart(const sp<AMessage> &msg); void onPause(); - void onStop(); + void onStop(const sp<AMessage> &msg); void onMonitorQueue(); void onDownloadNext(); + // Resume a fetcher to continue until the stopping point stored in msg. + status_t onResumeUntil(const sp<AMessage> &msg); + + status_t extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &buffer); + status_t extractAndQueueAccessUnits( const sp<ABuffer> &buffer, const sp<AMessage> &itemMeta); @@ -147,6 +186,10 @@ private: void updateDuration(); + // Before resuming a fetcher in onResume, check the remaining duration is longer than that + // returned by resumeThreshold. + int64_t resumeThreshold(const sp<AMessage> &msg); + DISALLOW_EVIL_CONSTRUCTORS(PlaylistFetcher); }; diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp index 34d671a..1199c22 100644 --- a/media/libstagefright/id3/ID3.cpp +++ b/media/libstagefright/id3/ID3.cpp @@ -41,9 +41,9 @@ struct MemorySource : public DataSource { } virtual ssize_t readAt(off64_t offset, void *data, size_t size) { - off64_t available = (offset >= mSize) ? 0ll : mSize - offset; + off64_t available = (offset >= (off64_t)mSize) ? 0ll : mSize - offset; - size_t copy = (available > size) ? size : available; + size_t copy = (available > (off64_t)size) ? size : available; memcpy(data, mData + offset, copy); return copy; @@ -56,14 +56,14 @@ private: DISALLOW_EVIL_CONSTRUCTORS(MemorySource); }; -ID3::ID3(const sp<DataSource> &source, bool ignoreV1) +ID3::ID3(const sp<DataSource> &source, bool ignoreV1, off64_t offset) : mIsValid(false), mData(NULL), mSize(0), mFirstFrameOffset(0), mVersion(ID3_UNKNOWN), mRawSize(0) { - mIsValid = parseV2(source); + mIsValid = parseV2(source, offset); if (!mIsValid && !ignoreV1) { mIsValid = parseV1(source); @@ -79,7 +79,7 @@ ID3::ID3(const uint8_t *data, size_t size, bool ignoreV1) mRawSize(0) { sp<MemorySource> source = new MemorySource(data, size); - mIsValid = parseV2(source); + mIsValid = parseV2(source, 0); if (!mIsValid && !ignoreV1) { mIsValid = parseV1(source); @@ -115,7 +115,7 @@ bool ID3::ParseSyncsafeInteger(const uint8_t encoded[4], size_t *x) { return true; } -bool ID3::parseV2(const sp<DataSource> &source) { +bool ID3::parseV2(const sp<DataSource> &source, off64_t offset) { struct id3_header { char id[3]; uint8_t version_major; @@ -126,7 +126,7 @@ struct id3_header { id3_header header; if (source->readAt( - 0, &header, sizeof(header)) != (ssize_t)sizeof(header)) { + offset, &header, sizeof(header)) != (ssize_t)sizeof(header)) { return false; } @@ -172,7 +172,7 @@ struct id3_header { } if (size > kMaxMetadataSize) { - ALOGE("skipping huge ID3 metadata of size %d", size); + ALOGE("skipping huge ID3 metadata of size %zu", size); return false; } @@ -185,7 +185,7 @@ struct id3_header { mSize = size; mRawSize = mSize + sizeof(header); - if (source->readAt(sizeof(header), mData, mSize) != (ssize_t)mSize) { + if (source->readAt(offset + sizeof(header), mData, mSize) != (ssize_t)mSize) { free(mData); mData = NULL; @@ -654,8 +654,8 @@ void ID3::Iterator::findFrame() { mFrameSize += 6; if (mOffset + mFrameSize > mParent.mSize) { - ALOGV("partial frame at offset %d (size = %d, bytes-remaining = %d)", - mOffset, mFrameSize, mParent.mSize - mOffset - 6); + ALOGV("partial frame at offset %zu (size = %zu, bytes-remaining = %zu)", + mOffset, mFrameSize, mParent.mSize - mOffset - (size_t)6); return; } @@ -695,8 +695,8 @@ void ID3::Iterator::findFrame() { mFrameSize = 10 + baseSize; if (mOffset + mFrameSize > mParent.mSize) { - ALOGV("partial frame at offset %d (size = %d, bytes-remaining = %d)", - mOffset, mFrameSize, mParent.mSize - mOffset - 10); + ALOGV("partial frame at offset %zu (size = %zu, bytes-remaining = %zu)", + mOffset, mFrameSize, mParent.mSize - mOffset - (size_t)10); return; } diff --git a/media/libstagefright/id3/testid3.cpp b/media/libstagefright/id3/testid3.cpp index bc4572c..b2f4188 100644 --- a/media/libstagefright/id3/testid3.cpp +++ b/media/libstagefright/id3/testid3.cpp @@ -33,7 +33,7 @@ static void hexdump(const void *_data, size_t size) { const uint8_t *data = (const uint8_t *)_data; size_t offset = 0; while (offset < size) { - printf("0x%04x ", offset); + printf("0x%04zx ", offset); size_t n = size - offset; if (n > 16) { @@ -101,7 +101,7 @@ void scanFile(const char *path) { const void *data = tag.getAlbumArt(&dataSize, &mime); if (data) { - printf("found album art: size=%d mime='%s'\n", dataSize, + printf("found album art: size=%zu mime='%s'\n", dataSize, mime.string()); hexdump(data, dataSize > 128 ? 128 : dataSize); diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h index 271df8e..6ee95a9 100644 --- a/media/libstagefright/include/AwesomePlayer.h +++ b/media/libstagefright/include/AwesomePlayer.h @@ -32,6 +32,7 @@ namespace android { struct AudioPlayer; +struct ClockEstimator; struct DataSource; struct MediaBuffer; struct MediaExtractor; @@ -234,6 +235,7 @@ private: MediaBuffer *mVideoBuffer; + sp<ClockEstimator> mClockEstimator; sp<HTTPBase> mConnectingDataSource; sp<NuCachedSource2> mCachedSource; @@ -293,6 +295,7 @@ private: bool getBitrate(int64_t *bitrate); + int64_t estimateRealTimeUs(TimeSource *ts, int64_t systemTimeUs); void finishSeekIfNecessary(int64_t videoTimeUs); void ensureCacheIsFetching_l(); diff --git a/media/libstagefright/include/ChromiumHTTPDataSource.h b/media/libstagefright/include/ChromiumHTTPDataSource.h index 785f939..da188dd 100644 --- a/media/libstagefright/include/ChromiumHTTPDataSource.h +++ b/media/libstagefright/include/ChromiumHTTPDataSource.h @@ -113,6 +113,7 @@ private: void onConnectionFailed(status_t err); void onReadCompleted(ssize_t size); void onDisconnectComplete(); + void onRedirect(const char *url); void clearDRMState_l(); diff --git a/media/libstagefright/include/ID3.h b/media/libstagefright/include/ID3.h index cca83ab..e83f3ef 100644 --- a/media/libstagefright/include/ID3.h +++ b/media/libstagefright/include/ID3.h @@ -35,7 +35,7 @@ struct ID3 { ID3_V2_4, }; - ID3(const sp<DataSource> &source, bool ignoreV1 = false); + ID3(const sp<DataSource> &source, bool ignoreV1 = false, off64_t offset = 0); ID3(const uint8_t *data, size_t size, bool ignoreV1 = false); ~ID3(); @@ -86,7 +86,7 @@ private: size_t mRawSize; bool parseV1(const sp<DataSource> &source); - bool parseV2(const sp<DataSource> &source); + bool parseV2(const sp<DataSource> &source, off64_t offset); void removeUnsynchronization(); bool removeUnsynchronizationV2_4(bool iTunesHack); diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h index bd5e4b9..7b4bc6d 100644 --- a/media/libstagefright/include/MPEG4Extractor.h +++ b/media/libstagefright/include/MPEG4Extractor.h @@ -97,6 +97,7 @@ private: status_t parseChunk(off64_t *offset, int depth); status_t parseITunesMetaData(off64_t offset, size_t size); status_t parse3GPPMetaData(off64_t offset, size_t size, int depth); + void parseID3v2MetaData(off64_t offset); status_t updateAudioTrackInfoFromESDS_MPEG4Audio( const void *esds_data, size_t esds_size); diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h index 31a5077..cd51bbf 100644 --- a/media/libstagefright/include/OMX.h +++ b/media/libstagefright/include/OMX.h @@ -134,10 +134,10 @@ public: OMX_IN OMX_PTR pEventData); OMX_ERRORTYPE OnEmptyBufferDone( - node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer); + node_id node, buffer_id buffer, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer); OMX_ERRORTYPE OnFillBufferDone( - node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer); + node_id node, buffer_id buffer, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer); void invalidateNodeID(node_id node); diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h index 339179e..3967dc6 100644 --- a/media/libstagefright/include/OMXNodeInstance.h +++ b/media/libstagefright/include/OMXNodeInstance.h @@ -138,12 +138,25 @@ private: OMX::buffer_id mID; }; Vector<ActiveBuffer> mActiveBuffers; +#ifdef __LP64__ + Mutex mBufferIDLock; + uint32_t mBufferIDCount; + KeyedVector<OMX::buffer_id, OMX_BUFFERHEADERTYPE *> mBufferIDToBufferHeader; + KeyedVector<OMX_BUFFERHEADERTYPE *, OMX::buffer_id> mBufferHeaderToBufferID; +#endif ~OMXNodeInstance(); void addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id); void removeActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id); void freeActiveBuffers(); + + // For buffer id management + OMX::buffer_id makeBufferID(OMX_BUFFERHEADERTYPE *bufferHeader); + OMX_BUFFERHEADERTYPE *findBufferHeader(OMX::buffer_id buffer); + OMX::buffer_id findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader); + void invalidateBufferID(OMX::buffer_id buffer); + status_t useGraphicBuffer2_l( OMX_U32 portIndex, const sp<GraphicBuffer> &graphicBuffer, OMX::buffer_id *buffer); diff --git a/media/libstagefright/include/SampleTable.h b/media/libstagefright/include/SampleTable.h index 847dff7..ed91adc 100644 --- a/media/libstagefright/include/SampleTable.h +++ b/media/libstagefright/include/SampleTable.h @@ -74,7 +74,8 @@ public: kFlagClosest }; status_t findSampleAtTime( - uint32_t req_time, uint32_t *sample_index, uint32_t flags); + uint64_t req_time, uint64_t scale_num, uint64_t scale_den, + uint32_t *sample_index, uint32_t flags); status_t findSyncSampleNear( uint32_t start_sample_index, uint32_t *sample_index, @@ -137,6 +138,13 @@ private: friend struct SampleIterator; + // normally we don't round + inline uint64_t getSampleTime( + size_t sample_index, uint64_t scale_num, uint64_t scale_den) const { + return (mSampleTimeEntries[sample_index].mCompositionTime + * scale_num) / scale_den; + } + status_t getSampleSize_l(uint32_t sample_index, size_t *sample_size); uint32_t getCompositionTimeOffset(uint32_t sampleIndex); diff --git a/media/libstagefright/include/TimedEventQueue.h b/media/libstagefright/include/TimedEventQueue.h index 38a08b1..2963150 100644 --- a/media/libstagefright/include/TimedEventQueue.h +++ b/media/libstagefright/include/TimedEventQueue.h @@ -122,7 +122,7 @@ private: }; struct StopEvent : public TimedEventQueue::Event { - virtual void fire(TimedEventQueue *queue, int64_t now_us) { + virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) { queue->mStopped = true; } }; @@ -145,7 +145,7 @@ private: static void *ThreadWrapper(void *me); void threadEntry(); - sp<Event> removeEventFromQueue_l(event_id id); + sp<Event> removeEventFromQueue_l(event_id id, bool *wakeLocked); void acquireWakeLock_l(); void releaseWakeLock_l(bool force = false); diff --git a/media/libstagefright/matroska/Android.mk b/media/libstagefright/matroska/Android.mk index 2d8c1e1..446ff8c 100644 --- a/media/libstagefright/matroska/Android.mk +++ b/media/libstagefright/matroska/Android.mk @@ -8,7 +8,7 @@ LOCAL_C_INCLUDES:= \ $(TOP)/external/libvpx/libwebm \ $(TOP)/frameworks/native/include/media/openmax \ -LOCAL_CFLAGS += -Wno-multichar +LOCAL_CFLAGS += -Wno-multichar -Werror LOCAL_MODULE:= libstagefright_matroska diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp index d260d0f..0e4dd2b 100644 --- a/media/libstagefright/matroska/MatroskaExtractor.cpp +++ b/media/libstagefright/matroska/MatroskaExtractor.cpp @@ -33,6 +33,8 @@ #include <media/stagefright/Utils.h> #include <utils/String8.h> +#include <inttypes.h> + namespace android { struct DataSourceReader : public mkvparser::IMkvReader { @@ -103,7 +105,7 @@ struct BlockIterator { private: MatroskaExtractor *mExtractor; - unsigned long mTrackNum; + long long mTrackNum; const mkvparser::Cluster *mCluster; const mkvparser::BlockEntry *mBlockEntry; @@ -183,7 +185,7 @@ MatroskaSource::MatroskaSource( CHECK_GE(avccSize, 5u); mNALSizeLen = 1 + (avcc[4] & 3); - ALOGV("mNALSizeLen = %d", mNALSizeLen); + ALOGV("mNALSizeLen = %zu", mNALSizeLen); } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { mType = AAC; } @@ -193,7 +195,7 @@ MatroskaSource::~MatroskaSource() { clearPendingFrames(); } -status_t MatroskaSource::start(MetaData *params) { +status_t MatroskaSource::start(MetaData * /* params */) { mBlockIter.reset(); return OK; @@ -320,7 +322,7 @@ void BlockIterator::seek( // Special case the 0 seek to avoid loading Cues when the application // extraneously seeks to 0 before playing. if (seekTimeNs <= 0) { - ALOGV("Seek to beginning: %lld", seekTimeUs); + ALOGV("Seek to beginning: %" PRId64, seekTimeUs); mCluster = pSegment->GetFirst(); mBlockEntryIndex = 0; do { @@ -329,7 +331,7 @@ void BlockIterator::seek( return; } - ALOGV("Seeking to: %lld", seekTimeUs); + ALOGV("Seeking to: %" PRId64, seekTimeUs); // If the Cues have not been located then find them. const mkvparser::Cues* pCues = pSegment->GetCues(); @@ -378,7 +380,7 @@ void BlockIterator::seek( for (size_t index = 0; index < pTracks->GetTracksCount(); ++index) { pTrack = pTracks->GetTrackByIndex(index); if (pTrack && pTrack->GetType() == 1) { // VIDEO_TRACK - ALOGV("Video track located at %d", index); + ALOGV("Video track located at %zu", index); break; } } @@ -409,8 +411,8 @@ void BlockIterator::seek( if (isAudio || block()->IsKey()) { // Accept the first key frame *actualFrameTimeUs = (block()->GetTime(mCluster) + 500LL) / 1000LL; - ALOGV("Requested seek point: %lld actual: %lld", - seekTimeUs, actualFrameTimeUs); + ALOGV("Requested seek point: %" PRId64 " actual: %" PRId64, + seekTimeUs, *actualFrameTimeUs); break; } } @@ -716,41 +718,61 @@ bool MatroskaExtractor::isLiveStreaming() const { return mIsLiveStreaming; } +static int bytesForSize(size_t size) { + // use at most 28 bits (4 times 7) + CHECK(size <= 0xfffffff); + + if (size > 0x1fffff) { + return 4; + } else if (size > 0x3fff) { + return 3; + } else if (size > 0x7f) { + return 2; + } + return 1; +} + +static void storeSize(uint8_t *data, size_t &idx, size_t size) { + int numBytes = bytesForSize(size); + idx += numBytes; + + data += idx; + size_t next = 0; + while (numBytes--) { + *--data = (size & 0x7f) | next; + size >>= 7; + next = 0x80; + } +} + static void addESDSFromCodecPrivate( const sp<MetaData> &meta, bool isAudio, const void *priv, size_t privSize) { - static const uint8_t kStaticESDS[] = { - 0x03, 22, - 0x00, 0x00, // ES_ID - 0x00, // streamDependenceFlag, URL_Flag, OCRstreamFlag - - 0x04, 17, - 0x40, // ObjectTypeIndication - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - - 0x05, - // CodecSpecificInfo (with size prefix) follows - }; - // Make sure all sizes can be coded in a single byte. - CHECK(privSize + 22 - 2 < 128); - size_t esdsSize = sizeof(kStaticESDS) + privSize + 1; + int privSizeBytesRequired = bytesForSize(privSize); + int esdsSize2 = 14 + privSizeBytesRequired + privSize; + int esdsSize2BytesRequired = bytesForSize(esdsSize2); + int esdsSize1 = 4 + esdsSize2BytesRequired + esdsSize2; + int esdsSize1BytesRequired = bytesForSize(esdsSize1); + size_t esdsSize = 1 + esdsSize1BytesRequired + esdsSize1; uint8_t *esds = new uint8_t[esdsSize]; - memcpy(esds, kStaticESDS, sizeof(kStaticESDS)); - uint8_t *ptr = esds + sizeof(kStaticESDS); - *ptr++ = privSize; - memcpy(ptr, priv, privSize); - - // Increment by codecPrivateSize less 2 bytes that are accounted for - // already in lengths of 22/17 - esds[1] += privSize - 2; - esds[6] += privSize - 2; - - // Set ObjectTypeIndication. - esds[7] = isAudio ? 0x40 // Audio ISO/IEC 14496-3 - : 0x20; // Visual ISO/IEC 14496-2 + + size_t idx = 0; + esds[idx++] = 0x03; + storeSize(esds, idx, esdsSize1); + esds[idx++] = 0x00; // ES_ID + esds[idx++] = 0x00; // ES_ID + esds[idx++] = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag + esds[idx++] = 0x04; + storeSize(esds, idx, esdsSize2); + esds[idx++] = isAudio ? 0x40 // Audio ISO/IEC 14496-3 + : 0x20; // Visual ISO/IEC 14496-2 + for (int i = 0; i < 12; i++) { + esds[idx++] = 0x00; + } + esds[idx++] = 0x05; + storeSize(esds, idx, privSize); + memcpy(esds + idx, priv, privSize); meta->setData(kKeyESDS, 0, esds, esdsSize); diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp index 175a263..2c8cf8d 100644 --- a/media/libstagefright/mpeg2ts/ATSParser.cpp +++ b/media/libstagefright/mpeg2ts/ATSParser.cpp @@ -36,6 +36,8 @@ #include <media/IStreamSource.h> #include <utils/KeyedVector.h> +#include <inttypes.h> + namespace android { // I want the expression "y" evaluated even if verbose logging is off. @@ -581,7 +583,7 @@ status_t ATSParser::Stream::parse( // Increment in multiples of 64K. neededSize = (neededSize + 65535) & ~65535; - ALOGI("resizing buffer to %d bytes", neededSize); + ALOGI("resizing buffer to %zu bytes", neededSize); sp<ABuffer> newBuffer = new ABuffer(neededSize); memcpy(newBuffer->data(), mBuffer->data(), mBuffer->size()); @@ -742,7 +744,7 @@ status_t ATSParser::Stream::parsePES(ABitReader *br) { PTS |= br->getBits(15); CHECK_EQ(br->getBits(1), 1u); - ALOGV("PTS = 0x%016llx (%.2f)", PTS, PTS / 90000.0); + ALOGV("PTS = 0x%016" PRIx64 " (%.2f)", PTS, PTS / 90000.0); optional_bytes_remaining -= 5; @@ -758,7 +760,7 @@ status_t ATSParser::Stream::parsePES(ABitReader *br) { DTS |= br->getBits(15); CHECK_EQ(br->getBits(1), 1u); - ALOGV("DTS = %llu", DTS); + ALOGV("DTS = %" PRIu64, DTS); optional_bytes_remaining -= 5; } @@ -776,7 +778,7 @@ status_t ATSParser::Stream::parsePES(ABitReader *br) { ESCR |= br->getBits(15); CHECK_EQ(br->getBits(1), 1u); - ALOGV("ESCR = %llu", ESCR); + ALOGV("ESCR = %" PRIu64, ESCR); MY_LOGV("ESCR_extension = %u", br->getBits(9)); CHECK_EQ(br->getBits(1), 1u); @@ -806,7 +808,7 @@ status_t ATSParser::Stream::parsePES(ABitReader *br) { if (br->numBitsLeft() < dataLength * 8) { ALOGE("PES packet does not carry enough data to contain " - "payload. (numBitsLeft = %d, required = %d)", + "payload. (numBitsLeft = %zu, required = %u)", br->numBitsLeft(), dataLength * 8); return ERROR_MALFORMED; @@ -826,7 +828,7 @@ status_t ATSParser::Stream::parsePES(ABitReader *br) { size_t payloadSizeBits = br->numBitsLeft(); CHECK_EQ(payloadSizeBits % 8, 0u); - ALOGV("There's %d bytes of payload.", payloadSizeBits / 8); + ALOGV("There's %zu bytes of payload.", payloadSizeBits / 8); } } else if (stream_id == 0xbe) { // padding_stream CHECK_NE(PES_packet_length, 0u); @@ -844,7 +846,7 @@ status_t ATSParser::Stream::flush() { return OK; } - ALOGV("flushing stream 0x%04x size = %d", mElementaryPID, mBuffer->size()); + ALOGV("flushing stream 0x%04x size = %zu", mElementaryPID, mBuffer->size()); ABitReader br(mBuffer->data(), mBuffer->size()); @@ -856,7 +858,7 @@ status_t ATSParser::Stream::flush() { } void ATSParser::Stream::onPayloadData( - unsigned PTS_DTS_flags, uint64_t PTS, uint64_t DTS, + unsigned PTS_DTS_flags, uint64_t PTS, uint64_t /* DTS */, const uint8_t *data, size_t size) { #if 0 ALOGI("payload streamType 0x%02x, PTS = 0x%016llx, dPTS = %lld", @@ -1166,7 +1168,7 @@ void ATSParser::parseAdaptationField(ABitReader *br, unsigned PID) { uint64_t PCR = PCR_base * 300 + PCR_ext; - ALOGV("PID 0x%04x: PCR = 0x%016llx (%.2f)", + ALOGV("PID 0x%04x: PCR = 0x%016" PRIx64 " (%.2f)", PID, PCR, PCR / 27E6); // The number of bytes received by this parser up to and @@ -1261,8 +1263,8 @@ bool ATSParser::PTSTimeDeltaEstablished() { } void ATSParser::updatePCR( - unsigned PID, uint64_t PCR, size_t byteOffsetFromStart) { - ALOGV("PCR 0x%016llx @ %d", PCR, byteOffsetFromStart); + unsigned /* PID */, uint64_t PCR, size_t byteOffsetFromStart) { + ALOGV("PCR 0x%016" PRIx64 " @ %zu", PCR, byteOffsetFromStart); if (mNumPCRs == 2) { mPCR[0] = mPCR[1]; diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h index a10edc9..8a80069 100644 --- a/media/libstagefright/mpeg2ts/ATSParser.h +++ b/media/libstagefright/mpeg2ts/ATSParser.h @@ -71,8 +71,9 @@ struct ATSParser : public RefBase { void signalEOS(status_t finalResult); enum SourceType { - VIDEO, - AUDIO + VIDEO = 0, + AUDIO = 1, + NUM_SOURCE_TYPES = 2 }; sp<MediaSource> getSource(SourceType type); diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp index 3153c8b..6dfaa94 100644 --- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp +++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp @@ -34,7 +34,8 @@ AnotherPacketSource::AnotherPacketSource(const sp<MetaData> &meta) : mIsAudio(false), mFormat(NULL), mLastQueuedTimeUs(0), - mEOSResult(OK) { + mEOSResult(OK), + mLatestEnqueuedMeta(NULL) { setFormat(meta); } @@ -61,7 +62,7 @@ void AnotherPacketSource::setFormat(const sp<MetaData> &meta) { AnotherPacketSource::~AnotherPacketSource() { } -status_t AnotherPacketSource::start(MetaData *params) { +status_t AnotherPacketSource::start(MetaData * /* params */) { return OK; } @@ -70,7 +71,27 @@ status_t AnotherPacketSource::stop() { } sp<MetaData> AnotherPacketSource::getFormat() { - return mFormat; + Mutex::Autolock autoLock(mLock); + if (mFormat != NULL) { + return mFormat; + } + + List<sp<ABuffer> >::iterator it = mBuffers.begin(); + while (it != mBuffers.end()) { + sp<ABuffer> buffer = *it; + int32_t discontinuity; + if (buffer->meta()->findInt32("discontinuity", &discontinuity)) { + break; + } + + sp<RefBase> object; + if (buffer->meta()->findObject("format", &object)) { + return static_cast<MetaData*>(object.get()); + } + + ++it; + } + return NULL; } status_t AnotherPacketSource::dequeueAccessUnit(sp<ABuffer> *buffer) { @@ -94,6 +115,11 @@ status_t AnotherPacketSource::dequeueAccessUnit(sp<ABuffer> *buffer) { return INFO_DISCONTINUITY; } + sp<RefBase> object; + if ((*buffer)->meta()->findObject("format", &object)) { + mFormat = static_cast<MetaData*>(object.get()); + } + return OK; } @@ -120,17 +146,22 @@ status_t AnotherPacketSource::read( } return INFO_DISCONTINUITY; - } else { - int64_t timeUs; - CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); + } + + sp<RefBase> object; + if (buffer->meta()->findObject("format", &object)) { + mFormat = static_cast<MetaData*>(object.get()); + } - MediaBuffer *mediaBuffer = new MediaBuffer(buffer); + int64_t timeUs; + CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); - mediaBuffer->meta_data()->setInt64(kKeyTime, timeUs); + MediaBuffer *mediaBuffer = new MediaBuffer(buffer); - *out = mediaBuffer; - return OK; - } + mediaBuffer->meta_data()->setInt64(kKeyTime, timeUs); + + *out = mediaBuffer; + return OK; } return mEOSResult; @@ -152,12 +183,24 @@ void AnotherPacketSource::queueAccessUnit(const sp<ABuffer> &buffer) { return; } - CHECK(buffer->meta()->findInt64("timeUs", &mLastQueuedTimeUs)); + int64_t lastQueuedTimeUs; + CHECK(buffer->meta()->findInt64("timeUs", &lastQueuedTimeUs)); + mLastQueuedTimeUs = lastQueuedTimeUs; ALOGV("queueAccessUnit timeUs=%lld us (%.2f secs)", mLastQueuedTimeUs, mLastQueuedTimeUs / 1E6); Mutex::Autolock autoLock(mLock); mBuffers.push_back(buffer); mCondition.signal(); + + if (!mLatestEnqueuedMeta.get()) { + mLatestEnqueuedMeta = buffer->meta(); + } else { + int64_t latestTimeUs = 0; + CHECK(mLatestEnqueuedMeta->findInt64("timeUs", &latestTimeUs)); + if (lastQueuedTimeUs > latestTimeUs) { + mLatestEnqueuedMeta = buffer->meta(); + } + } } void AnotherPacketSource::clear() { @@ -167,6 +210,7 @@ void AnotherPacketSource::clear() { mEOSResult = OK; mFormat = NULL; + mLatestEnqueuedMeta = NULL; } void AnotherPacketSource::queueDiscontinuity( @@ -191,6 +235,7 @@ void AnotherPacketSource::queueDiscontinuity( mEOSResult = OK; mLastQueuedTimeUs = 0; + mLatestEnqueuedMeta = NULL; sp<ABuffer> buffer = new ABuffer(0); buffer->meta()->setInt32("discontinuity", static_cast<int32_t>(type)); @@ -278,4 +323,9 @@ bool AnotherPacketSource::isFinished(int64_t duration) const { return (mEOSResult != OK); } +sp<AMessage> AnotherPacketSource::getLatestMeta() { + Mutex::Autolock autoLock(mLock); + return mLatestEnqueuedMeta; +} + } // namespace android diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.h b/media/libstagefright/mpeg2ts/AnotherPacketSource.h index e16cf78..9b193a2 100644 --- a/media/libstagefright/mpeg2ts/AnotherPacketSource.h +++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.h @@ -62,6 +62,8 @@ struct AnotherPacketSource : public MediaSource { bool isFinished(int64_t duration) const; + sp<AMessage> getLatestMeta(); + protected: virtual ~AnotherPacketSource(); @@ -74,6 +76,7 @@ private: int64_t mLastQueuedTimeUs; List<sp<ABuffer> > mBuffers; status_t mEOSResult; + sp<AMessage> mLatestEnqueuedMeta; bool wasFormatChange(int32_t discontinuityType) const; diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp index 8f9c9c8..1960b27 100644 --- a/media/libstagefright/mpeg2ts/ESQueue.cpp +++ b/media/libstagefright/mpeg2ts/ESQueue.cpp @@ -31,6 +31,7 @@ #include "include/avc_utils.h" +#include <inttypes.h> #include <netinet/in.h> namespace android { @@ -181,7 +182,7 @@ status_t ElementaryStreamQueue::appendData( if (startOffset > 0) { ALOGI("found something resembling an H.264/MPEG syncword " - "at offset %d", + "at offset %zd", startOffset); } @@ -214,7 +215,7 @@ status_t ElementaryStreamQueue::appendData( if (startOffset > 0) { ALOGI("found something resembling an AAC syncword at " - "offset %d", + "offset %zd", startOffset); } @@ -242,7 +243,7 @@ status_t ElementaryStreamQueue::appendData( if (startOffset > 0) { ALOGI("found something resembling an MPEG audio " - "syncword at offset %d", + "syncword at offset %zd", startOffset); } @@ -266,7 +267,7 @@ status_t ElementaryStreamQueue::appendData( if (mBuffer == NULL || neededSize > mBuffer->capacity()) { neededSize = (neededSize + 65535) & ~65535; - ALOGV("resizing buffer to size %d", neededSize); + ALOGV("resizing buffer to size %zu", neededSize); sp<ABuffer> buffer = new ABuffer(neededSize); if (mBuffer != NULL) { @@ -289,7 +290,7 @@ status_t ElementaryStreamQueue::appendData( #if 0 if (mMode == AAC) { - ALOGI("size = %d, timeUs = %.2f secs", size, timeUs / 1E6); + ALOGI("size = %zu, timeUs = %.2f secs", size, timeUs / 1E6); hexdump(data, size); } #endif @@ -604,7 +605,9 @@ sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitH264() { dstOffset += pos.nalSize + 4; } +#if !LOG_NDEBUG ALOGV("accessUnit contains nal types %s", out.c_str()); +#endif const NALPosition &pos = nals.itemAt(nals.size() - 1); size_t nextScan = pos.nalOffset + pos.nalSize; @@ -835,7 +838,7 @@ sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitMPEGVideo() { accessUnit->meta()->setInt64("timeUs", timeUs); - ALOGV("returning MPEG video access unit at time %lld us", + ALOGV("returning MPEG video access unit at time %" PRId64 " us", timeUs); // hexdump(accessUnit->data(), accessUnit->size()); @@ -994,7 +997,7 @@ sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitMPEG4Video() { accessUnit->meta()->setInt64("timeUs", timeUs); - ALOGV("returning MPEG4 video access unit at time %lld us", + ALOGV("returning MPEG4 video access unit at time %" PRId64 " us", timeUs); // hexdump(accessUnit->data(), accessUnit->size()); diff --git a/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp index dd714c9..85859f7 100644 --- a/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp +++ b/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp @@ -36,6 +36,8 @@ #include <media/stagefright/Utils.h> #include <utils/String8.h> +#include <inttypes.h> + namespace android { struct MPEG2PSExtractor::Track : public MediaSource { @@ -130,7 +132,8 @@ sp<MediaSource> MPEG2PSExtractor::getTrack(size_t index) { return new WrappedTrack(this, mTracks.valueAt(index)); } -sp<MetaData> MPEG2PSExtractor::getTrackMetaData(size_t index, uint32_t flags) { +sp<MetaData> MPEG2PSExtractor::getTrackMetaData( + size_t index, uint32_t /* flags */) { if (index >= mTracks.size()) { return NULL; } @@ -408,7 +411,7 @@ ssize_t MPEG2PSExtractor::dequeuePES() { PTS |= br.getBits(15); CHECK_EQ(br.getBits(1), 1u); - ALOGV("PTS = %llu", PTS); + ALOGV("PTS = %" PRIu64, PTS); // ALOGI("PTS = %.2f secs", PTS / 90000.0f); optional_bytes_remaining -= 5; @@ -425,7 +428,7 @@ ssize_t MPEG2PSExtractor::dequeuePES() { DTS |= br.getBits(15); CHECK_EQ(br.getBits(1), 1u); - ALOGV("DTS = %llu", DTS); + ALOGV("DTS = %" PRIu64, DTS); optional_bytes_remaining -= 5; } @@ -443,7 +446,7 @@ ssize_t MPEG2PSExtractor::dequeuePES() { ESCR |= br.getBits(15); CHECK_EQ(br.getBits(1), 1u); - ALOGV("ESCR = %llu", ESCR); + ALOGV("ESCR = %" PRIu64, ESCR); /* unsigned ESCR_extension = */br.getBits(9); CHECK_EQ(br.getBits(1), 1u); @@ -472,7 +475,7 @@ ssize_t MPEG2PSExtractor::dequeuePES() { if (br.numBitsLeft() < dataLength * 8) { ALOGE("PES packet does not carry enough data to contain " - "payload. (numBitsLeft = %d, required = %d)", + "payload. (numBitsLeft = %zu, required = %u)", br.numBitsLeft(), dataLength * 8); return ERROR_MALFORMED; @@ -625,7 +628,7 @@ status_t MPEG2PSExtractor::Track::read( status_t MPEG2PSExtractor::Track::appendPESData( unsigned PTS_DTS_flags, - uint64_t PTS, uint64_t DTS, + uint64_t PTS, uint64_t /* DTS */, const uint8_t *data, size_t size) { if (mQueue == NULL) { return OK; diff --git a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp index d449c34..35ca118 100644 --- a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp +++ b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp @@ -141,7 +141,7 @@ sp<MediaSource> MPEG2TSExtractor::getTrack(size_t index) { } sp<MetaData> MPEG2TSExtractor::getTrackMetaData( - size_t index, uint32_t flags) { + size_t index, uint32_t /* flags */) { return index < mSourceImpls.size() ? mSourceImpls.editItemAt(index)->getFormat() : NULL; } diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp index b8970ad..3fe9c23 100644 --- a/media/libstagefright/omx/GraphicBufferSource.cpp +++ b/media/libstagefright/omx/GraphicBufferSource.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include <inttypes.h> + #define LOG_TAG "GraphicBufferSource" //#define LOG_NDEBUG 0 #include <utils/Log.h> @@ -42,7 +44,11 @@ GraphicBufferSource::GraphicBufferSource(OMXNodeInstance* nodeInstance, mEndOfStream(false), mEndOfStreamSent(false), mRepeatAfterUs(-1ll), + mMaxTimestampGapUs(-1ll), + mPrevOriginalTimeUs(-1ll), + mPrevModifiedTimeUs(-1ll), mRepeatLastFrameGeneration(0), + mRepeatLastFrameTimestamp(-1ll), mLatestSubmittedBufferId(-1), mLatestSubmittedBufferFrameNum(0), mLatestSubmittedBufferUseCount(0), @@ -196,7 +202,7 @@ void GraphicBufferSource::addCodecBuffer(OMX_BUFFERHEADERTYPE* header) { return; } - ALOGV("addCodecBuffer h=%p size=%lu p=%p", + ALOGV("addCodecBuffer h=%p size=%" PRIu32 " p=%p", header, header->nAllocLen, header->pBuffer); CodecBuffer codecBuffer; codecBuffer.mHeader = header; @@ -217,7 +223,7 @@ void GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header) { return; } - ALOGV("codecBufferEmptied h=%p size=%lu filled=%lu p=%p", + ALOGV("codecBufferEmptied h=%p size=%" PRIu32 " filled=%" PRIu32 " p=%p", header, header->nAllocLen, header->nFilledLen, header->pBuffer); CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi)); @@ -299,6 +305,32 @@ void GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header) { return; } +void GraphicBufferSource::codecBufferFilled(OMX_BUFFERHEADERTYPE* header) { + Mutex::Autolock autoLock(mMutex); + + if (mMaxTimestampGapUs > 0ll + && !(header->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) { + ssize_t index = mOriginalTimeUs.indexOfKey(header->nTimeStamp); + if (index >= 0) { + ALOGV("OUT timestamp: %lld -> %lld", + header->nTimeStamp, mOriginalTimeUs[index]); + header->nTimeStamp = mOriginalTimeUs[index]; + mOriginalTimeUs.removeItemsAt(index); + } else { + // giving up the effort as encoder doesn't appear to preserve pts + ALOGW("giving up limiting timestamp gap (pts = %lld)", + header->nTimeStamp); + mMaxTimestampGapUs = -1ll; + } + if (mOriginalTimeUs.size() > BufferQueue::NUM_BUFFER_SLOTS) { + // something terribly wrong must have happened, giving up... + ALOGE("mOriginalTimeUs has too many entries (%d)", + mOriginalTimeUs.size()); + mMaxTimestampGapUs = -1ll; + } + } +} + void GraphicBufferSource::suspend(bool suspend) { Mutex::Autolock autoLock(mMutex); @@ -431,6 +463,7 @@ bool GraphicBufferSource::repeatLatestSubmittedBuffer_l() { BufferQueue::BufferItem item; item.mBuf = mLatestSubmittedBufferId; item.mFrameNumber = mLatestSubmittedBufferFrameNum; + item.mTimestamp = mRepeatLastFrameTimestamp; status_t err = submitBuffer_l(item, cbi); @@ -440,6 +473,20 @@ bool GraphicBufferSource::repeatLatestSubmittedBuffer_l() { ++mLatestSubmittedBufferUseCount; + /* repeat last frame up to kRepeatLastFrameCount times. + * in case of static scene, a single repeat might not get rid of encoder + * ghosting completely, refresh a couple more times to get better quality + */ + if (--mRepeatLastFrameCount > 0) { + mRepeatLastFrameTimestamp = item.mTimestamp + mRepeatAfterUs * 1000; + + if (mReflector != NULL) { + sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector->id()); + msg->setInt32("generation", ++mRepeatLastFrameGeneration); + msg->post(mRepeatAfterUs); + } + } + return true; } @@ -460,8 +507,11 @@ void GraphicBufferSource::setLatestSubmittedBuffer_l( mLatestSubmittedBufferId = item.mBuf; mLatestSubmittedBufferFrameNum = item.mFrameNumber; + mRepeatLastFrameTimestamp = item.mTimestamp + mRepeatAfterUs * 1000; + mLatestSubmittedBufferUseCount = 1; mRepeatBufferDeferred = false; + mRepeatLastFrameCount = kRepeatLastFrameCount; if (mReflector != NULL) { sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector->id()); @@ -497,9 +547,48 @@ status_t GraphicBufferSource::signalEndOfInputStream() { return OK; } +int64_t GraphicBufferSource::getTimestamp(const BufferQueue::BufferItem &item) { + int64_t timeUs = item.mTimestamp / 1000; + + if (mMaxTimestampGapUs > 0ll) { + /* Cap timestamp gap between adjacent frames to specified max + * + * In the scenario of cast mirroring, encoding could be suspended for + * prolonged periods. Limiting the pts gap to workaround the problem + * where encoder's rate control logic produces huge frames after a + * long period of suspension. + */ + + int64_t originalTimeUs = timeUs; + if (mPrevOriginalTimeUs >= 0ll) { + if (originalTimeUs < mPrevOriginalTimeUs) { + // Drop the frame if it's going backward in time. Bad timestamp + // could disrupt encoder's rate control completely. + ALOGW("Dropping frame that's going backward in time"); + return -1; + } + int64_t timestampGapUs = originalTimeUs - mPrevOriginalTimeUs; + timeUs = (timestampGapUs < mMaxTimestampGapUs ? + timestampGapUs : mMaxTimestampGapUs) + mPrevModifiedTimeUs; + } + mPrevOriginalTimeUs = originalTimeUs; + mPrevModifiedTimeUs = timeUs; + mOriginalTimeUs.add(timeUs, originalTimeUs); + ALOGV("IN timestamp: %lld -> %lld", originalTimeUs, timeUs); + } + + return timeUs; +} + status_t GraphicBufferSource::submitBuffer_l( const BufferQueue::BufferItem &item, int cbi) { ALOGV("submitBuffer_l cbi=%d", cbi); + + int64_t timeUs = getTimestamp(item); + if (timeUs < 0ll) { + return UNKNOWN_ERROR; + } + CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi)); codecBuffer.mGraphicBuffer = mBufferSlot[item.mBuf]; codecBuffer.mBuf = item.mBuf; @@ -515,7 +604,7 @@ status_t GraphicBufferSource::submitBuffer_l( status_t err = mNodeInstance->emptyDirectBuffer(header, 0, 4 + sizeof(buffer_handle_t), OMX_BUFFERFLAG_ENDOFFRAME, - item.mTimestamp / 1000); + timeUs); if (err != OK) { ALOGW("WARNING: emptyDirectBuffer failed: 0x%x", err); codecBuffer.mGraphicBuffer = NULL; @@ -609,6 +698,12 @@ void GraphicBufferSource::onFrameAvailable() { BufferQueue::BufferItem item; status_t err = mBufferQueue->acquireBuffer(&item, 0); if (err == OK) { + // If this is the first time we're seeing this buffer, add it to our + // slot table. + if (item.mGraphicBuffer != NULL) { + ALOGV("fillCodecBuffer_l: setting mBufferSlot %d", item.mBuf); + mBufferSlot[item.mBuf] = item.mGraphicBuffer; + } mBufferQueue->releaseBuffer(item.mBuf, item.mFrameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence); } @@ -658,6 +753,17 @@ status_t GraphicBufferSource::setRepeatPreviousFrameDelayUs( return OK; } +status_t GraphicBufferSource::setMaxTimestampGapUs(int64_t maxGapUs) { + Mutex::Autolock autoLock(mMutex); + + if (mExecuting || maxGapUs <= 0ll) { + return INVALID_OPERATION; + } + + mMaxTimestampGapUs = maxGapUs; + + return OK; +} void GraphicBufferSource::onMessageReceived(const sp<AMessage> &msg) { switch (msg->what()) { case kWhatRepeatLastFrame: diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h index 9e5eee6..3b0e454 100644 --- a/media/libstagefright/omx/GraphicBufferSource.h +++ b/media/libstagefright/omx/GraphicBufferSource.h @@ -87,6 +87,10 @@ public: // fill it with a new frame of data; otherwise, just mark it as available. void codecBufferEmptied(OMX_BUFFERHEADERTYPE* header); + // Called when omx_message::FILL_BUFFER_DONE is received. (Currently the + // buffer source will fix timestamp in the header if needed.) + void codecBufferFilled(OMX_BUFFERHEADERTYPE* header); + // This is called after the last input frame has been submitted. We // need to submit an empty buffer with the EOS flag set. If we don't // have a codec buffer ready, we just set the mEndOfStream flag. @@ -105,6 +109,15 @@ public: // state and once this behaviour is specified it cannot be reset. status_t setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs); + // When set, the timestamp fed to the encoder will be modified such that + // the gap between two adjacent frames is capped at maxGapUs. Timestamp + // will be restored to the original when the encoded frame is returned to + // the client. + // This is to solve a problem in certain real-time streaming case, where + // encoder's rate control logic produces huge frames after a long period + // of suspension on input. + status_t setMaxTimestampGapUs(int64_t maxGapUs); + protected: // BufferQueue::ConsumerListener interface, called when a new frame of // data is available. If we're executing and a codec buffer is @@ -165,6 +178,7 @@ private: void setLatestSubmittedBuffer_l(const BufferQueue::BufferItem &item); bool repeatLatestSubmittedBuffer_l(); + int64_t getTimestamp(const BufferQueue::BufferItem &item); // Lock, covers all member variables. mutable Mutex mMutex; @@ -206,13 +220,22 @@ private: enum { kWhatRepeatLastFrame, }; - + enum { + kRepeatLastFrameCount = 10, + }; int64_t mRepeatAfterUs; + int64_t mMaxTimestampGapUs; + + KeyedVector<int64_t, int64_t> mOriginalTimeUs; + int64_t mPrevOriginalTimeUs; + int64_t mPrevModifiedTimeUs; sp<ALooper> mLooper; sp<AHandlerReflector<GraphicBufferSource> > mReflector; int32_t mRepeatLastFrameGeneration; + int64_t mRepeatLastFrameTimestamp; + int32_t mRepeatLastFrameCount; int mLatestSubmittedBufferId; uint64_t mLatestSubmittedBufferFrameNum; diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp index 84a0e10..7819fc3 100644 --- a/media/libstagefright/omx/OMX.cpp +++ b/media/libstagefright/omx/OMX.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include <inttypes.h> + //#define LOG_NDEBUG 0 #define LOG_TAG "OMX" #include <utils/Log.h> @@ -185,7 +187,7 @@ void OMX::binderDied(const wp<IBinder> &the_late_who) { instance->onObserverDied(mMaster); } -bool OMX::livesLocally(node_id node, pid_t pid) { +bool OMX::livesLocally(node_id /* node */, pid_t pid) { return pid == getpid(); } @@ -285,6 +287,7 @@ status_t OMX::sendCommand( status_t OMX::getParameter( node_id node, OMX_INDEXTYPE index, void *params, size_t size) { + ALOGV("getParameter(%u %#x %p %zd)", node, index, params, size); return findInstance(node)->getParameter( index, params, size); } @@ -292,6 +295,7 @@ status_t OMX::getParameter( status_t OMX::setParameter( node_id node, OMX_INDEXTYPE index, const void *params, size_t size) { + ALOGV("setParameter(%u %#x %p %zd)", node, index, params, size); return findInstance(node)->setParameter( index, params, size); } @@ -424,8 +428,8 @@ OMX_ERRORTYPE OMX::OnEvent( OMX_IN OMX_EVENTTYPE eEvent, OMX_IN OMX_U32 nData1, OMX_IN OMX_U32 nData2, - OMX_IN OMX_PTR pEventData) { - ALOGV("OnEvent(%d, %ld, %ld)", eEvent, nData1, nData2); + OMX_IN OMX_PTR /* pEventData */) { + ALOGV("OnEvent(%d, %" PRIu32", %" PRIu32 ")", eEvent, nData1, nData2); // Forward to OMXNodeInstance. findInstance(node)->onEvent(eEvent, nData1, nData2); @@ -443,13 +447,13 @@ OMX_ERRORTYPE OMX::OnEvent( } OMX_ERRORTYPE OMX::OnEmptyBufferDone( - node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) { + node_id node, buffer_id buffer, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) { ALOGV("OnEmptyBufferDone buffer=%p", pBuffer); omx_message msg; msg.type = omx_message::EMPTY_BUFFER_DONE; msg.node = node; - msg.u.buffer_data.buffer = pBuffer; + msg.u.buffer_data.buffer = buffer; findDispatcher(node)->post(msg); @@ -457,13 +461,13 @@ OMX_ERRORTYPE OMX::OnEmptyBufferDone( } OMX_ERRORTYPE OMX::OnFillBufferDone( - node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) { + node_id node, buffer_id buffer, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) { ALOGV("OnFillBufferDone buffer=%p", pBuffer); omx_message msg; msg.type = omx_message::FILL_BUFFER_DONE; msg.node = node; - msg.u.extended_buffer_data.buffer = pBuffer; + msg.u.extended_buffer_data.buffer = buffer; msg.u.extended_buffer_data.range_offset = pBuffer->nOffset; msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen; msg.u.extended_buffer_data.flags = pBuffer->nFlags; diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp index 5f104fc..c64dcf0 100644 --- a/media/libstagefright/omx/OMXNodeInstance.cpp +++ b/media/libstagefright/omx/OMXNodeInstance.cpp @@ -92,10 +92,14 @@ OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = { OMXNodeInstance::OMXNodeInstance( OMX *owner, const sp<IOMXObserver> &observer) : mOwner(owner), - mNodeID(NULL), + mNodeID(0), mHandle(NULL), mObserver(observer), - mDying(false) { + mDying(false) +#ifdef __LP64__ + , mBufferIDCount(0) +#endif +{ } OMXNodeInstance::~OMXNodeInstance() { @@ -232,7 +236,7 @@ status_t OMXNodeInstance::freeNode(OMXMaster *master) { } mOwner->invalidateNodeID(mNodeID); - mNodeID = NULL; + mNodeID = 0; ALOGV("OMXNodeInstance going away."); delete this; @@ -266,26 +270,26 @@ status_t OMXNodeInstance::sendCommand( } status_t OMXNodeInstance::getParameter( - OMX_INDEXTYPE index, void *params, size_t size) { + OMX_INDEXTYPE index, void *params, size_t /* size */) { Mutex::Autolock autoLock(mLock); OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params); - + ALOGE_IF(err != OMX_ErrorNone, "getParameter(%d) ERROR: %#x", index, err); return StatusFromOMXError(err); } status_t OMXNodeInstance::setParameter( - OMX_INDEXTYPE index, const void *params, size_t size) { + OMX_INDEXTYPE index, const void *params, size_t /* size */) { Mutex::Autolock autoLock(mLock); OMX_ERRORTYPE err = OMX_SetParameter( mHandle, index, const_cast<void *>(params)); - + ALOGE_IF(err != OMX_ErrorNone, "setParameter(%d) ERROR: %#x", index, err); return StatusFromOMXError(err); } status_t OMXNodeInstance::getConfig( - OMX_INDEXTYPE index, void *params, size_t size) { + OMX_INDEXTYPE index, void *params, size_t /* size */) { Mutex::Autolock autoLock(mLock); OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params); @@ -293,7 +297,7 @@ status_t OMXNodeInstance::getConfig( } status_t OMXNodeInstance::setConfig( - OMX_INDEXTYPE index, const void *params, size_t size) { + OMX_INDEXTYPE index, const void *params, size_t /* size */) { Mutex::Autolock autoLock(mLock); OMX_ERRORTYPE err = OMX_SetConfig( @@ -482,7 +486,7 @@ status_t OMXNodeInstance::useBuffer( CHECK_EQ(header->pAppPrivate, buffer_meta); - *buffer = header; + *buffer = makeBufferID(header); addActiveBuffer(portIndex, *buffer); @@ -538,7 +542,7 @@ status_t OMXNodeInstance::useGraphicBuffer2_l( CHECK_EQ(header->pBuffer, bufferHandle); CHECK_EQ(header->pAppPrivate, bufferMeta); - *buffer = header; + *buffer = makeBufferID(header); addActiveBuffer(portIndex, *buffer); @@ -602,7 +606,7 @@ status_t OMXNodeInstance::useGraphicBuffer( CHECK_EQ(header->pAppPrivate, bufferMeta); - *buffer = header; + *buffer = makeBufferID(header); addActiveBuffer(portIndex, *buffer); @@ -610,11 +614,11 @@ status_t OMXNodeInstance::useGraphicBuffer( } status_t OMXNodeInstance::updateGraphicBufferInMeta( - OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer, + OMX_U32 /* portIndex */, const sp<GraphicBuffer>& graphicBuffer, OMX::buffer_id buffer) { Mutex::Autolock autoLock(mLock); - OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)(buffer); + OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer); VideoDecoderOutputMetaData *metadata = (VideoDecoderOutputMetaData *)(header->pBuffer); BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate); @@ -710,7 +714,7 @@ status_t OMXNodeInstance::allocateBuffer( CHECK_EQ(header->pAppPrivate, buffer_meta); - *buffer = header; + *buffer = makeBufferID(header); *buffer_data = header->pBuffer; addActiveBuffer(portIndex, *buffer); @@ -748,7 +752,7 @@ status_t OMXNodeInstance::allocateBufferWithBackup( CHECK_EQ(header->pAppPrivate, buffer_meta); - *buffer = header; + *buffer = makeBufferID(header); addActiveBuffer(portIndex, *buffer); @@ -766,13 +770,14 @@ status_t OMXNodeInstance::freeBuffer( removeActiveBuffer(portIndex, buffer); - OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; + OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer); BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate); OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header); delete buffer_meta; buffer_meta = NULL; + invalidateBufferID(buffer); return StatusFromOMXError(err); } @@ -780,7 +785,7 @@ status_t OMXNodeInstance::freeBuffer( status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) { Mutex::Autolock autoLock(mLock); - OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; + OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer); header->nFilledLen = 0; header->nOffset = 0; header->nFlags = 0; @@ -796,7 +801,7 @@ status_t OMXNodeInstance::emptyBuffer( OMX_U32 flags, OMX_TICKS timestamp) { Mutex::Autolock autoLock(mLock); - OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; + OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer); header->nFilledLen = rangeLength; header->nOffset = rangeOffset; header->nFlags = flags; @@ -849,6 +854,7 @@ status_t OMXNodeInstance::setInternalOption( switch (type) { case IOMX::INTERNAL_OPTION_SUSPEND: case IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY: + case IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP: { const sp<GraphicBufferSource> &bufferSource = getGraphicBufferSource(); @@ -864,7 +870,8 @@ status_t OMXNodeInstance::setInternalOption( bool suspend = *(bool *)data; bufferSource->suspend(suspend); - } else { + } else if (type == + IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY){ if (size != sizeof(int64_t)) { return INVALID_OPERATION; } @@ -872,6 +879,14 @@ status_t OMXNodeInstance::setInternalOption( int64_t delayUs = *(int64_t *)data; return bufferSource->setRepeatPreviousFrameDelayUs(delayUs); + } else { + if (size != sizeof(int64_t)) { + return INVALID_OPERATION; + } + + int64_t maxGapUs = *(int64_t *)data; + + return bufferSource->setMaxTimestampGapUs(maxGapUs); } return OK; @@ -883,19 +898,28 @@ status_t OMXNodeInstance::setInternalOption( } void OMXNodeInstance::onMessage(const omx_message &msg) { + const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource()); + if (msg.type == omx_message::FILL_BUFFER_DONE) { OMX_BUFFERHEADERTYPE *buffer = - static_cast<OMX_BUFFERHEADERTYPE *>( - msg.u.extended_buffer_data.buffer); + findBufferHeader(msg.u.extended_buffer_data.buffer); BufferMeta *buffer_meta = static_cast<BufferMeta *>(buffer->pAppPrivate); buffer_meta->CopyFromOMX(buffer); - } else if (msg.type == omx_message::EMPTY_BUFFER_DONE) { - const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource()); if (bufferSource != NULL) { + // fix up the buffer info (especially timestamp) if needed + bufferSource->codecBufferFilled(buffer); + + omx_message newMsg = msg; + newMsg.u.extended_buffer_data.timestamp = buffer->nTimeStamp; + mObserver->onMessage(newMsg); + return; + } + } else if (msg.type == omx_message::EMPTY_BUFFER_DONE) { + if (bufferSource != NULL) { // This is one of the buffers used exclusively by // GraphicBufferSource. // Don't dispatch a message back to ACodec, since it doesn't @@ -903,8 +927,7 @@ void OMXNodeInstance::onMessage(const omx_message &msg) { // be very confused. OMX_BUFFERHEADERTYPE *buffer = - static_cast<OMX_BUFFERHEADERTYPE *>( - msg.u.buffer_data.buffer); + findBufferHeader(msg.u.buffer_data.buffer); bufferSource->codecBufferEmptied(buffer); return; @@ -941,7 +964,7 @@ void OMXNodeInstance::onEvent( // static OMX_ERRORTYPE OMXNodeInstance::OnEvent( - OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_HANDLETYPE /* hComponent */, OMX_IN OMX_PTR pAppData, OMX_IN OMX_EVENTTYPE eEvent, OMX_IN OMX_U32 nData1, @@ -957,26 +980,28 @@ OMX_ERRORTYPE OMXNodeInstance::OnEvent( // static OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone( - OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_HANDLETYPE /* hComponent */, OMX_IN OMX_PTR pAppData, OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); if (instance->mDying) { return OMX_ErrorNone; } - return instance->owner()->OnEmptyBufferDone(instance->nodeID(), pBuffer); + return instance->owner()->OnEmptyBufferDone(instance->nodeID(), + instance->findBufferID(pBuffer), pBuffer); } // static OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone( - OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_HANDLETYPE /* hComponent */, OMX_IN OMX_PTR pAppData, OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); if (instance->mDying) { return OMX_ErrorNone; } - return instance->owner()->OnFillBufferDone(instance->nodeID(), pBuffer); + return instance->owner()->OnFillBufferDone(instance->nodeID(), + instance->findBufferID(pBuffer), pBuffer); } void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) { @@ -1011,4 +1036,67 @@ void OMXNodeInstance::freeActiveBuffers() { } } +#ifdef __LP64__ + +OMX::buffer_id OMXNodeInstance::makeBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) { + if (bufferHeader == NULL) { + return 0; + } + Mutex::Autolock autoLock(mBufferIDLock); + OMX::buffer_id buffer; + do { // handle the very unlikely case of ID overflow + if (++mBufferIDCount == 0) { + ++mBufferIDCount; + } + buffer = (OMX::buffer_id)mBufferIDCount; + } while (mBufferIDToBufferHeader.indexOfKey(buffer) >= 0); + mBufferIDToBufferHeader.add(buffer, bufferHeader); + mBufferHeaderToBufferID.add(bufferHeader, buffer); + return buffer; +} + +OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(OMX::buffer_id buffer) { + if (buffer == 0) { + return NULL; + } + Mutex::Autolock autoLock(mBufferIDLock); + return mBufferIDToBufferHeader.valueFor(buffer); +} + +OMX::buffer_id OMXNodeInstance::findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) { + if (bufferHeader == NULL) { + return 0; + } + Mutex::Autolock autoLock(mBufferIDLock); + return mBufferHeaderToBufferID.valueFor(bufferHeader); +} + +void OMXNodeInstance::invalidateBufferID(OMX::buffer_id buffer) { + if (buffer == 0) { + return; + } + Mutex::Autolock autoLock(mBufferIDLock); + mBufferHeaderToBufferID.removeItem(mBufferIDToBufferHeader.valueFor(buffer)); + mBufferIDToBufferHeader.removeItem(buffer); +} + +#else + +OMX::buffer_id OMXNodeInstance::makeBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) { + return (OMX::buffer_id)bufferHeader; +} + +OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(OMX::buffer_id buffer) { + return (OMX_BUFFERHEADERTYPE *)buffer; +} + +OMX::buffer_id OMXNodeInstance::findBufferID(OMX_BUFFERHEADERTYPE *bufferHeader) { + return (OMX::buffer_id)bufferHeader; +} + +void OMXNodeInstance::invalidateBufferID(OMX::buffer_id buffer __unused) { +} + +#endif + } // namespace android diff --git a/media/libstagefright/omx/SoftOMXComponent.cpp b/media/libstagefright/omx/SoftOMXComponent.cpp index b1c34dc..646cd32 100644 --- a/media/libstagefright/omx/SoftOMXComponent.cpp +++ b/media/libstagefright/omx/SoftOMXComponent.cpp @@ -257,69 +257,69 @@ OMX_ERRORTYPE SoftOMXComponent::GetStateWrapper( //////////////////////////////////////////////////////////////////////////////// OMX_ERRORTYPE SoftOMXComponent::sendCommand( - OMX_COMMANDTYPE cmd, OMX_U32 param, OMX_PTR data) { + OMX_COMMANDTYPE /* cmd */, OMX_U32 /* param */, OMX_PTR /* data */) { return OMX_ErrorUndefined; } OMX_ERRORTYPE SoftOMXComponent::getParameter( - OMX_INDEXTYPE index, OMX_PTR params) { + OMX_INDEXTYPE /* index */, OMX_PTR /* params */) { return OMX_ErrorUndefined; } OMX_ERRORTYPE SoftOMXComponent::setParameter( - OMX_INDEXTYPE index, const OMX_PTR params) { + OMX_INDEXTYPE /* index */, const OMX_PTR /* params */) { return OMX_ErrorUndefined; } OMX_ERRORTYPE SoftOMXComponent::getConfig( - OMX_INDEXTYPE index, OMX_PTR params) { + OMX_INDEXTYPE /* index */, OMX_PTR /* params */) { return OMX_ErrorUndefined; } OMX_ERRORTYPE SoftOMXComponent::setConfig( - OMX_INDEXTYPE index, const OMX_PTR params) { + OMX_INDEXTYPE /* index */, const OMX_PTR /* params */) { return OMX_ErrorUndefined; } OMX_ERRORTYPE SoftOMXComponent::getExtensionIndex( - const char *name, OMX_INDEXTYPE *index) { + const char * /* name */, OMX_INDEXTYPE * /* index */) { return OMX_ErrorUndefined; } OMX_ERRORTYPE SoftOMXComponent::useBuffer( - OMX_BUFFERHEADERTYPE **buffer, - OMX_U32 portIndex, - OMX_PTR appPrivate, - OMX_U32 size, - OMX_U8 *ptr) { + OMX_BUFFERHEADERTYPE ** /* buffer */, + OMX_U32 /* portIndex */, + OMX_PTR /* appPrivate */, + OMX_U32 /* size */, + OMX_U8 * /* ptr */) { return OMX_ErrorUndefined; } OMX_ERRORTYPE SoftOMXComponent::allocateBuffer( - OMX_BUFFERHEADERTYPE **buffer, - OMX_U32 portIndex, - OMX_PTR appPrivate, - OMX_U32 size) { + OMX_BUFFERHEADERTYPE ** /* buffer */, + OMX_U32 /* portIndex */, + OMX_PTR /* appPrivate */, + OMX_U32 /* size */) { return OMX_ErrorUndefined; } OMX_ERRORTYPE SoftOMXComponent::freeBuffer( - OMX_U32 portIndex, - OMX_BUFFERHEADERTYPE *buffer) { + OMX_U32 /* portIndex */, + OMX_BUFFERHEADERTYPE * /* buffer */) { return OMX_ErrorUndefined; } OMX_ERRORTYPE SoftOMXComponent::emptyThisBuffer( - OMX_BUFFERHEADERTYPE *buffer) { + OMX_BUFFERHEADERTYPE * /* buffer */) { return OMX_ErrorUndefined; } OMX_ERRORTYPE SoftOMXComponent::fillThisBuffer( - OMX_BUFFERHEADERTYPE *buffer) { + OMX_BUFFERHEADERTYPE * /* buffer */) { return OMX_ErrorUndefined; } -OMX_ERRORTYPE SoftOMXComponent::getState(OMX_STATETYPE *state) { +OMX_ERRORTYPE SoftOMXComponent::getState(OMX_STATETYPE * /* state */) { return OMX_ErrorUndefined; } diff --git a/media/libstagefright/omx/SoftOMXPlugin.cpp b/media/libstagefright/omx/SoftOMXPlugin.cpp index d6cde73..d49e50b 100644 --- a/media/libstagefright/omx/SoftOMXPlugin.cpp +++ b/media/libstagefright/omx/SoftOMXPlugin.cpp @@ -154,7 +154,7 @@ OMX_ERRORTYPE SoftOMXPlugin::destroyComponentInstance( OMX_ERRORTYPE SoftOMXPlugin::enumerateComponents( OMX_STRING name, - size_t size, + size_t /* size */, OMX_U32 index) { if (index >= kNumComponents) { return OMX_ErrorNoMore; diff --git a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp index 08a3d42..20a7076 100644 --- a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp +++ b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include <inttypes.h> + //#define LOG_NDEBUG 0 #define LOG_TAG "SoftVideoDecoderOMXComponent" #include <utils/Log.h> @@ -175,18 +177,19 @@ OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalGetParameter( { OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) params; + OMX_U32 profileIndex = profileLevel->nProfileIndex; if (profileLevel->nPortIndex != kInputPortIndex) { - ALOGE("Invalid port index: %ld", profileLevel->nPortIndex); + ALOGE("Invalid port index: %" PRIu32, profileLevel->nPortIndex); return OMX_ErrorUnsupportedIndex; } - if (index >= mNumProfileLevels) { + if (profileIndex >= mNumProfileLevels) { return OMX_ErrorNoMore; } - profileLevel->eProfile = mProfileLevels[index].mProfile; - profileLevel->eLevel = mProfileLevels[index].mLevel; + profileLevel->eProfile = mProfileLevels[profileIndex].mProfile; + profileLevel->eLevel = mProfileLevels[profileIndex].mLevel; return OMX_ErrorNone; } diff --git a/media/libstagefright/omx/tests/Android.mk b/media/libstagefright/omx/tests/Android.mk index 1061c39..e368134 100644 --- a/media/libstagefright/omx/tests/Android.mk +++ b/media/libstagefright/omx/tests/Android.mk @@ -15,4 +15,6 @@ LOCAL_MODULE := omx_tests LOCAL_MODULE_TAGS := tests +LOCAL_32_BIT_ONLY := true + include $(BUILD_EXECUTABLE) diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp index 4bee808..44e4f9d 100644 --- a/media/libstagefright/omx/tests/OMXHarness.cpp +++ b/media/libstagefright/omx/tests/OMXHarness.cpp @@ -16,6 +16,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "OMXHarness" +#include <inttypes.h> #include <utils/Log.h> #include "OMXHarness.h" @@ -711,11 +712,11 @@ status_t Harness::testSeek( int64_t bufferTimeUs; CHECK(buffer->meta_data()->findInt64(kKeyTime, &bufferTimeUs)); if (!CloseEnough(bufferTimeUs, actualSeekTimeUs)) { - printf("\n * Attempted seeking to %lld us (%.2f secs)", + printf("\n * Attempted seeking to %" PRId64 " us (%.2f secs)", requestedSeekTimeUs, requestedSeekTimeUs / 1E6); - printf("\n * Nearest keyframe is at %lld us (%.2f secs)", + printf("\n * Nearest keyframe is at %" PRId64 " us (%.2f secs)", actualSeekTimeUs, actualSeekTimeUs / 1E6); - printf("\n * Returned buffer was at %lld us (%.2f secs)\n\n", + printf("\n * Returned buffer was at %" PRId64 " us (%.2f secs)\n\n", bufferTimeUs, bufferTimeUs / 1E6); buffer->release(); diff --git a/media/libstagefright/rtsp/AAVCAssembler.cpp b/media/libstagefright/rtsp/AAVCAssembler.cpp index a6825eb..4bc67e8 100644 --- a/media/libstagefright/rtsp/AAVCAssembler.cpp +++ b/media/libstagefright/rtsp/AAVCAssembler.cpp @@ -124,7 +124,7 @@ ARTPAssembler::AssemblyStatus AAVCAssembler::addNALUnit( } void AAVCAssembler::addSingleNALUnit(const sp<ABuffer> &buffer) { - ALOGV("addSingleNALUnit of size %d", buffer->size()); + ALOGV("addSingleNALUnit of size %zu", buffer->size()); #if !LOG_NDEBUG hexdump(buffer->data(), buffer->size()); #endif @@ -191,7 +191,7 @@ ARTPAssembler::AssemblyStatus AAVCAssembler::addFragmentedNALUnit( CHECK((indicator & 0x1f) == 28); if (size < 2) { - ALOGV("Ignoring malformed FU buffer (size = %d)", size); + ALOGV("Ignoring malformed FU buffer (size = %zu)", size); queue->erase(queue->begin()); ++mNextExpectedSeqNo; @@ -225,7 +225,7 @@ ARTPAssembler::AssemblyStatus AAVCAssembler::addFragmentedNALUnit( } else { List<sp<ABuffer> >::iterator it = ++queue->begin(); while (it != queue->end()) { - ALOGV("sequence length %d", totalCount); + ALOGV("sequence length %zu", totalCount); const sp<ABuffer> &buffer = *it; @@ -294,7 +294,7 @@ ARTPAssembler::AssemblyStatus AAVCAssembler::addFragmentedNALUnit( for (size_t i = 0; i < totalCount; ++i) { const sp<ABuffer> &buffer = *it; - ALOGV("piece #%d/%d", i + 1, totalCount); + ALOGV("piece #%zu/%zu", i + 1, totalCount); #if !LOG_NDEBUG hexdump(buffer->data(), buffer->size()); #endif @@ -317,7 +317,7 @@ ARTPAssembler::AssemblyStatus AAVCAssembler::addFragmentedNALUnit( void AAVCAssembler::submitAccessUnit() { CHECK(!mNALUnits.empty()); - ALOGV("Access unit complete (%d nal units)", mNALUnits.size()); + ALOGV("Access unit complete (%zu nal units)", mNALUnits.size()); size_t totalSize = 0; for (List<sp<ABuffer> >::iterator it = mNALUnits.begin(); diff --git a/media/libstagefright/rtsp/AMPEG2TSAssembler.cpp b/media/libstagefright/rtsp/AMPEG2TSAssembler.cpp index 4c9bf5b..dca5c89 100644 --- a/media/libstagefright/rtsp/AMPEG2TSAssembler.cpp +++ b/media/libstagefright/rtsp/AMPEG2TSAssembler.cpp @@ -34,7 +34,9 @@ namespace android { AMPEG2TSAssembler::AMPEG2TSAssembler( - const sp<AMessage> ¬ify, const char *desc, const AString ¶ms) + const sp<AMessage> ¬ify, + const char * /* desc */, + const AString & /* params */) : mNotifyMsg(notify), mNextExpectedSeqNoValid(false), mNextExpectedSeqNo(0) { diff --git a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp index eefceba..98b50dd 100644 --- a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp +++ b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp @@ -365,7 +365,7 @@ ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::addPacket( void AMPEG4ElementaryAssembler::submitAccessUnit() { CHECK(!mPackets.empty()); - ALOGV("Access unit complete (%d nal units)", mPackets.size()); + ALOGV("Access unit complete (%zu nal units)", mPackets.size()); sp<ABuffer> accessUnit; diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp index af369b5..372fbe9 100644 --- a/media/libstagefright/rtsp/ARTPConnection.cpp +++ b/media/libstagefright/rtsp/ARTPConnection.cpp @@ -563,7 +563,7 @@ status_t ARTPConnection::parseRTCP(StreamInfo *s, const sp<ABuffer> &buffer) { default: { - ALOGW("Unknown RTCP packet type %u of size %d", + ALOGW("Unknown RTCP packet type %u of size %zu", (unsigned)data[1], headerLength); break; } diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp index 0d07043..793d116 100644 --- a/media/libstagefright/rtsp/ARTPWriter.cpp +++ b/media/libstagefright/rtsp/ARTPWriter.cpp @@ -114,7 +114,7 @@ bool ARTPWriter::reachedEOS() { return (mFlags & kFlagEOS) != 0; } -status_t ARTPWriter::start(MetaData *params) { +status_t ARTPWriter::start(MetaData * /* params */) { Mutex::Autolock autoLock(mLock); if (mFlags & kFlagStarted) { return INVALID_OPERATION; @@ -277,7 +277,7 @@ void ARTPWriter::onRead(const sp<AMessage> &msg) { } if (mediaBuf->range_length() > 0) { - ALOGV("read buffer of size %d", mediaBuf->range_length()); + ALOGV("read buffer of size %zu", mediaBuf->range_length()); if (mMode == H264) { StripStartcode(mediaBuf); diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp index efde7a9..492bd4a 100644 --- a/media/libstagefright/rtsp/ARTSPConnection.cpp +++ b/media/libstagefright/rtsp/ARTSPConnection.cpp @@ -239,7 +239,7 @@ void ARTSPConnection::onConnect(const sp<AMessage> &msg) { // right here, since we currently have no way of asking the user // for this information. - ALOGE("Malformed rtsp url %s", url.c_str()); + ALOGE("Malformed rtsp url <URL suppressed>"); reply->setInt32("result", ERROR_MALFORMED); reply->post(); diff --git a/media/libstagefright/rtsp/ARawAudioAssembler.cpp b/media/libstagefright/rtsp/ARawAudioAssembler.cpp index 0da5dd2..167f7a4 100644 --- a/media/libstagefright/rtsp/ARawAudioAssembler.cpp +++ b/media/libstagefright/rtsp/ARawAudioAssembler.cpp @@ -34,7 +34,9 @@ namespace android { ARawAudioAssembler::ARawAudioAssembler( - const sp<AMessage> ¬ify, const char *desc, const AString ¶ms) + const sp<AMessage> ¬ify, + const char * /* desc */, + const AString & /* params */) : mNotifyMsg(notify), mNextExpectedSeqNoValid(false), mNextExpectedSeqNo(0) { diff --git a/media/libstagefright/rtsp/Android.mk b/media/libstagefright/rtsp/Android.mk index e77c69c..36e8d82 100644 --- a/media/libstagefright/rtsp/Android.mk +++ b/media/libstagefright/rtsp/Android.mk @@ -30,6 +30,8 @@ ifeq ($(TARGET_ARCH),arm) LOCAL_CFLAGS += -Wno-psabi endif +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk + include $(BUILD_STATIC_LIBRARY) ################################################################################ @@ -55,4 +57,6 @@ LOCAL_MODULE_TAGS := optional LOCAL_MODULE:= rtp_test +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk + # include $(BUILD_EXECUTABLE) diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h index cd77aa0..e7580c2 100644 --- a/media/libstagefright/rtsp/MyHandler.h +++ b/media/libstagefright/rtsp/MyHandler.h @@ -149,7 +149,7 @@ struct MyHandler : public AHandler { mSessionURL.append(StringPrintf("%u", port)); mSessionURL.append(path); - ALOGI("rewritten session url: '%s'", mSessionURL.c_str()); + ALOGV("rewritten session url: '%s'", mSessionURL.c_str()); } mSessionHost = host; @@ -478,21 +478,32 @@ struct MyHandler : public AHandler { sp<ARTSPResponse> response = static_cast<ARTSPResponse *>(obj.get()); - if (response->mStatusCode == 302) { + if (response->mStatusCode == 301 || response->mStatusCode == 302) { ssize_t i = response->mHeaders.indexOfKey("location"); CHECK_GE(i, 0); - mSessionURL = response->mHeaders.valueAt(i); - - AString request; - request = "DESCRIBE "; - request.append(mSessionURL); - request.append(" RTSP/1.0\r\n"); - request.append("Accept: application/sdp\r\n"); - request.append("\r\n"); + mOriginalSessionURL = response->mHeaders.valueAt(i); + mSessionURL = mOriginalSessionURL; + + // Strip any authentication info from the session url, we don't + // want to transmit user/pass in cleartext. + AString host, path, user, pass; + unsigned port; + if (ARTSPConnection::ParseURL( + mSessionURL.c_str(), &host, &port, &path, &user, &pass) + && user.size() > 0) { + mSessionURL.clear(); + mSessionURL.append("rtsp://"); + mSessionURL.append(host); + mSessionURL.append(":"); + mSessionURL.append(StringPrintf("%u", port)); + mSessionURL.append(path); + + ALOGI("rewritten session url: '%s'", mSessionURL.c_str()); + } - sp<AMessage> reply = new AMessage('desc', id()); - mConn->sendRequest(request.c_str(), reply); + sp<AMessage> reply = new AMessage('conn', id()); + mConn->connect(mOriginalSessionURL.c_str(), reply); break; } diff --git a/media/libstagefright/rtsp/SDPLoader.cpp b/media/libstagefright/rtsp/SDPLoader.cpp index ed3fa7e..89ff17d 100644 --- a/media/libstagefright/rtsp/SDPLoader.cpp +++ b/media/libstagefright/rtsp/SDPLoader.cpp @@ -95,7 +95,7 @@ void SDPLoader::onLoad(const sp<AMessage> &msg) { msg->findPointer("headers", (void **)&headers); if (!(mFlags & kFlagIncognito)) { - ALOGI("onLoad '%s'", url.c_str()); + ALOGV("onLoad '%s'", url.c_str()); } else { ALOGI("onLoad <URL suppressed>"); } @@ -130,7 +130,7 @@ void SDPLoader::onLoad(const sp<AMessage> &msg) { ssize_t readSize = mHTTPDataSource->readAt(0, buffer->data(), sdpSize); if (readSize < 0) { - ALOGE("Failed to read SDP, error code = %ld", readSize); + ALOGE("Failed to read SDP, error code = %zu", readSize); err = UNKNOWN_ERROR; } else { desc = new ASessionDescription; diff --git a/media/libstagefright/tests/Android.mk b/media/libstagefright/tests/Android.mk index 06ce16b..903af49 100644 --- a/media/libstagefright/tests/Android.mk +++ b/media/libstagefright/tests/Android.mk @@ -41,6 +41,8 @@ LOCAL_C_INCLUDES := \ frameworks/av/media/libstagefright/include \ $(TOP)/frameworks/native/include/media/openmax \ +LOCAL_32_BIT_ONLY := true + include $(BUILD_EXECUTABLE) endif diff --git a/media/libstagefright/tests/DummyRecorder.cpp b/media/libstagefright/tests/DummyRecorder.cpp index ac37b28..8f17088 100644 --- a/media/libstagefright/tests/DummyRecorder.cpp +++ b/media/libstagefright/tests/DummyRecorder.cpp @@ -61,7 +61,7 @@ status_t DummyRecorder::stop() { mSource->stop(); void *dummy; pthread_join(mThread, &dummy); - status_t err = (status_t) dummy; + status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy)); ALOGV("Ending the reading thread"); return err; diff --git a/media/libstagefright/timedtext/Android.mk b/media/libstagefright/timedtext/Android.mk index f099bbd..6a8b9fc 100644 --- a/media/libstagefright/timedtext/Android.mk +++ b/media/libstagefright/timedtext/Android.mk @@ -9,7 +9,8 @@ LOCAL_SRC_FILES:= \ TimedTextSRTSource.cpp \ TimedTextPlayer.cpp -LOCAL_CFLAGS += -Wno-multichar +LOCAL_CFLAGS += -Wno-multichar -Werror + LOCAL_C_INCLUDES:= \ $(TOP)/frameworks/av/include/media/stagefright/timedtext \ $(TOP)/frameworks/av/media/libstagefright diff --git a/media/libstagefright/timedtext/TimedTextPlayer.cpp b/media/libstagefright/timedtext/TimedTextPlayer.cpp index 9fb0afe..a070487 100644 --- a/media/libstagefright/timedtext/TimedTextPlayer.cpp +++ b/media/libstagefright/timedtext/TimedTextPlayer.cpp @@ -18,6 +18,7 @@ #define LOG_TAG "TimedTextPlayer" #include <utils/Log.h> +#include <inttypes.h> #include <limits.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/AMessage.h> @@ -271,7 +272,7 @@ int64_t TimedTextPlayer::delayUsFromCurrentTime(int64_t fireTimeUs) { sp<MediaPlayerBase> listener = mListener.promote(); if (listener == NULL) { // TODO: it may be better to return kInvalidTimeUs - ALOGE("%s: Listener is NULL. (fireTimeUs = %lld)", + ALOGE("%s: Listener is NULL. (fireTimeUs = %" PRId64" )", __FUNCTION__, fireTimeUs); return 0; } diff --git a/media/libstagefright/timedtext/TimedTextSource.h b/media/libstagefright/timedtext/TimedTextSource.h index 756cc31..8c1c1cd 100644 --- a/media/libstagefright/timedtext/TimedTextSource.h +++ b/media/libstagefright/timedtext/TimedTextSource.h @@ -47,7 +47,7 @@ class TimedTextSource : public RefBase { int64_t *endTimeUs, Parcel *parcel, const MediaSource::ReadOptions *options = NULL) = 0; - virtual status_t extractGlobalDescriptions(Parcel *parcel) { + virtual status_t extractGlobalDescriptions(Parcel * /* parcel */) { return INVALID_OPERATION; } virtual sp<MetaData> getFormat(); diff --git a/media/libstagefright/wifi-display/rtp/RTPSender.cpp b/media/libstagefright/wifi-display/rtp/RTPSender.cpp index 1887b8b..e88a3bd 100644 --- a/media/libstagefright/wifi-display/rtp/RTPSender.cpp +++ b/media/libstagefright/wifi-display/rtp/RTPSender.cpp @@ -685,9 +685,8 @@ status_t RTPSender::onRTCPData(const sp<ABuffer> &buffer) { return OK; } -status_t RTPSender::parseReceiverReport(const uint8_t *data, size_t size) { - // hexdump(data, size); - +status_t RTPSender::parseReceiverReport( + const uint8_t *data, size_t /* size */) { float fractionLost = data[12] / 256.0f; ALOGI("lost %.2f %% of packets during report interval.", diff --git a/media/libstagefright/wifi-display/source/TSPacketizer.cpp b/media/libstagefright/wifi-display/source/TSPacketizer.cpp index c674700..50d317a 100644 --- a/media/libstagefright/wifi-display/source/TSPacketizer.cpp +++ b/media/libstagefright/wifi-display/source/TSPacketizer.cpp @@ -216,7 +216,7 @@ sp<ABuffer> TSPacketizer::Track::prependADTSHeader( uint8_t *ptr = dup->data(); *ptr++ = 0xff; - *ptr++ = 0xf1; // b11110001, ID=0, layer=0, protection_absent=1 + *ptr++ = 0xf9; // b11111001, ID=1(MPEG-2), layer=0, protection_absent=1 *ptr++ = profile << 6 @@ -565,7 +565,7 @@ status_t TSPacketizer::packetize( } } - // size_t numPaddingBytes = sizeAvailableForPayload - numBytesOfPayload; + size_t numPaddingBytes = sizeAvailableForPayload - numBytesOfPayload; ALOGV("packet 1 contains %zd padding bytes and %zd bytes of payload", numPaddingBytes, numBytesOfPayload); diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp index 05e4018..da405e2 100644 --- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp +++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp @@ -746,7 +746,7 @@ status_t WifiDisplaySource::sendM16(int32_t sessionID) { } status_t WifiDisplaySource::onReceiveM1Response( - int32_t sessionID, const sp<ParsedMessage> &msg) { + int32_t /* sessionID */, const sp<ParsedMessage> &msg) { int32_t statusCode; if (!msg->getStatusCode(&statusCode)) { return ERROR_MALFORMED; @@ -991,7 +991,7 @@ status_t WifiDisplaySource::onReceiveM4Response( } status_t WifiDisplaySource::onReceiveM5Response( - int32_t sessionID, const sp<ParsedMessage> &msg) { + int32_t /* sessionID */, const sp<ParsedMessage> &msg) { int32_t statusCode; if (!msg->getStatusCode(&statusCode)) { return ERROR_MALFORMED; @@ -1005,7 +1005,7 @@ status_t WifiDisplaySource::onReceiveM5Response( } status_t WifiDisplaySource::onReceiveM16Response( - int32_t sessionID, const sp<ParsedMessage> &msg) { + int32_t sessionID, const sp<ParsedMessage> & /* msg */) { // If only the response was required to include a "Session:" header... CHECK_EQ(sessionID, mClientSessionID); @@ -1680,7 +1680,7 @@ WifiDisplaySource::HDCPObserver::HDCPObserver( } void WifiDisplaySource::HDCPObserver::notify( - int msg, int ext1, int ext2, const Parcel *obj) { + int msg, int ext1, int ext2, const Parcel * /* obj */) { sp<AMessage> notify = mNotify->dup(); notify->setInt32("msg", msg); notify->setInt32("ext1", ext1); diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk index 1ac647a..d07bc99 100644 --- a/media/mediaserver/Android.mk +++ b/media/mediaserver/Android.mk @@ -35,5 +35,6 @@ LOCAL_C_INCLUDES := \ frameworks/av/services/camera/libcameraservice LOCAL_MODULE:= mediaserver +LOCAL_32_BIT_ONLY := true include $(BUILD_EXECUTABLE) diff --git a/media/mtp/Android.mk b/media/mtp/Android.mk index ac608a1..3af0956 100644 --- a/media/mtp/Android.mk +++ b/media/mtp/Android.mk @@ -39,9 +39,6 @@ LOCAL_MODULE:= libmtp LOCAL_CFLAGS := -DMTP_DEVICE -DMTP_HOST -# Needed for <bionic_time.h> -LOCAL_C_INCLUDES := bionic/libc/private - LOCAL_SHARED_LIBRARIES := libutils libcutils liblog libusbhost libbinder include $(BUILD_SHARED_LIBRARY) diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp index 930f0b0..e6e19e3 100644 --- a/media/mtp/MtpDataPacket.cpp +++ b/media/mtp/MtpDataPacket.cpp @@ -331,7 +331,7 @@ void MtpDataPacket::putString(const char* s) { void MtpDataPacket::putString(const uint16_t* string) { int count = 0; - for (int i = 0; i < 256; i++) { + for (int i = 0; i <= MTP_STRING_MAX_CHARACTER_NUMBER; i++) { if (string[i]) count++; else @@ -363,7 +363,7 @@ int MtpDataPacket::write(int fd) { } int MtpDataPacket::writeData(int fd, void* data, uint32_t length) { - allocate(length); + allocate(length + MTP_CONTAINER_HEADER_SIZE); memcpy(mBuffer + MTP_CONTAINER_HEADER_SIZE, data, length); length += MTP_CONTAINER_HEADER_SIZE; MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, length); diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp index d672dff..d6d5dd5 100644 --- a/media/mtp/MtpDevice.cpp +++ b/media/mtp/MtpDevice.cpp @@ -195,7 +195,7 @@ MtpDevice::MtpDevice(struct usb_device* device, int interface, MtpDevice::~MtpDevice() { close(); - for (int i = 0; i < mDeviceProperties.size(); i++) + for (size_t i = 0; i < mDeviceProperties.size(); i++) delete mDeviceProperties[i]; usb_request_free(mRequestIn1); usb_request_free(mRequestIn2); @@ -253,7 +253,7 @@ void MtpDevice::print() { ALOGI("*** FORMAT: %s\n", MtpDebug::getFormatCodeName(format)); MtpObjectPropertyList* props = getObjectPropsSupported(format); if (props) { - for (int j = 0; j < props->size(); j++) { + for (size_t j = 0; j < props->size(); j++) { MtpObjectProperty prop = (*props)[j]; MtpProperty* property = getObjectPropDesc(prop, format); if (property) { diff --git a/media/mtp/MtpProperty.cpp b/media/mtp/MtpProperty.cpp index 64dd45b..375ed9a 100644 --- a/media/mtp/MtpProperty.cpp +++ b/media/mtp/MtpProperty.cpp @@ -16,6 +16,7 @@ #define LOG_TAG "MtpProperty" +#include <inttypes.h> #include "MtpDataPacket.h" #include "MtpDebug.h" #include "MtpProperty.h" @@ -385,10 +386,10 @@ void MtpProperty::print(MtpPropertyValue& value, MtpString& buffer) { buffer.appendFormat("%d", value.u.u32); break; case MTP_TYPE_INT64: - buffer.appendFormat("%lld", value.u.i64); + buffer.appendFormat("%" PRId64, value.u.i64); break; case MTP_TYPE_UINT64: - buffer.appendFormat("%lld", value.u.u64); + buffer.appendFormat("%" PRIu64, value.u.u64); break; case MTP_TYPE_INT128: buffer.appendFormat("%08X%08X%08X%08X", value.u.i128[0], value.u.i128[1], diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp index df87db4..155f645 100644 --- a/media/mtp/MtpServer.cpp +++ b/media/mtp/MtpServer.cpp @@ -20,6 +20,7 @@ #include <sys/ioctl.h> #include <sys/stat.h> #include <fcntl.h> +#include <inttypes.h> #include <errno.h> #include <sys/stat.h> #include <dirent.h> @@ -124,7 +125,7 @@ void MtpServer::addStorage(MtpStorage* storage) { void MtpServer::removeStorage(MtpStorage* storage) { Mutex::Autolock autoLock(mMutex); - for (int i = 0; i < mStorages.size(); i++) { + for (size_t i = 0; i < mStorages.size(); i++) { if (mStorages[i] == storage) { mStorages.removeAt(i); sendStoreRemoved(storage->getStorageID()); @@ -136,7 +137,7 @@ void MtpServer::removeStorage(MtpStorage* storage) { MtpStorage* MtpServer::getStorage(MtpStorageID id) { if (id == 0) return mStorages[0]; - for (int i = 0; i < mStorages.size(); i++) { + for (size_t i = 0; i < mStorages.size(); i++) { MtpStorage* storage = mStorages[i]; if (storage->getStorageID() == id) return storage; @@ -1110,7 +1111,7 @@ MtpResponseCode MtpServer::doSendPartialObject() { } const char* filePath = (const char *)edit->mPath; - ALOGV("receiving partial %s %lld %lld\n", filePath, offset, length); + ALOGV("receiving partial %s %lld %" PRIu32 "\n", filePath, offset, length); // read the header, and possibly some data int ret = mData.read(mFD); diff --git a/media/mtp/MtpStringBuffer.cpp b/media/mtp/MtpStringBuffer.cpp index fe8cf04..f3420a4 100644 --- a/media/mtp/MtpStringBuffer.cpp +++ b/media/mtp/MtpStringBuffer.cpp @@ -56,42 +56,47 @@ MtpStringBuffer::~MtpStringBuffer() { } void MtpStringBuffer::set(const char* src) { - int length = strlen(src); - if (length >= sizeof(mBuffer)) - length = sizeof(mBuffer) - 1; - memcpy(mBuffer, src, length); - // count the characters int count = 0; char ch; - while ((ch = *src++) != 0) { + char* dest = (char*)mBuffer; + + while ((ch = *src++) != 0 && count < MTP_STRING_MAX_CHARACTER_NUMBER) { if ((ch & 0x80) == 0) { // single byte character + *dest++ = ch; } else if ((ch & 0xE0) == 0xC0) { // two byte character - if (! *src++) { + char ch1 = *src++; + if (! ch1) { // last character was truncated, so ignore last byte - length--; break; } + + *dest++ = ch; + *dest++ = ch1; } else if ((ch & 0xF0) == 0xE0) { // 3 byte char - if (! *src++) { + char ch1 = *src++; + if (! ch1) { // last character was truncated, so ignore last byte - length--; break; } - if (! *src++) { - // last character was truncated, so ignore last two bytes - length -= 2; + char ch2 = *src++; + if (! ch2) { + // last character was truncated, so ignore last byte break; } + + *dest++ = ch; + *dest++ = ch1; + *dest++ = ch2; } count++; } - mByteCount = length + 1; - mBuffer[length] = 0; + *dest++ = 0; + mByteCount = dest - (char*)mBuffer; mCharCount = count; } @@ -100,7 +105,7 @@ void MtpStringBuffer::set(const uint16_t* src) { uint16_t ch; uint8_t* dest = mBuffer; - while ((ch = *src++) != 0 && count < 255) { + while ((ch = *src++) != 0 && count < MTP_STRING_MAX_CHARACTER_NUMBER) { if (ch >= 0x0800) { *dest++ = (uint8_t)(0xE0 | (ch >> 12)); *dest++ = (uint8_t)(0x80 | ((ch >> 6) & 0x3F)); diff --git a/media/mtp/MtpStringBuffer.h b/media/mtp/MtpStringBuffer.h index cbc8307..e5150df 100644 --- a/media/mtp/MtpStringBuffer.h +++ b/media/mtp/MtpStringBuffer.h @@ -19,6 +19,9 @@ #include <stdint.h> +// Max Character number of a MTP String +#define MTP_STRING_MAX_CHARACTER_NUMBER 255 + namespace android { class MtpDataPacket; @@ -29,7 +32,7 @@ class MtpStringBuffer { private: // mBuffer contains string in UTF8 format // maximum 3 bytes/character, with 1 extra for zero termination - uint8_t mBuffer[255 * 3 + 1]; + uint8_t mBuffer[MTP_STRING_MAX_CHARACTER_NUMBER * 3 + 1]; int mCharCount; int mByteCount; diff --git a/media/mtp/MtpUtils.cpp b/media/mtp/MtpUtils.cpp index 6ec8876..0667bdd 100644 --- a/media/mtp/MtpUtils.cpp +++ b/media/mtp/MtpUtils.cpp @@ -19,7 +19,8 @@ #include <stdio.h> #include <time.h> -#include <cutils/tztime.h> +#include <../private/bionic_time.h> /* TODO: switch this code to icu4c! */ + #include "MtpUtils.h" namespace android { diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk index 54377f1..b895027 100644 --- a/services/audioflinger/Android.mk +++ b/services/audioflinger/Android.mk @@ -19,11 +19,8 @@ LOCAL_SRC_FILES:= \ Tracks.cpp \ Effects.cpp \ AudioMixer.cpp.arm \ - AudioResampler.cpp.arm \ AudioPolicyService.cpp \ ServiceUtilities.cpp \ - AudioResamplerCubic.cpp.arm \ - AudioResamplerSinc.cpp.arm LOCAL_SRC_FILES += StateQueue.cpp @@ -32,6 +29,7 @@ LOCAL_C_INCLUDES := \ $(call include-path-for, audio-utils) LOCAL_SHARED_LIBRARIES := \ + libaudioresampler \ libaudioutils \ libcommon_time_client \ libcutils \ @@ -43,7 +41,6 @@ LOCAL_SHARED_LIBRARIES := \ libhardware \ libhardware_legacy \ libeffects \ - libdl \ libpowermanager LOCAL_STATIC_LIBRARIES := \ @@ -52,6 +49,7 @@ LOCAL_STATIC_LIBRARIES := \ libmedia_helper LOCAL_MODULE:= libaudioflinger +LOCAL_32_BIT_ONLY := true LOCAL_SRC_FILES += FastMixer.cpp FastMixerState.cpp AudioWatchdog.cpp @@ -75,15 +73,9 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ test-resample.cpp \ - AudioResampler.cpp.arm \ - AudioResamplerCubic.cpp.arm \ - AudioResamplerSinc.cpp.arm LOCAL_SHARED_LIBRARIES := \ - libdl \ - libcutils \ - libutils \ - liblog + libaudioresampler \ LOCAL_MODULE:= test-resample @@ -91,4 +83,20 @@ LOCAL_MODULE_TAGS := optional include $(BUILD_EXECUTABLE) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + AudioResampler.cpp.arm \ + AudioResamplerCubic.cpp.arm \ + AudioResamplerSinc.cpp.arm + +LOCAL_SHARED_LIBRARIES := \ + libcutils \ + libdl \ + liblog + +LOCAL_MODULE := libaudioresampler + +include $(BUILD_SHARED_LIBRARY) + include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 3132e54..33b19a4 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -379,7 +379,7 @@ status_t AudioFlinger::dump(int fd, const Vector<String16>& args) if (mLogMemoryDealer != 0) { sp<IBinder> binder = defaultServiceManager()->getService(String16("media.log")); if (binder != 0) { - fdprintf(fd, "\nmedia.log:\n"); + dprintf(fd, "\nmedia.log:\n"); Vector<String16> args; binder->dump(fd, args); } @@ -513,6 +513,8 @@ sp<IAudioTrack> AudioFlinger::createTrack( track = thread->createTrack_l(client, streamType, sampleRate, format, channelMask, frameCount, sharedBuffer, lSessionId, flags, tid, clientUid, &lStatus); + LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (track == 0)); + // we don't abort yet if lStatus != NO_ERROR; there is still work to be done regardless // move effect chain to this output thread if an effect on same session was waiting // for a track to be created @@ -523,7 +525,7 @@ sp<IAudioTrack> AudioFlinger::createTrack( } // Look for sync events awaiting for a session to be used. - for (int i = 0; i < (int)mPendingSyncEvents.size(); i++) { + for (size_t i = 0; i < mPendingSyncEvents.size(); i++) { if (mPendingSyncEvents[i]->triggerSession() == lSessionId) { if (thread->isValidSyncEvent(mPendingSyncEvents[i])) { if (lStatus == NO_ERROR) { @@ -829,7 +831,7 @@ status_t AudioFlinger::setStreamMute(audio_stream_type_t stream, bool muted) AutoMutex lock(mLock); mStreamTypes[stream].mute = muted; - for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) + for (size_t i = 0; i < mPlaybackThreads.size(); i++) mPlaybackThreads.valueAt(i)->setStreamMute(stream, muted); return NO_ERROR; @@ -1010,7 +1012,7 @@ size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, audio_format_t form return size; } -unsigned int AudioFlinger::getInputFramesLost(audio_io_handle_t ioHandle) const +uint32_t AudioFlinger::getInputFramesLost(audio_io_handle_t ioHandle) const { Mutex::Autolock _l(mLock); @@ -1042,7 +1044,7 @@ status_t AudioFlinger::setVoiceVolume(float value) return ret; } -status_t AudioFlinger::getRenderPosition(size_t *halFrames, size_t *dspFrames, +status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, audio_io_handle_t output) const { status_t status; @@ -1291,7 +1293,7 @@ sp<IAudioRecord> AudioFlinger::openRecord( frameCount, lSessionId, IPCThreadState::self()->getCallingUid(), flags, tid, &lStatus); - LOG_ALWAYS_FATAL_IF((recordTrack != 0) != (lStatus == NO_ERROR)); + LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (recordTrack == 0)); } if (lStatus != NO_ERROR) { // remove local strong reference to Client before deleting the RecordTrack so that the @@ -2458,7 +2460,7 @@ void AudioFlinger::dumpTee(int fd, const sp<NBAIO_Source>& source, audio_io_hand } } else { if (fd >= 0) { - fdprintf(fd, "unable to rotate tees in %s: %s\n", teePath, strerror(errno)); + dprintf(fd, "unable to rotate tees in %s: %s\n", teePath, strerror(errno)); } } char teeTime[16]; @@ -2512,11 +2514,11 @@ void AudioFlinger::dumpTee(int fd, const sp<NBAIO_Source>& source, audio_io_hand write(teeFd, &temp, sizeof(temp)); close(teeFd); if (fd >= 0) { - fdprintf(fd, "tee copied to %s\n", teePath); + dprintf(fd, "tee copied to %s\n", teePath); } } else { if (fd >= 0) { - fdprintf(fd, "unable to create tee %s: %s\n", teePath, strerror(errno)); + dprintf(fd, "unable to create tee %s: %s\n", teePath, strerror(errno)); } } } diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index 53e238e..7320144 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -186,10 +186,10 @@ public: virtual status_t setVoiceVolume(float volume); - virtual status_t getRenderPosition(size_t *halFrames, size_t *dspFrames, + virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, audio_io_handle_t output) const; - virtual unsigned int getInputFramesLost(audio_io_handle_t ioHandle) const; + virtual uint32_t getInputFramesLost(audio_io_handle_t ioHandle) const; virtual int newAudioSessionId(); diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp index df4e029..f92421e 100644 --- a/services/audioflinger/AudioMixer.cpp +++ b/services/audioflinger/AudioMixer.cpp @@ -421,15 +421,16 @@ void AudioMixer::setParameter(int name, int target, int param, void *value) ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name); track_t& track = mState.tracks[name]; - int valueInt = (int)value; - int32_t *valueBuf = (int32_t *)value; + int valueInt = static_cast<int>(reinterpret_cast<uintptr_t>(value)); + int32_t *valueBuf = reinterpret_cast<int32_t*>(value); switch (target) { case TRACK: switch (param) { case CHANNEL_MASK: { - audio_channel_mask_t mask = (audio_channel_mask_t) value; + audio_channel_mask_t mask = + static_cast<audio_channel_mask_t>(reinterpret_cast<uintptr_t>(value)); if (track.channelMask != mask) { uint32_t channelCount = popcount(mask); ALOG_ASSERT((channelCount <= MAX_NUM_CHANNELS_TO_DOWNMIX) && channelCount); @@ -1122,10 +1123,6 @@ void AudioMixer::process__genericNoResampling(state_t* state, int64_t pts) t.bufferProvider->getNextBuffer(&t.buffer, pts); t.frameCount = t.buffer.frameCount; t.in = t.buffer.raw; - // t.in == NULL can happen if the track was flushed just after having - // been enabled for mixing. - if (t.in == NULL) - enabledTracks &= ~(1<<i); } e0 = enabledTracks; @@ -1161,6 +1158,13 @@ void AudioMixer::process__genericNoResampling(state_t* state, int64_t pts) aux = t.auxBuffer + numFrames; } while (outFrames) { + // t.in == NULL can happen if the track was flushed just after having + // been enabled for mixing. + if (t.in == NULL) { + enabledTracks &= ~(1<<i); + e1 &= ~(1<<i); + break; + } size_t inFrames = (t.frameCount > outFrames)?outFrames:t.frameCount; if (inFrames) { t.hook(&t, outTemp + (BLOCKSIZE-outFrames)*MAX_NUM_CHANNELS, inFrames, diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp index 35e816b..6ea5324 100644 --- a/services/audioflinger/AudioPolicyService.cpp +++ b/services/audioflinger/AudioPolicyService.cpp @@ -678,6 +678,10 @@ AudioPolicyService::AudioCommandThread::~AudioCommandThread() if (!mAudioCommands.isEmpty()) { release_wake_lock(mName.string()); } + for (size_t k=0; k < mAudioCommands.size(); k++) { + delete mAudioCommands[k]->mParam; + delete mAudioCommands[k]; + } mAudioCommands.clear(); delete mpToneGenerator; } @@ -849,7 +853,7 @@ void AudioPolicyService::AudioCommandThread::startToneCommand(ToneGenerator::ton ToneData *data = new ToneData(); data->mType = type; data->mStream = stream; - command->mParam = (void *)data; + command->mParam = data; Mutex::Autolock _l(mLock); insertCommand_l(command); ALOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream); @@ -950,7 +954,7 @@ void AudioPolicyService::AudioCommandThread::stopOutputCommand(audio_io_handle_t data->mIO = output; data->mStream = stream; data->mSession = session; - command->mParam = (void *)data; + command->mParam = data; Mutex::Autolock _l(mLock); insertCommand_l(command); ALOGV("AudioCommandThread() adding stop output %d", output); @@ -963,7 +967,7 @@ void AudioPolicyService::AudioCommandThread::releaseOutputCommand(audio_io_handl command->mCommand = RELEASE_OUTPUT; ReleaseOutputData *data = new ReleaseOutputData(); data->mIO = output; - command->mParam = (void *)data; + command->mParam = data; Mutex::Autolock _l(mLock); insertCommand_l(command); ALOGV("AudioCommandThread() adding release output %d", output); @@ -1052,6 +1056,10 @@ void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *comma for (size_t k = i + 1; k < mAudioCommands.size(); k++) { if (mAudioCommands[k] == removedCommands[j]) { ALOGV("suppressing command: %d", mAudioCommands[k]->mCommand); + // for commands that are not filtered, + // command->mParam is deleted in threadLoop + delete mAudioCommands[k]->mParam; + delete mAudioCommands[k]; mAudioCommands.removeAt(k); break; } @@ -1301,7 +1309,7 @@ effect_param_t *AudioPolicyService::loadEffectParameter(cnode *root) return fx_param; error: - delete fx_param; + free(fx_param); return NULL; } @@ -1433,6 +1441,14 @@ status_t AudioPolicyService::loadPreProcessorConfig(const char *path) loadEffects(root, effects); loadInputSources(root, effects); + // delete effects to fix memory leak. + // as effects is local var and valgrind would treat this as memory leak + // and although it only did in mediaserver init, but free it in case mediaserver reboot + size_t i; + for (i = 0; i < effects.size(); i++) { + delete effects[i]; + } + config_free(root); free(root); free(data); diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h index ae053a9..a38160f 100644 --- a/services/audioflinger/AudioPolicyService.h +++ b/services/audioflinger/AudioPolicyService.h @@ -197,6 +197,8 @@ private: void insertCommand_l(AudioCommand *command, int delayMs = 0); private: + class AudioCommandData; + // descriptor for requested tone playback event class AudioCommand { @@ -211,41 +213,48 @@ private: Condition mCond; // condition for status return status_t mStatus; // command status bool mWaitStatus; // true if caller is waiting for status - void *mParam; // command parameter (ToneData, VolumeData, ParametersData) + AudioCommandData *mParam; // command specific parameter data + }; + + class AudioCommandData { + public: + virtual ~AudioCommandData() {} + protected: + AudioCommandData() {} }; - class ToneData { + class ToneData : public AudioCommandData { public: ToneGenerator::tone_type mType; // tone type (START_TONE only) audio_stream_type_t mStream; // stream type (START_TONE only) }; - class VolumeData { + class VolumeData : public AudioCommandData { public: audio_stream_type_t mStream; float mVolume; audio_io_handle_t mIO; }; - class ParametersData { + class ParametersData : public AudioCommandData { public: audio_io_handle_t mIO; String8 mKeyValuePairs; }; - class VoiceVolumeData { + class VoiceVolumeData : public AudioCommandData { public: float mVolume; }; - class StopOutputData { + class StopOutputData : public AudioCommandData { public: audio_io_handle_t mIO; audio_stream_type_t mStream; int mSession; }; - class ReleaseOutputData { + class ReleaseOutputData : public AudioCommandData { public: audio_io_handle_t mIO; }; diff --git a/services/audioflinger/AudioResamplerSinc.cpp b/services/audioflinger/AudioResamplerSinc.cpp index 207f26b..e50b192 100644 --- a/services/audioflinger/AudioResamplerSinc.cpp +++ b/services/audioflinger/AudioResamplerSinc.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "AudioResamplerSinc" //#define LOG_NDEBUG 0 +#define __STDC_CONSTANT_MACROS #include <malloc.h> #include <string.h> #include <stdlib.h> @@ -37,12 +38,14 @@ #define USE_INLINE_ASSEMBLY (false) #endif -#if USE_INLINE_ASSEMBLY && defined(__ARM_NEON__) -#define USE_NEON (true) +#if defined(__aarch64__) || defined(__ARM_NEON__) +#include <arm_neon.h> +#define USE_NEON #else -#define USE_NEON (false) +#undef USE_NEON #endif +#define UNUSED(x) ((void)(x)) namespace android { // ---------------------------------------------------------------------------- @@ -634,8 +637,8 @@ void AudioResamplerSinc::read( } template<int CHANNELS> -void AudioResamplerSinc::filterCoefficient( - int32_t* out, uint32_t phase, const int16_t *samples, uint32_t vRL) +void AudioResamplerSinc::filterCoefficient(int32_t* out, uint32_t phase, + const int16_t *samples, uint32_t vRL) { // NOTE: be very careful when modifying the code here. register // pressure is very high and a small change might cause the compiler @@ -662,160 +665,171 @@ void AudioResamplerSinc::filterCoefficient( size_t count = offset; - if (!USE_NEON) { - int32_t l = 0; - int32_t r = 0; - for (size_t i=0 ; i<count ; i++) { - interpolate<CHANNELS>(l, r, coefsP++, offset, lerpP, sP); - sP -= CHANNELS; - interpolate<CHANNELS>(l, r, coefsN++, offset, lerpN, sN); - sN += CHANNELS; - } - out[0] += 2 * mulRL(1, l, vRL); - out[1] += 2 * mulRL(0, r, vRL); - } else if (CHANNELS == 1) { +#ifndef USE_NEON + int32_t l = 0; + int32_t r = 0; + for (size_t i=0 ; i<count ; i++) { + interpolate<CHANNELS>(l, r, coefsP++, offset, lerpP, sP); + sP -= CHANNELS; + interpolate<CHANNELS>(l, r, coefsN++, offset, lerpN, sN); + sN += CHANNELS; + } + out[0] += 2 * mulRL(1, l, vRL); + out[1] += 2 * mulRL(0, r, vRL); +#else + UNUSED(vRL); + if (CHANNELS == 1) { int32_t const* coefsP1 = coefsP + offset; int32_t const* coefsN1 = coefsN + offset; sP -= CHANNELS*3; - asm ( - "vmov.32 d2[0], %[lerpP] \n" // load the positive phase - "vmov.32 d2[1], %[lerpN] \n" // load the negative phase - "veor q0, q0, q0 \n" // result, initialize to 0 - "vshl.s32 d2, d2, #16 \n" // convert to 32 bits - - "1: \n" - "vld1.16 { d4}, [%[sP]] \n" // load 4 16-bits stereo samples - "vld1.32 { q8}, [%[coefsP0]:128]! \n" // load 4 32-bits coefs - "vld1.32 { q9}, [%[coefsP1]:128]! \n" // load 4 32-bits coefs for interpolation - "vld1.16 { d6}, [%[sN]]! \n" // load 4 16-bits stereo samples - "vld1.32 {q10}, [%[coefsN0]:128]! \n" // load 4 32-bits coefs - "vld1.32 {q11}, [%[coefsN1]:128]! \n" // load 4 32-bits coefs for interpolation - - "vrev64.16 d4, d4 \n" // reverse 2 frames of the positive side - - "vsub.s32 q9, q9, q8 \n" // interpolate (step1) 1st set of coefs - "vsub.s32 q11, q11, q10 \n" // interpolate (step1) 2nd set of coets - "vshll.s16 q12, d4, #15 \n" // extend samples to 31 bits - - "vqrdmulh.s32 q9, q9, d2[0] \n" // interpolate (step2) 1st set of coefs - "vqrdmulh.s32 q11, q11, d2[1] \n" // interpolate (step3) 2nd set of coefs - "vshll.s16 q14, d6, #15 \n" // extend samples to 31 bits - - "vadd.s32 q8, q8, q9 \n" // interpolate (step3) 1st set - "vadd.s32 q10, q10, q11 \n" // interpolate (step4) 2nd set - "subs %[count], %[count], #4 \n" // update loop counter - - "vqrdmulh.s32 q12, q12, q8 \n" // multiply samples by interpolated coef - "vqrdmulh.s32 q14, q14, q10 \n" // multiply samples by interpolated coef - "sub %[sP], %[sP], #8 \n" // move pointer to next set of samples - - "vadd.s32 q0, q0, q12 \n" // accumulate result - "vadd.s32 q0, q0, q14 \n" // accumulate result - - "bne 1b \n" // loop - - "vld1.s32 {d2}, [%[vLR]] \n" // load volumes - "vld1.s32 {d3}, %[out] \n" // load the output - "vpadd.s32 d0, d0, d1 \n" // add all 4 partial sums - "vpadd.s32 d0, d0, d0 \n" // together - "vdup.i32 d0, d0[0] \n" // interleave L,R channels - "vqrdmulh.s32 d0, d0, d2 \n" // apply volume - "vadd.s32 d3, d3, d0 \n" // accumulate result - "vst1.s32 {d3}, %[out] \n" // store result - - : [out] "=Uv" (out[0]), - [count] "+r" (count), - [coefsP0] "+r" (coefsP), - [coefsP1] "+r" (coefsP1), - [coefsN0] "+r" (coefsN), - [coefsN1] "+r" (coefsN1), - [sP] "+r" (sP), - [sN] "+r" (sN) - : [lerpP] "r" (lerpP), - [lerpN] "r" (lerpN), - [vLR] "r" (mVolumeSIMD) - : "cc", "memory", - "q0", "q1", "q2", "q3", - "q8", "q9", "q10", "q11", - "q12", "q14" - ); + + int32x4_t sum; + int32x2_t lerpPN; + lerpPN = vdup_n_s32(0); + lerpPN = vld1_lane_s32((int32_t *)&lerpP, lerpPN, 0); + lerpPN = vld1_lane_s32((int32_t *)&lerpN, lerpPN, 1); + lerpPN = vshl_n_s32(lerpPN, 16); + sum = vdupq_n_s32(0); + + int16x4_t sampleP, sampleN; + int32x4_t samplePExt, sampleNExt; + int32x4_t coefsPV0, coefsPV1, coefsNV0, coefsNV1; + + coefsP = (const int32_t*)__builtin_assume_aligned(coefsP, 16); + coefsN = (const int32_t*)__builtin_assume_aligned(coefsN, 16); + coefsP1 = (const int32_t*)__builtin_assume_aligned(coefsP1, 16); + coefsN1 = (const int32_t*)__builtin_assume_aligned(coefsN1, 16); + for (; count > 0; count -= 4) { + sampleP = vld1_s16(sP); + sampleN = vld1_s16(sN); + coefsPV0 = vld1q_s32(coefsP); + coefsNV0 = vld1q_s32(coefsN); + coefsPV1 = vld1q_s32(coefsP1); + coefsNV1 = vld1q_s32(coefsN1); + sP -= 4; + sN += 4; + coefsP += 4; + coefsN += 4; + coefsP1 += 4; + coefsN1 += 4; + + sampleP = vrev64_s16(sampleP); + + // interpolate (step1) + coefsPV1 = vsubq_s32(coefsPV1, coefsPV0); + coefsNV1 = vsubq_s32(coefsNV1, coefsNV0); + samplePExt = vshll_n_s16(sampleP, 15); + // interpolate (step2) + coefsPV1 = vqrdmulhq_lane_s32(coefsPV1, lerpPN, 0); + coefsNV1 = vqrdmulhq_lane_s32(coefsNV1, lerpPN, 1); + sampleNExt = vshll_n_s16(sampleN, 15); + // interpolate (step3) + coefsPV0 = vaddq_s32(coefsPV0, coefsPV1); + coefsNV0 = vaddq_s32(coefsNV0, coefsNV1); + + samplePExt = vqrdmulhq_s32(samplePExt, coefsPV0); + sampleNExt = vqrdmulhq_s32(sampleNExt, coefsNV0); + sum = vaddq_s32(sum, samplePExt); + sum = vaddq_s32(sum, sampleNExt); + } + int32x2_t volumesV, outV; + volumesV = vld1_s32(mVolumeSIMD); + outV = vld1_s32(out); + + //add all 4 partial sums + int32x2_t sumLow, sumHigh; + sumLow = vget_low_s32(sum); + sumHigh = vget_high_s32(sum); + sumLow = vpadd_s32(sumLow, sumHigh); + sumLow = vpadd_s32(sumLow, sumLow); + + sumLow = vqrdmulh_s32(sumLow, volumesV); + outV = vadd_s32(outV, sumLow); + vst1_s32(out, outV); } else if (CHANNELS == 2) { int32_t const* coefsP1 = coefsP + offset; int32_t const* coefsN1 = coefsN + offset; sP -= CHANNELS*3; - asm ( - "vmov.32 d2[0], %[lerpP] \n" // load the positive phase - "vmov.32 d2[1], %[lerpN] \n" // load the negative phase - "veor q0, q0, q0 \n" // result, initialize to 0 - "veor q4, q4, q4 \n" // result, initialize to 0 - "vshl.s32 d2, d2, #16 \n" // convert to 32 bits - - "1: \n" - "vld2.16 {d4,d5}, [%[sP]] \n" // load 4 16-bits stereo samples - "vld1.32 { q8}, [%[coefsP0]:128]! \n" // load 4 32-bits coefs - "vld1.32 { q9}, [%[coefsP1]:128]! \n" // load 4 32-bits coefs for interpolation - "vld2.16 {d6,d7}, [%[sN]]! \n" // load 4 16-bits stereo samples - "vld1.32 {q10}, [%[coefsN0]:128]! \n" // load 4 32-bits coefs - "vld1.32 {q11}, [%[coefsN1]:128]! \n" // load 4 32-bits coefs for interpolation - - "vrev64.16 d4, d4 \n" // reverse 2 frames of the positive side - "vrev64.16 d5, d5 \n" // reverse 2 frames of the positive side - - "vsub.s32 q9, q9, q8 \n" // interpolate (step1) 1st set of coefs - "vsub.s32 q11, q11, q10 \n" // interpolate (step1) 2nd set of coets - "vshll.s16 q12, d4, #15 \n" // extend samples to 31 bits - "vshll.s16 q13, d5, #15 \n" // extend samples to 31 bits - - "vqrdmulh.s32 q9, q9, d2[0] \n" // interpolate (step2) 1st set of coefs - "vqrdmulh.s32 q11, q11, d2[1] \n" // interpolate (step3) 2nd set of coefs - "vshll.s16 q14, d6, #15 \n" // extend samples to 31 bits - "vshll.s16 q15, d7, #15 \n" // extend samples to 31 bits - - "vadd.s32 q8, q8, q9 \n" // interpolate (step3) 1st set - "vadd.s32 q10, q10, q11 \n" // interpolate (step4) 2nd set - "subs %[count], %[count], #4 \n" // update loop counter - - "vqrdmulh.s32 q12, q12, q8 \n" // multiply samples by interpolated coef - "vqrdmulh.s32 q13, q13, q8 \n" // multiply samples by interpolated coef - "vqrdmulh.s32 q14, q14, q10 \n" // multiply samples by interpolated coef - "vqrdmulh.s32 q15, q15, q10 \n" // multiply samples by interpolated coef - "sub %[sP], %[sP], #16 \n" // move pointer to next set of samples - - "vadd.s32 q0, q0, q12 \n" // accumulate result - "vadd.s32 q4, q4, q13 \n" // accumulate result - "vadd.s32 q0, q0, q14 \n" // accumulate result - "vadd.s32 q4, q4, q15 \n" // accumulate result - - "bne 1b \n" // loop - - "vld1.s32 {d2}, [%[vLR]] \n" // load volumes - "vld1.s32 {d3}, %[out] \n" // load the output - "vpadd.s32 d0, d0, d1 \n" // add all 4 partial sums from q0 - "vpadd.s32 d8, d8, d9 \n" // add all 4 partial sums from q4 - "vpadd.s32 d0, d0, d0 \n" // together - "vpadd.s32 d8, d8, d8 \n" // together - "vtrn.s32 d0, d8 \n" // interlace L,R channels - "vqrdmulh.s32 d0, d0, d2 \n" // apply volume - "vadd.s32 d3, d3, d0 \n" // accumulate result - "vst1.s32 {d3}, %[out] \n" // store result - - : [out] "=Uv" (out[0]), - [count] "+r" (count), - [coefsP0] "+r" (coefsP), - [coefsP1] "+r" (coefsP1), - [coefsN0] "+r" (coefsN), - [coefsN1] "+r" (coefsN1), - [sP] "+r" (sP), - [sN] "+r" (sN) - : [lerpP] "r" (lerpP), - [lerpN] "r" (lerpN), - [vLR] "r" (mVolumeSIMD) - : "cc", "memory", - "q0", "q1", "q2", "q3", "q4", - "q8", "q9", "q10", "q11", - "q12", "q13", "q14", "q15" - ); + + int32x4_t sum0, sum1; + int32x2_t lerpPN; + + lerpPN = vdup_n_s32(0); + lerpPN = vld1_lane_s32((int32_t *)&lerpP, lerpPN, 0); + lerpPN = vld1_lane_s32((int32_t *)&lerpN, lerpPN, 1); + lerpPN = vshl_n_s32(lerpPN, 16); + sum0 = vdupq_n_s32(0); + sum1 = vdupq_n_s32(0); + + int16x4x2_t sampleP, sampleN; + int32x4x2_t samplePExt, sampleNExt; + int32x4_t coefsPV0, coefsPV1, coefsNV0, coefsNV1; + + coefsP = (const int32_t*)__builtin_assume_aligned(coefsP, 16); + coefsN = (const int32_t*)__builtin_assume_aligned(coefsN, 16); + coefsP1 = (const int32_t*)__builtin_assume_aligned(coefsP1, 16); + coefsN1 = (const int32_t*)__builtin_assume_aligned(coefsN1, 16); + for (; count > 0; count -= 4) { + sampleP = vld2_s16(sP); + sampleN = vld2_s16(sN); + coefsPV0 = vld1q_s32(coefsP); + coefsNV0 = vld1q_s32(coefsN); + coefsPV1 = vld1q_s32(coefsP1); + coefsNV1 = vld1q_s32(coefsN1); + sP -= 8; + sN += 8; + coefsP += 4; + coefsN += 4; + coefsP1 += 4; + coefsN1 += 4; + + sampleP.val[0] = vrev64_s16(sampleP.val[0]); + sampleP.val[1] = vrev64_s16(sampleP.val[1]); + + // interpolate (step1) + coefsPV1 = vsubq_s32(coefsPV1, coefsPV0); + coefsNV1 = vsubq_s32(coefsNV1, coefsNV0); + samplePExt.val[0] = vshll_n_s16(sampleP.val[0], 15); + samplePExt.val[1] = vshll_n_s16(sampleP.val[1], 15); + // interpolate (step2) + coefsPV1 = vqrdmulhq_lane_s32(coefsPV1, lerpPN, 0); + coefsNV1 = vqrdmulhq_lane_s32(coefsNV1, lerpPN, 1); + sampleNExt.val[0] = vshll_n_s16(sampleN.val[0], 15); + sampleNExt.val[1] = vshll_n_s16(sampleN.val[1], 15); + // interpolate (step3) + coefsPV0 = vaddq_s32(coefsPV0, coefsPV1); + coefsNV0 = vaddq_s32(coefsNV0, coefsNV1); + + samplePExt.val[0] = vqrdmulhq_s32(samplePExt.val[0], coefsPV0); + samplePExt.val[1] = vqrdmulhq_s32(samplePExt.val[1], coefsPV0); + sampleNExt.val[0] = vqrdmulhq_s32(sampleNExt.val[0], coefsNV0); + sampleNExt.val[1] = vqrdmulhq_s32(sampleNExt.val[1], coefsNV0); + sum0 = vaddq_s32(sum0, samplePExt.val[0]); + sum1 = vaddq_s32(sum1, samplePExt.val[1]); + sum0 = vaddq_s32(sum0, sampleNExt.val[0]); + sum1 = vaddq_s32(sum1, sampleNExt.val[1]); + } + int32x2_t volumesV, outV; + volumesV = vld1_s32(mVolumeSIMD); + outV = vld1_s32(out); + + //add all 4 partial sums + int32x2_t sumLow0, sumHigh0, sumLow1, sumHigh1; + sumLow0 = vget_low_s32(sum0); + sumHigh0 = vget_high_s32(sum0); + sumLow1 = vget_low_s32(sum1); + sumHigh1 = vget_high_s32(sum1); + sumLow0 = vpadd_s32(sumLow0, sumHigh0); + sumLow0 = vpadd_s32(sumLow0, sumLow0); + sumLow1 = vpadd_s32(sumLow1, sumHigh1); + sumLow1 = vpadd_s32(sumLow1, sumLow1); + + sumLow0 = vtrn_s32(sumLow0, sumLow1).val[0]; + sumLow0 = vqrdmulh_s32(sumLow0, volumesV); + outV = vadd_s32(outV, sumLow0); + vst1_s32(out, outV); } +#endif } template<int CHANNELS> diff --git a/services/audioflinger/AudioWatchdog.cpp b/services/audioflinger/AudioWatchdog.cpp index 93d185e..877e776 100644 --- a/services/audioflinger/AudioWatchdog.cpp +++ b/services/audioflinger/AudioWatchdog.cpp @@ -34,7 +34,7 @@ void AudioWatchdogDump::dump(int fd) } else { strcpy(buf, "N/A\n"); } - fdprintf(fd, "Watchdog: underruns=%u, logs=%u, most recent underrun log at %s", + dprintf(fd, "Watchdog: underruns=%u, logs=%u, most recent underrun log at %s", mUnderruns, mLogs, buf); } diff --git a/services/audioflinger/Configuration.h b/services/audioflinger/Configuration.h index bc2038a..0754d9d 100644 --- a/services/audioflinger/Configuration.h +++ b/services/audioflinger/Configuration.h @@ -32,9 +32,6 @@ // uncomment to enable fast mixer to take performance samples for later statistical analysis #define FAST_MIXER_STATISTICS -// uncomment to allow fast tracks at non-native sample rate -//#define FAST_TRACKS_AT_NON_NATIVE_SAMPLE_RATE - // uncomment for debugging timing problems related to StateQueue::push() //#define STATE_QUEUE_DUMP diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp index a8a5169..010e233 100644 --- a/services/audioflinger/Effects.cpp +++ b/services/audioflinger/Effects.cpp @@ -820,8 +820,8 @@ void AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args) } result.append("\t\tSession Status State Engine:\n"); - snprintf(buffer, SIZE, "\t\t%05d %03d %03d 0x%08x\n", - mSessionId, mStatus, mState, (uint32_t)mEffectInterface); + snprintf(buffer, SIZE, "\t\t%05d %03d %03d %p\n", + mSessionId, mStatus, mState, mEffectInterface); result.append(buffer); result.append("\t\tDescriptor:\n"); @@ -850,26 +850,26 @@ void AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args) result.append(buffer); result.append("\t\t- Input configuration:\n"); - result.append("\t\t\tBuffer Frames Smp rate Channels Format\n"); - snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n", - (uint32_t)mConfig.inputCfg.buffer.raw, + result.append("\t\t\tFrames Smp rate Channels Format Buffer\n"); + snprintf(buffer, SIZE, "\t\t\t%05zu %05d %08x %6d %p\n", mConfig.inputCfg.buffer.frameCount, mConfig.inputCfg.samplingRate, mConfig.inputCfg.channels, - mConfig.inputCfg.format); + mConfig.inputCfg.format, + mConfig.inputCfg.buffer.raw); result.append(buffer); result.append("\t\t- Output configuration:\n"); result.append("\t\t\tBuffer Frames Smp rate Channels Format\n"); - snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n", - (uint32_t)mConfig.outputCfg.buffer.raw, + snprintf(buffer, SIZE, "\t\t\t%p %05zu %05d %08x %d\n", + mConfig.outputCfg.buffer.raw, mConfig.outputCfg.buffer.frameCount, mConfig.outputCfg.samplingRate, mConfig.outputCfg.channels, mConfig.outputCfg.format); result.append(buffer); - snprintf(buffer, SIZE, "\t\t%d Clients:\n", mHandles.size()); + snprintf(buffer, SIZE, "\t\t%zu Clients:\n", mHandles.size()); result.append(buffer); result.append("\t\t\tPid Priority Ctrl Locked client server\n"); for (size_t i = 0; i < mHandles.size(); ++i) { @@ -1578,10 +1578,10 @@ void AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args) } result.append("\tNum fx In buffer Out buffer Active tracks:\n"); - snprintf(buffer, SIZE, "\t%02d 0x%08x 0x%08x %d\n", + snprintf(buffer, SIZE, "\t%02zu %p %p %d\n", mEffects.size(), - (uint32_t)mInBuffer, - (uint32_t)mOutBuffer, + mInBuffer, + mOutBuffer, mActiveTrackCnt); result.append(buffer); write(fd, result.string(), result.size()); diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp index f27ea17..6d87838 100644 --- a/services/audioflinger/FastMixer.cpp +++ b/services/audioflinger/FastMixer.cpp @@ -26,7 +26,6 @@ #define ATRACE_TAG ATRACE_TAG_AUDIO #include "Configuration.h" -#include <sys/atomics.h> #include <time.h> #include <utils/Log.h> #include <utils/Trace.h> @@ -179,7 +178,7 @@ bool FastMixer::threadLoop() ALOG_ASSERT(coldFutexAddr != NULL); int32_t old = android_atomic_dec(coldFutexAddr); if (old <= 0) { - __futex_syscall4(coldFutexAddr, FUTEX_WAIT_PRIVATE, old - 1, NULL); + (void) syscall(__NR_futex, coldFutexAddr, FUTEX_WAIT_PRIVATE, old - 1, NULL); } int policy = sched_getscheduler(0); if (!(policy == SCHED_FIFO || policy == SCHED_RR)) { @@ -236,7 +235,6 @@ bool FastMixer::threadLoop() sampleRate = Format_sampleRate(format); ALOG_ASSERT(Format_channelCount(format) == FCC_2); } - dumpState->mSampleRate = sampleRate; } if ((format != previousFormat) || (frameCount != previous->mFrameCount)) { @@ -321,12 +319,8 @@ bool FastMixer::threadLoop() mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MAIN_BUFFER, (void *) mixBuffer); // newly allocated track names default to full scale volume - if (fastTrack->mSampleRate != 0 && fastTrack->mSampleRate != sampleRate) { - mixer->setParameter(name, AudioMixer::RESAMPLE, - AudioMixer::SAMPLE_RATE, (void*) fastTrack->mSampleRate); - } mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::CHANNEL_MASK, - (void *) fastTrack->mChannelMask); + (void *)(uintptr_t)fastTrack->mChannelMask); mixer->enable(name); } generations[i] = fastTrack->mGeneration; @@ -353,16 +347,10 @@ bool FastMixer::threadLoop() mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, (void *)0x1000); } - if (fastTrack->mSampleRate != 0 && - fastTrack->mSampleRate != sampleRate) { - mixer->setParameter(name, AudioMixer::RESAMPLE, - AudioMixer::SAMPLE_RATE, (void*) fastTrack->mSampleRate); - } else { - mixer->setParameter(name, AudioMixer::RESAMPLE, - AudioMixer::REMOVE, NULL); - } + mixer->setParameter(name, AudioMixer::RESAMPLE, + AudioMixer::REMOVE, NULL); mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::CHANNEL_MASK, - (void *) fastTrack->mChannelMask); + (void *)(uintptr_t) fastTrack->mChannelMask); // already enabled } generations[i] = fastTrack->mGeneration; @@ -392,16 +380,8 @@ bool FastMixer::threadLoop() // Refresh the per-track timestamp if (timestampStatus == NO_ERROR) { - uint32_t trackFramesWrittenButNotPresented; - uint32_t trackSampleRate = fastTrack->mSampleRate; - // There is currently no sample rate conversion for fast tracks currently - if (trackSampleRate != 0 && trackSampleRate != sampleRate) { - trackFramesWrittenButNotPresented = - ((int64_t) nativeFramesWrittenButNotPresented * trackSampleRate) / - sampleRate; - } else { - trackFramesWrittenButNotPresented = nativeFramesWrittenButNotPresented; - } + uint32_t trackFramesWrittenButNotPresented = + nativeFramesWrittenButNotPresented; uint32_t trackFramesWritten = fastTrack->mBufferProvider->framesReleased(); // Can't provide an AudioTimestamp before first frame presented, // or during the brief 32-bit wraparound window @@ -419,9 +399,9 @@ bool FastMixer::threadLoop() if (fastTrack->mVolumeProvider != NULL) { uint32_t vlr = fastTrack->mVolumeProvider->getVolumeLR(); mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, - (void *)(vlr & 0xFFFF)); + (void *)(uintptr_t)(vlr & 0xFFFF)); mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, - (void *)(vlr >> 16)); + (void *)(uintptr_t)(vlr >> 16)); } // FIXME The current implementation of framesReady() for fast tracks // takes a tryLock, which can block @@ -714,7 +694,7 @@ static int compare_uint32_t(const void *pa, const void *pb) void FastMixerDumpState::dump(int fd) const { if (mCommand == FastMixerState::INITIAL) { - fdprintf(fd, "FastMixer not initialized\n"); + dprintf(fd, "FastMixer not initialized\n"); return; } #define COMMAND_MAX 32 @@ -748,9 +728,9 @@ void FastMixerDumpState::dump(int fd) const double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) + (mMeasuredWarmupTs.tv_nsec / 1000000.0); double mixPeriodSec = (double) mFrameCount / (double) mSampleRate; - fdprintf(fd, "FastMixer command=%s writeSequence=%u framesWritten=%u\n" + dprintf(fd, "FastMixer command=%s writeSequence=%u framesWritten=%u\n" " numTracks=%u writeErrors=%u underruns=%u overruns=%u\n" - " sampleRate=%u frameCount=%u measuredWarmup=%.3g ms, warmupCycles=%u\n" + " sampleRate=%u frameCount=%zu measuredWarmup=%.3g ms, warmupCycles=%u\n" " mixPeriod=%.2f ms\n", string, mWriteSequence, mFramesWritten, mNumTracks, mWriteErrors, mUnderruns, mOverruns, @@ -802,21 +782,21 @@ void FastMixerDumpState::dump(int fd) const previousCpukHz = sampleCpukHz; #endif } - fdprintf(fd, "Simple moving statistics over last %.1f seconds:\n", wall.n() * mixPeriodSec); - fdprintf(fd, " wall clock time in ms per mix cycle:\n" - " mean=%.2f min=%.2f max=%.2f stddev=%.2f\n", - wall.mean()*1e-6, wall.minimum()*1e-6, wall.maximum()*1e-6, wall.stddev()*1e-6); - fdprintf(fd, " raw CPU load in us per mix cycle:\n" - " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n", - loadNs.mean()*1e-3, loadNs.minimum()*1e-3, loadNs.maximum()*1e-3, - loadNs.stddev()*1e-3); + dprintf(fd, "Simple moving statistics over last %.1f seconds:\n", wall.n() * mixPeriodSec); + dprintf(fd, " wall clock time in ms per mix cycle:\n" + " mean=%.2f min=%.2f max=%.2f stddev=%.2f\n", + wall.mean()*1e-6, wall.minimum()*1e-6, wall.maximum()*1e-6, wall.stddev()*1e-6); + dprintf(fd, " raw CPU load in us per mix cycle:\n" + " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n", + loadNs.mean()*1e-3, loadNs.minimum()*1e-3, loadNs.maximum()*1e-3, + loadNs.stddev()*1e-3); #ifdef CPU_FREQUENCY_STATISTICS - fdprintf(fd, " CPU clock frequency in MHz:\n" - " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n", - kHz.mean()*1e-3, kHz.minimum()*1e-3, kHz.maximum()*1e-3, kHz.stddev()*1e-3); - fdprintf(fd, " adjusted CPU load in MHz (i.e. normalized for CPU clock frequency):\n" - " mean=%.1f min=%.1f max=%.1f stddev=%.1f\n", - loadMHz.mean(), loadMHz.minimum(), loadMHz.maximum(), loadMHz.stddev()); + dprintf(fd, " CPU clock frequency in MHz:\n" + " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n", + kHz.mean()*1e-3, kHz.minimum()*1e-3, kHz.maximum()*1e-3, kHz.stddev()*1e-3); + dprintf(fd, " adjusted CPU load in MHz (i.e. normalized for CPU clock frequency):\n" + " mean=%.1f min=%.1f max=%.1f stddev=%.1f\n", + loadMHz.mean(), loadMHz.minimum(), loadMHz.maximum(), loadMHz.stddev()); #endif if (tail != NULL) { qsort(tail, n, sizeof(uint32_t), compare_uint32_t); @@ -827,12 +807,12 @@ void FastMixerDumpState::dump(int fd) const left.sample(tail[i]); right.sample(tail[n - (i + 1)]); } - fdprintf(fd, "Distribution of mix cycle times in ms for the tails (> ~3 stddev outliers):\n" - " left tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n" - " right tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n", - left.mean()*1e-6, left.minimum()*1e-6, left.maximum()*1e-6, left.stddev()*1e-6, - right.mean()*1e-6, right.minimum()*1e-6, right.maximum()*1e-6, - right.stddev()*1e-6); + dprintf(fd, "Distribution of mix cycle times in ms for the tails (> ~3 stddev outliers):\n" + " left tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n" + " right tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n", + left.mean()*1e-6, left.minimum()*1e-6, left.maximum()*1e-6, left.stddev()*1e-6, + right.mean()*1e-6, right.minimum()*1e-6, right.maximum()*1e-6, + right.stddev()*1e-6); delete[] tail; } #endif @@ -842,9 +822,9 @@ void FastMixerDumpState::dump(int fd) const // Instead we always display all tracks, with an indication // of whether we think the track is active. uint32_t trackMask = mTrackMask; - fdprintf(fd, "Fast tracks: kMaxFastTracks=%u activeMask=%#x\n", + dprintf(fd, "Fast tracks: kMaxFastTracks=%u activeMask=%#x\n", FastMixerState::kMaxFastTracks, trackMask); - fdprintf(fd, "Index Active Full Partial Empty Recent Ready\n"); + dprintf(fd, "Index Active Full Partial Empty Recent Ready\n"); for (uint32_t i = 0; i < FastMixerState::kMaxFastTracks; ++i, trackMask >>= 1) { bool isActive = trackMask & 1; const FastTrackDump *ftDump = &mTracks[i]; @@ -864,7 +844,7 @@ void FastMixerDumpState::dump(int fd) const mostRecent = "?"; break; } - fdprintf(fd, "%5u %6s %4u %7u %5u %7s %5u\n", i, isActive ? "yes" : "no", + dprintf(fd, "%5u %6s %4u %7u %5u %7s %5zu\n", i, isActive ? "yes" : "no", (underruns.mBitFields.mFull) & UNDERRUN_MASK, (underruns.mBitFields.mPartial) & UNDERRUN_MASK, (underruns.mBitFields.mEmpty) & UNDERRUN_MASK, diff --git a/services/audioflinger/FastMixer.h b/services/audioflinger/FastMixer.h index 6158925..c356d31 100644 --- a/services/audioflinger/FastMixer.h +++ b/services/audioflinger/FastMixer.h @@ -17,11 +17,10 @@ #ifndef ANDROID_AUDIO_FAST_MIXER_H #define ANDROID_AUDIO_FAST_MIXER_H +#include <linux/futex.h> +#include <sys/syscall.h> #include <utils/Debug.h> #include <utils/Thread.h> -extern "C" { -#include "../private/bionic_futex.h" -} #include "StateQueue.h" #include "FastMixerState.h" diff --git a/services/audioflinger/FastMixerState.cpp b/services/audioflinger/FastMixerState.cpp index 737de97..43ff233 100644 --- a/services/audioflinger/FastMixerState.cpp +++ b/services/audioflinger/FastMixerState.cpp @@ -20,7 +20,7 @@ namespace android { FastTrack::FastTrack() : - mBufferProvider(NULL), mVolumeProvider(NULL), mSampleRate(0), + mBufferProvider(NULL), mVolumeProvider(NULL), mChannelMask(AUDIO_CHANNEL_OUT_STEREO), mGeneration(0) { } diff --git a/services/audioflinger/FastMixerState.h b/services/audioflinger/FastMixerState.h index f6e7903..9739fe9 100644 --- a/services/audioflinger/FastMixerState.h +++ b/services/audioflinger/FastMixerState.h @@ -43,7 +43,6 @@ struct FastTrack { ExtendedAudioBufferProvider* mBufferProvider; // must be NULL if inactive, or non-NULL if active VolumeProvider* mVolumeProvider; // optional; if NULL then full-scale - unsigned mSampleRate; // optional; if zero then use mixer sample rate audio_channel_mask_t mChannelMask; // AUDIO_CHANNEL_OUT_MONO or AUDIO_CHANNEL_OUT_STEREO int mGeneration; // increment when any field is assigned }; diff --git a/services/audioflinger/StateQueue.cpp b/services/audioflinger/StateQueue.cpp index c2d3bbd..40d7bcd 100644 --- a/services/audioflinger/StateQueue.cpp +++ b/services/audioflinger/StateQueue.cpp @@ -28,12 +28,12 @@ namespace android { #ifdef STATE_QUEUE_DUMP void StateQueueObserverDump::dump(int fd) { - fdprintf(fd, "State queue observer: stateChanges=%u\n", mStateChanges); + dprintf(fd, "State queue observer: stateChanges=%u\n", mStateChanges); } void StateQueueMutatorDump::dump(int fd) { - fdprintf(fd, "State queue mutator: pushDirty=%u pushAck=%u blockedSequence=%u\n", + dprintf(fd, "State queue mutator: pushDirty=%u pushAck=%u blockedSequence=%u\n", mPushDirty, mPushAck, mBlockedSequence); } #endif @@ -41,13 +41,14 @@ void StateQueueMutatorDump::dump(int fd) // Constructor and destructor template<typename T> StateQueue<T>::StateQueue() : - mNext(NULL), mAck(NULL), mCurrent(NULL), + mAck(NULL), mCurrent(NULL), mMutating(&mStates[0]), mExpecting(NULL), mInMutation(false), mIsDirty(false), mIsInitialized(false) #ifdef STATE_QUEUE_DUMP , mObserverDump(&mObserverDummyDump), mMutatorDump(&mMutatorDummyDump) #endif { + atomic_init(&mNext, 0); } template<typename T> StateQueue<T>::~StateQueue() @@ -58,7 +59,8 @@ template<typename T> StateQueue<T>::~StateQueue() template<typename T> const T* StateQueue<T>::poll() { - const T *next = (const T *) android_atomic_acquire_load((volatile int32_t *) &mNext); + const T *next = (const T *) atomic_load_explicit(&mNext, memory_order_acquire); + if (next != mCurrent) { mAck = next; // no additional barrier needed mCurrent = next; @@ -140,7 +142,7 @@ template<typename T> bool StateQueue<T>::push(StateQueue<T>::block_t block) } // publish - android_atomic_release_store((int32_t) mMutating, (volatile int32_t *) &mNext); + atomic_store_explicit(&mNext, (uintptr_t)mMutating, memory_order_release); mExpecting = mMutating; // copy with circular wraparound diff --git a/services/audioflinger/StateQueue.h b/services/audioflinger/StateQueue.h index 9cde642..ef01df7 100644 --- a/services/audioflinger/StateQueue.h +++ b/services/audioflinger/StateQueue.h @@ -17,6 +17,8 @@ #ifndef ANDROID_AUDIO_STATE_QUEUE_H #define ANDROID_AUDIO_STATE_QUEUE_H +#include <stdatomic.h> + // The state queue template class was originally driven by this use case / requirements: // There are two threads: a fast mixer, and a normal mixer, and they share state. // The interesting part of the shared state is a set of active fast tracks, @@ -184,7 +186,7 @@ private: T mStates[kN]; // written by mutator, read by observer // "volatile" is meaningless with SMP, but here it indicates that we're using atomic ops - volatile const T* mNext; // written by mutator to advance next, read by observer + atomic_uintptr_t mNext; // written by mutator to advance next, read by observer volatile const T* mAck; // written by observer to acknowledge advance of next, read by mutator // only used by observer diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index bf85b51..23a2174 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -135,12 +135,12 @@ static const int kPriorityFastMixer = 3; // IAudioFlinger::createTrack() reports back to client the total size of shared memory area // for the track. The client then sub-divides this into smaller buffers for its use. -// Currently the client uses double-buffering by default, but doesn't tell us about that. -// So for now we just assume that client is double-buffered. -// FIXME It would be better for client to tell AudioFlinger whether it wants double-buffering or -// N-buffering, so AudioFlinger could allocate the right amount of memory. +// Currently the client uses N-buffering by default, but doesn't tell us about the value of N. +// So for now we just assume that client is double-buffered for fast tracks. +// FIXME It would be better for client to tell AudioFlinger the value of N, +// so AudioFlinger could allocate the right amount of memory. // See the client's minBufCount and mNotificationFramesAct calculations for details. -static const int kFastTrackMultiplier = 1; +static const int kFastTrackMultiplier = 2; // ---------------------------------------------------------------------------- @@ -425,7 +425,7 @@ void AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args) result.append(buffer); snprintf(buffer, SIZE, "Sample rate: %u\n", mSampleRate); result.append(buffer); - snprintf(buffer, SIZE, "HAL frame count: %d\n", mFrameCount); + snprintf(buffer, SIZE, "HAL frame count: %zu\n", mFrameCount); result.append(buffer); snprintf(buffer, SIZE, "Channel Count: %u\n", mChannelCount); result.append(buffer); @@ -433,14 +433,14 @@ void AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args) result.append(buffer); snprintf(buffer, SIZE, "Format: %d\n", mFormat); result.append(buffer); - snprintf(buffer, SIZE, "Frame size: %u\n", mFrameSize); + snprintf(buffer, SIZE, "Frame size: %zu\n", mFrameSize); result.append(buffer); snprintf(buffer, SIZE, "\nPending setParameters commands: \n"); result.append(buffer); result.append(" Index Command"); for (size_t i = 0; i < mNewParameters.size(); ++i) { - snprintf(buffer, SIZE, "\n %02d ", i); + snprintf(buffer, SIZE, "\n %02zu ", i); result.append(buffer); result.append(mNewParameters[i]); } @@ -466,7 +466,7 @@ void AudioFlinger::ThreadBase::dumpEffectChains(int fd, const Vector<String16>& char buffer[SIZE]; String8 result; - snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size()); + snprintf(buffer, SIZE, "\n- %zu Effect Chains:\n", mEffectChains.size()); write(fd, buffer, strlen(buffer)); for (size_t i = 0; i < mEffectChains.size(); ++i) { @@ -1116,7 +1116,7 @@ void AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& ar // These values are "raw"; they will wrap around. See prepareTracks_l() for a better way. FastTrackUnderruns underruns = getFastTrackUnderruns(0); - fdprintf(fd, "Normal mixer raw underrun counters: partial=%u empty=%u\n", + dprintf(fd, "Normal mixer raw underrun counters: partial=%u empty=%u\n", underruns.mBitFields.mPartial, underruns.mBitFields.mEmpty); } @@ -1128,7 +1128,7 @@ void AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& snprintf(buffer, SIZE, "\nOutput thread %p internals\n", this); result.append(buffer); - snprintf(buffer, SIZE, "Normal frame count: %d\n", mNormalFrameCount); + snprintf(buffer, SIZE, "Normal frame count: %zu\n", mNormalFrameCount); result.append(buffer); snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime)); @@ -1144,7 +1144,7 @@ void AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& snprintf(buffer, SIZE, "mix buffer : %p\n", mMixBuffer); result.append(buffer); write(fd, result.string(), result.size()); - fdprintf(fd, "Fast track availMask=%#x\n", mFastTrackAvailMask); + dprintf(fd, "Fast track availMask=%#x\n", mFastTrackAvailMask); dumpBase(fd, args); } @@ -1210,7 +1210,7 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac ( (tid != -1) && ((frameCount == 0) || - (frameCount >= (mFrameCount * kFastTrackMultiplier))) + (frameCount >= mFrameCount)) ) ) && // PCM data @@ -1218,10 +1218,8 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac // mono or stereo ( (channelMask == AUDIO_CHANNEL_OUT_MONO) || (channelMask == AUDIO_CHANNEL_OUT_STEREO) ) && -#ifndef FAST_TRACKS_AT_NON_NATIVE_SAMPLE_RATE // hardware sample rate (sampleRate == mSampleRate) && -#endif // normal mixer has an associated fast mixer hasFastMixer() && // there are sufficient fast track slots available @@ -1326,8 +1324,10 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac track = TimedTrack::create(this, client, streamType, sampleRate, format, channelMask, frameCount, sharedBuffer, sessionId, uid); } + if (track == 0 || track->getCblk() == NULL || track->name() < 0) { lStatus = NO_MEMORY; + // track must be cleared from the caller as the caller has the AF lock goto Exit; } @@ -1718,7 +1718,7 @@ void AudioFlinger::PlaybackThread::readOutputParameters() } -status_t AudioFlinger::PlaybackThread::getRenderPosition(size_t *halFrames, size_t *dspFrames) +status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames) { if (halFrames == NULL || dspFrames == NULL) { return BAD_VALUE; @@ -1736,7 +1736,11 @@ status_t AudioFlinger::PlaybackThread::getRenderPosition(size_t *halFrames, size *dspFrames = framesWritten >= latencyFrames ? framesWritten - latencyFrames : 0; return NO_ERROR; } else { - return mOutput->stream->get_render_position(mOutput->stream, dspFrames); + status_t status; + uint32_t frames; + status = mOutput->stream->get_render_position(mOutput->stream, &frames); + *dspFrames = (size_t)frames; + return status; } } @@ -1913,7 +1917,7 @@ ssize_t AudioFlinger::PlaybackThread::threadLoop_write() // otherwise use the HAL / AudioStreamOut directly } else { // Direct output and offload threads - size_t offset = (mCurrentWriteLength - mBytesRemaining) / sizeof(int16_t); + size_t offset = (mCurrentWriteLength - mBytesRemaining); if (mUseAsyncWrite) { ALOGW_IF(mWriteAckSequence & 1, "threadLoop_write(): out of sequence write request"); mWriteAckSequence += 2; @@ -1924,7 +1928,7 @@ ssize_t AudioFlinger::PlaybackThread::threadLoop_write() // FIXME We should have an implementation of timestamps for direct output threads. // They are used e.g for multichannel PCM playback over HDMI. bytesWritten = mOutput->stream->write(mOutput->stream, - mMixBuffer + offset, mBytesRemaining); + (char *)mMixBuffer + offset, mBytesRemaining); if (mUseAsyncWrite && ((bytesWritten < 0) || (bytesWritten == (ssize_t)mBytesRemaining))) { // do not wait for async callback in case of error of full write @@ -2600,7 +2604,7 @@ AudioFlinger::MixerThread::~MixerThread() if (state->mCommand == FastMixerState::COLD_IDLE) { int32_t old = android_atomic_inc(&mFastMixerFutex); if (old == -1) { - __futex_syscall3(&mFastMixerFutex, FUTEX_WAKE_PRIVATE, 1); + (void) syscall(__NR_futex, &mFastMixerFutex, FUTEX_WAKE_PRIVATE, 1); } } state->mCommand = FastMixerState::EXIT; @@ -2657,7 +2661,7 @@ ssize_t AudioFlinger::MixerThread::threadLoop_write() if (state->mCommand == FastMixerState::COLD_IDLE) { int32_t old = android_atomic_inc(&mFastMixerFutex); if (old == -1) { - __futex_syscall3(&mFastMixerFutex, FUTEX_WAKE_PRIVATE, 1); + (void) syscall(__NR_futex, &mFastMixerFutex, FUTEX_WAKE_PRIVATE, 1); } #ifdef AUDIO_WATCHDOG if (mAudioWatchdog != 0) { @@ -2973,7 +2977,6 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac VolumeProvider *vp = track; fastTrack->mBufferProvider = eabp; fastTrack->mVolumeProvider = vp; - fastTrack->mSampleRate = track->mSampleRate; fastTrack->mChannelMask = track->mChannelMask; fastTrack->mGeneration++; state->mTrackMask |= 1 << j; @@ -3036,15 +3039,8 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac (mMixerStatusIgnoringFastTracks == MIXER_TRACKS_READY)) { minFrames = desiredFrames; } - // It's not safe to call framesReady() for a static buffer track, so assume it's ready - size_t framesReady; - if (track->sharedBuffer() == 0) { - framesReady = track->framesReady(); - } else if (track->isStopped()) { - framesReady = 0; - } else { - framesReady = 1; - } + + size_t framesReady = track->framesReady(); if ((framesReady >= minFrames) && track->isReady() && !track->isPaused() && !track->isTerminated()) { @@ -3157,9 +3153,9 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac mAudioMixer->setBufferProvider(name, track); mAudioMixer->enable(name); - mAudioMixer->setParameter(name, param, AudioMixer::VOLUME0, (void *)vl); - mAudioMixer->setParameter(name, param, AudioMixer::VOLUME1, (void *)vr); - mAudioMixer->setParameter(name, param, AudioMixer::AUXLEVEL, (void *)va); + mAudioMixer->setParameter(name, param, AudioMixer::VOLUME0, (void *)(uintptr_t)vl); + mAudioMixer->setParameter(name, param, AudioMixer::VOLUME1, (void *)(uintptr_t)vr); + mAudioMixer->setParameter(name, param, AudioMixer::AUXLEVEL, (void *)(uintptr_t)va); mAudioMixer->setParameter( name, AudioMixer::TRACK, @@ -3167,7 +3163,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac mAudioMixer->setParameter( name, AudioMixer::TRACK, - AudioMixer::CHANNEL_MASK, (void *)track->channelMask()); + AudioMixer::CHANNEL_MASK, (void *)(uintptr_t)track->channelMask()); // limit track sample rate to 2 x output sample rate, which changes at re-configuration uint32_t maxSampleRate = mSampleRate * 2; uint32_t reqSampleRate = track->mAudioTrackServerProxy->getSampleRate(); @@ -3180,7 +3176,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac name, AudioMixer::RESAMPLE, AudioMixer::SAMPLE_RATE, - (void *)reqSampleRate); + (void *)(uintptr_t)reqSampleRate); mAudioMixer->setParameter( name, AudioMixer::TRACK, @@ -3861,7 +3857,12 @@ bool AudioFlinger::AsyncCallbackThread::threadLoop() { Mutex::Autolock _l(mLock); - mWaitWorkCV.wait(mLock); + while (!((mWriteAckSequence & 1) || + (mDrainSequence & 1) || + exitPending())) { + mWaitWorkCV.wait(mLock); + } + if (exitPending()) { break; } @@ -3951,7 +3952,10 @@ void AudioFlinger::OffloadThread::threadLoop_exit() mMixerStatus = MIXER_DRAIN_ALL; threadLoop_drain(); } - mCallbackThread->exit(); + if (mUseAsyncWrite) { + ALOG_ASSERT(mCallbackThread != 0); + mCallbackThread->exit(); + } PlaybackThread::threadLoop_exit(); } @@ -4687,7 +4691,7 @@ sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createR ( (tid != -1) && ((frameCount == 0) || - (frameCount >= (mFrameCount * kFastTrackMultiplier))) + (frameCount >= mFrameCount)) ) && // FIXME when record supports non-PCM data, also check for audio_is_linear_pcm(format) // mono or stereo @@ -4742,7 +4746,7 @@ sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createR if (track->getCblk() == 0) { ALOGE("createRecordTrack_l() no control block"); lStatus = NO_MEMORY; - track.clear(); + // track must be cleared from the caller as the caller has the AF lock goto Exit; } mTracks.add(track); @@ -4959,9 +4963,9 @@ void AudioFlinger::RecordThread::dumpInternals(int fd, const Vector<String16>& a result.append(buffer); if (mActiveTrack != 0) { - snprintf(buffer, SIZE, "In index: %d\n", mRsmpInIndex); + snprintf(buffer, SIZE, "In index: %zu\n", mRsmpInIndex); result.append(buffer); - snprintf(buffer, SIZE, "Buffer size: %u bytes\n", mBufferSize); + snprintf(buffer, SIZE, "Buffer size: %zu bytes\n", mBufferSize); result.append(buffer); snprintf(buffer, SIZE, "Resampling: %d\n", (mResampler != NULL)); result.append(buffer); diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h index 207f1eb..a2fb874 100644 --- a/services/audioflinger/Threads.h +++ b/services/audioflinger/Threads.h @@ -446,7 +446,7 @@ public: virtual String8 getParameters(const String8& keys); virtual void audioConfigChanged_l(int event, int param = 0); - status_t getRenderPosition(size_t *halFrames, size_t *dspFrames); + status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames); int16_t *mixBuffer() const { return mMixBuffer; }; virtual void detachAuxEffect_l(int effectId); diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index af04ce7..cbf56b5 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -21,6 +21,7 @@ #include "Configuration.h" #include <math.h> +#include <sys/syscall.h> #include <utils/Log.h> #include <private/media/AudioTrackShared.h> @@ -487,8 +488,8 @@ void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size) nowInUnderrun = '?'; break; } - snprintf(&buffer[7], size-7, " %6u %4u %08X %08X %7u %6u %1c %1d %5u %5.2g %5.2g " - "%08X %08X %08X 0x%03X %9u%c\n", + snprintf(&buffer[7], size-7, " %6u %4u %08X %08X %7u %6zu %1c %1d %5u %5.2g %5.2g " + "%08X %p %p 0x%03X %9u%c\n", (mClient == 0) ? getpid_cached : mClient->pid(), mStreamType, mFormat, @@ -501,8 +502,8 @@ void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size) 20.0 * log10((vlr & 0xFFFF) / 4096.0), 20.0 * log10((vlr >> 16) / 4096.0), mCblk->mServer, - (int)mMainBuffer, - (int)mAuxBuffer, + mMainBuffer, + mAuxBuffer, mCblk->mFlags, mAudioTrackServerProxy->getUnderrunFrames(), nowInUnderrun); @@ -551,7 +552,7 @@ size_t AudioFlinger::PlaybackThread::Track::framesReleased() const // Don't call for fast tracks; the framesReady() could result in priority inversion bool AudioFlinger::PlaybackThread::Track::isReady() const { - if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) { + if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing() || isStopping()) { return true; } @@ -895,7 +896,7 @@ bool AudioFlinger::PlaybackThread::Track::presentationComplete(size_t framesWrit void AudioFlinger::PlaybackThread::Track::triggerEvents(AudioSystem::sync_event_t type) { - for (int i = 0; i < (int)mSyncEvents.size(); i++) { + for (size_t i = 0; i < mSyncEvents.size(); i++) { if (mSyncEvents[i]->type() == type) { mSyncEvents[i]->trigger(); mSyncEvents.removeAt(i); @@ -952,7 +953,7 @@ void AudioFlinger::PlaybackThread::Track::invalidate() android_atomic_or(CBLK_INVALID, &cblk->mFlags); android_atomic_release_store(0x40000000, &cblk->mFutex); // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE - (void) __futex_syscall3(&cblk->mFutex, FUTEX_WAKE, INT_MAX); + (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX); mIsInvalid = true; } @@ -1839,7 +1840,7 @@ void AudioFlinger::RecordThread::RecordTrack::invalidate() android_atomic_or(CBLK_INVALID, &cblk->mFlags); android_atomic_release_store(0x40000000, &cblk->mFutex); // client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE - (void) __futex_syscall3(&cblk->mFutex, FUTEX_WAKE, INT_MAX); + (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX); } @@ -1850,7 +1851,7 @@ void AudioFlinger::RecordThread::RecordTrack::invalidate() void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size) { - snprintf(buffer, size, "%6u %3u %08X %7u %1d %08X %6u\n", + snprintf(buffer, size, "%6u %3u %08X %7u %1d %08X %6zu\n", (mClient == 0) ? getpid_cached : mClient->pid(), mFormat, mChannelMask, diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index eeedfc9..9ce7daf 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -196,7 +196,7 @@ void CameraService::onDeviceStatusChanged(int cameraId, */ } - ALOGV("%s: After unplug, disconnected %d clients", + ALOGV("%s: After unplug, disconnected %zu clients", __FUNCTION__, clientsToDisconnect.size()); } @@ -655,6 +655,11 @@ status_t CameraService::addListener( const sp<ICameraServiceListener>& listener) { ALOGV("%s: Add listener %p", __FUNCTION__, listener.get()); + if (listener == 0) { + ALOGE("%s: Listener must not be null", __FUNCTION__); + return BAD_VALUE; + } + Mutex::Autolock lock(mServiceLock); Vector<sp<ICameraServiceListener> >::iterator it, end; @@ -683,6 +688,11 @@ status_t CameraService::removeListener( const sp<ICameraServiceListener>& listener) { ALOGV("%s: Remove listener %p", __FUNCTION__, listener.get()); + if (listener == 0) { + ALOGE("%s: Listener must not be null", __FUNCTION__); + return BAD_VALUE; + } + Mutex::Autolock lock(mServiceLock); Vector<sp<ICameraServiceListener> >::iterator it; @@ -1042,13 +1052,13 @@ void CameraService::BasicClient::opChanged(int32_t op, const String16& packageNa // ---------------------------------------------------------------------------- Mutex* CameraService::Client::getClientLockFromCookie(void* user) { - return gCameraService->getClientLockById((int) user); + return gCameraService->getClientLockById((int)(intptr_t) user); } // Provide client pointer for callbacks. Client lock returned from getClientLockFromCookie should // be acquired for this to be safe CameraService::Client* CameraService::Client::getClientFromCookie(void* user) { - BasicClient *basicClient = gCameraService->getClientByIdUnsafe((int) user); + BasicClient *basicClient = gCameraService->getClientByIdUnsafe((int)(intptr_t) user); // OK: only CameraClient calls this, and they already cast anyway. Client* client = static_cast<Client*>(basicClient); @@ -1159,6 +1169,7 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) { if (!mModule) { result = String8::format("No camera module available!\n"); write(fd, result.string(), result.size()); + if (locked) mServiceLock.unlock(); return NO_ERROR; } diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp index 0b6ca5c..af23557 100644 --- a/services/camera/libcameraservice/api1/Camera2Client.cpp +++ b/services/camera/libcameraservice/api1/Camera2Client.cpp @@ -18,6 +18,7 @@ #define ATRACE_TAG ATRACE_TAG_CAMERA //#define LOG_NDEBUG 0 +#include <inttypes.h> #include <utils/Log.h> #include <utils/Trace.h> @@ -193,7 +194,7 @@ status_t Camera2Client::dump(int fd, const Vector<String16>& args) { result.appendFormat(" GPS lat x long x alt: %f x %f x %f\n", p.gpsCoordinates[0], p.gpsCoordinates[1], p.gpsCoordinates[2]); - result.appendFormat(" GPS timestamp: %lld\n", + result.appendFormat(" GPS timestamp: %" PRId64 "\n", p.gpsTimestamp); result.appendFormat(" GPS processing method: %s\n", p.gpsProcessingMethod.string()); @@ -406,12 +407,6 @@ void Camera2Client::disconnect() { l.mParameters.state = Parameters::DISCONNECTED; } - mStreamingProcessor->deletePreviewStream(); - mStreamingProcessor->deleteRecordingStream(); - mJpegProcessor->deleteStream(); - mCallbackProcessor->deleteStream(); - mZslProcessor->deleteStream(); - mStreamingProcessor->requestExit(); mFrameProcessor->requestExit(); mCaptureSequencer->requestExit(); @@ -428,6 +423,14 @@ void Camera2Client::disconnect() { mZslProcessorThread->join(); mCallbackProcessor->join(); + ALOGV("Camera %d: Deleting streams", mCameraId); + + mStreamingProcessor->deletePreviewStream(); + mStreamingProcessor->deleteRecordingStream(); + mJpegProcessor->deleteStream(); + mCallbackProcessor->deleteStream(); + mZslProcessor->deleteStream(); + ALOGV("Camera %d: Disconnecting device", mCameraId); mDevice->disconnect(); @@ -731,6 +734,7 @@ status_t Camera2Client::startPreviewL(Parameters ¶ms, bool restart) { return OK; } params.state = Parameters::STOPPED; + int lastPreviewStreamId = mStreamingProcessor->getPreviewStreamId(); res = mStreamingProcessor->updatePreviewStream(params); if (res != OK) { @@ -739,6 +743,8 @@ status_t Camera2Client::startPreviewL(Parameters ¶ms, bool restart) { return res; } + bool previewStreamChanged = mStreamingProcessor->getPreviewStreamId() != lastPreviewStreamId; + // We could wait to create the JPEG output stream until first actual use // (first takePicture call). However, this would substantially increase the // first capture latency on HAL3 devices, and potentially on some HAL2 @@ -788,6 +794,19 @@ status_t Camera2Client::startPreviewL(Parameters ¶ms, bool restart) { return res; } outputStreams.push(getCallbackStreamId()); + } else if (previewStreamChanged && mCallbackProcessor->getStreamId() != NO_STREAM) { + /** + * Delete the unused callback stream when preview stream is changed and + * preview is not enabled. Don't need stop preview stream as preview is in + * STOPPED state now. + */ + ALOGV("%s: Camera %d: Delete unused preview callback stream.", __FUNCTION__, mCameraId); + res = mCallbackProcessor->deleteStream(); + if (res != OK) { + ALOGE("%s: Camera %d: Unable to delete callback stream %s (%d)", + __FUNCTION__, mCameraId, strerror(-res), res); + return res; + } } if (params.zslMode && !params.recordingHint) { res = updateProcessorStream(mZslProcessor, params); diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp index bd6805d..30b7bb8 100644 --- a/services/camera/libcameraservice/api1/CameraClient.cpp +++ b/services/camera/libcameraservice/api1/CameraClient.cpp @@ -85,7 +85,7 @@ status_t CameraClient::initialize(camera_module_t *module) { mHardware->setCallbacks(notifyCallback, dataCallback, dataCallbackTimestamp, - (void *)mCameraId); + (void *)(uintptr_t)mCameraId); // Enable zoom, error, focus, and metadata messages by default enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS | diff --git a/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp b/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp index 8a4ce4e..f5c28ed 100644 --- a/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp +++ b/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp @@ -18,6 +18,8 @@ #define ATRACE_TAG ATRACE_TAG_CAMERA //#define LOG_NDEBUG 0 +#include <inttypes.h> + #include <utils/Log.h> #include <utils/Trace.h> #include <utils/Vector.h> @@ -585,8 +587,8 @@ CaptureSequencer::CaptureState CaptureSequencer::manageStandardCaptureWait( ALOGE("No timestamp field in capture frame!"); } if (entry.data.i64[0] != mCaptureTimestamp) { - ALOGW("Mismatched capture timestamps: Metadata frame %lld," - " captured buffer %lld", + ALOGW("Mismatched capture timestamps: Metadata frame %" PRId64 "," + " captured buffer %" PRId64, entry.data.i64[0], mCaptureTimestamp); } diff --git a/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp b/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp index 19acae4..dd5b27c 100644 --- a/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp +++ b/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp @@ -168,7 +168,7 @@ status_t FrameProcessor::processFaceDetect(const CameraMetadata &frame, continue; } if (faceScores[i] > 100) { - ALOGW("%s: Face index %d with out of range score %d", + ALOGW("%s: Face index %zu with out of range score %d", __FUNCTION__, i, faceScores[i]); } diff --git a/services/camera/libcameraservice/api1/client2/JpegCompressor.cpp b/services/camera/libcameraservice/api1/client2/JpegCompressor.cpp index 2f0c67d..9ecab71 100644 --- a/services/camera/libcameraservice/api1/client2/JpegCompressor.cpp +++ b/services/camera/libcameraservice/api1/client2/JpegCompressor.cpp @@ -197,7 +197,7 @@ void JpegCompressor::jpegErrorHandler(j_common_ptr cinfo) { void JpegCompressor::jpegInitDestination(j_compress_ptr cinfo) { ALOGV("%s", __FUNCTION__); JpegDestination *dest= static_cast<JpegDestination*>(cinfo->dest); - ALOGV("%s: Setting destination to %p, size %d", + ALOGV("%s: Setting destination to %p, size %zu", __FUNCTION__, dest->parent->mJpegBuffer->data, kMaxJpegSize); dest->next_output_byte = (JOCTET*)(dest->parent->mJpegBuffer->data); dest->free_in_buffer = kMaxJpegSize; @@ -213,7 +213,7 @@ boolean JpegCompressor::jpegEmptyOutputBuffer(j_compress_ptr /*cinfo*/) { void JpegCompressor::jpegTermDestination(j_compress_ptr cinfo) { (void) cinfo; // TODO: clean up ALOGV("%s", __FUNCTION__); - ALOGV("%s: Done writing JPEG data. %d bytes left in buffer", + ALOGV("%s: Done writing JPEG data. %zu bytes left in buffer", __FUNCTION__, cinfo->dest->free_in_buffer); } diff --git a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp index 77d5c8a..2de7a2b 100644 --- a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp +++ b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp @@ -200,50 +200,59 @@ status_t JpegProcessor::processNewCapture() { ATRACE_CALL(); status_t res; sp<Camera2Heap> captureHeap; + sp<MemoryBase> captureBuffer; CpuConsumer::LockedBuffer imgBuffer; - res = mCaptureConsumer->lockNextBuffer(&imgBuffer); - if (res != OK) { - if (res != BAD_VALUE) { - ALOGE("%s: Camera %d: Error receiving still image buffer: " - "%s (%d)", __FUNCTION__, - mId, strerror(-res), res); + { + Mutex::Autolock l(mInputMutex); + if (mCaptureStreamId == NO_STREAM) { + ALOGW("%s: Camera %d: No stream is available", __FUNCTION__, mId); + return INVALID_OPERATION; } - return res; - } - ALOGV("%s: Camera %d: Still capture available", __FUNCTION__, - mId); + res = mCaptureConsumer->lockNextBuffer(&imgBuffer); + if (res != OK) { + if (res != BAD_VALUE) { + ALOGE("%s: Camera %d: Error receiving still image buffer: " + "%s (%d)", __FUNCTION__, + mId, strerror(-res), res); + } + return res; + } - if (imgBuffer.format != HAL_PIXEL_FORMAT_BLOB) { - ALOGE("%s: Camera %d: Unexpected format for still image: " - "%x, expected %x", __FUNCTION__, mId, - imgBuffer.format, - HAL_PIXEL_FORMAT_BLOB); - mCaptureConsumer->unlockBuffer(imgBuffer); - return OK; - } + ALOGV("%s: Camera %d: Still capture available", __FUNCTION__, + mId); - // Find size of JPEG image - size_t jpegSize = findJpegSize(imgBuffer.data, imgBuffer.width); - if (jpegSize == 0) { // failed to find size, default to whole buffer - jpegSize = imgBuffer.width; - } - size_t heapSize = mCaptureHeap->getSize(); - if (jpegSize > heapSize) { - ALOGW("%s: JPEG image is larger than expected, truncating " - "(got %d, expected at most %d bytes)", - __FUNCTION__, jpegSize, heapSize); - jpegSize = heapSize; - } + if (imgBuffer.format != HAL_PIXEL_FORMAT_BLOB) { + ALOGE("%s: Camera %d: Unexpected format for still image: " + "%x, expected %x", __FUNCTION__, mId, + imgBuffer.format, + HAL_PIXEL_FORMAT_BLOB); + mCaptureConsumer->unlockBuffer(imgBuffer); + return OK; + } - // TODO: Optimize this to avoid memcopy - sp<MemoryBase> captureBuffer = new MemoryBase(mCaptureHeap, 0, jpegSize); - void* captureMemory = mCaptureHeap->getBase(); - memcpy(captureMemory, imgBuffer.data, jpegSize); + // Find size of JPEG image + size_t jpegSize = findJpegSize(imgBuffer.data, imgBuffer.width); + if (jpegSize == 0) { // failed to find size, default to whole buffer + jpegSize = imgBuffer.width; + } + size_t heapSize = mCaptureHeap->getSize(); + if (jpegSize > heapSize) { + ALOGW("%s: JPEG image is larger than expected, truncating " + "(got %zu, expected at most %zu bytes)", + __FUNCTION__, jpegSize, heapSize); + jpegSize = heapSize; + } + + // TODO: Optimize this to avoid memcopy + captureBuffer = new MemoryBase(mCaptureHeap, 0, jpegSize); + void* captureMemory = mCaptureHeap->getBase(); + memcpy(captureMemory, imgBuffer.data, jpegSize); - mCaptureConsumer->unlockBuffer(imgBuffer); + mCaptureConsumer->unlockBuffer(imgBuffer); + } sp<CaptureSequencer> sequencer = mSequencer.promote(); if (sequencer != 0) { @@ -326,13 +335,13 @@ size_t JpegProcessor::findJpegSize(uint8_t* jpegBuffer, size_t maxSize) { size_t offset = size - MARKER_LENGTH; uint8_t *end = jpegBuffer + offset; if (checkJpegStart(jpegBuffer) && checkJpegEnd(end)) { - ALOGV("Found JPEG transport header, img size %d", size); + ALOGV("Found JPEG transport header, img size %zu", size); return size; } else { ALOGW("Found JPEG transport header with bad Image Start/End"); } } else { - ALOGW("Found JPEG transport header with bad size %d", size); + ALOGW("Found JPEG transport header with bad size %zu", size); } } @@ -348,15 +357,15 @@ size_t JpegProcessor::findJpegSize(uint8_t* jpegBuffer, size_t maxSize) { segment_t *segment = (segment_t*)(jpegBuffer + size); uint8_t type = checkJpegMarker(segment->marker); if (type == 0) { // invalid marker, no more segments, begin JPEG data - ALOGV("JPEG stream found beginning at offset %d", size); + ALOGV("JPEG stream found beginning at offset %zu", size); break; } if (type == EOI || size > maxSize - sizeof(segment_t)) { - ALOGE("Got premature End before JPEG data, offset %d", size); + ALOGE("Got premature End before JPEG data, offset %zu", size); return 0; } size_t length = ntohs(segment->length); - ALOGV("JFIF Segment, type %x length %x", type, length); + ALOGV("JFIF Segment, type %x length %zx", type, length); size += length + MARKER_LENGTH; } @@ -376,10 +385,10 @@ size_t JpegProcessor::findJpegSize(uint8_t* jpegBuffer, size_t maxSize) { } if (size > maxSize) { - ALOGW("JPEG size %d too large, reducing to maxSize %d", size, maxSize); + ALOGW("JPEG size %zu too large, reducing to maxSize %zu", size, maxSize); size = maxSize; } - ALOGV("Final JPEG size %d", size); + ALOGV("Final JPEG size %zu", size); return size; } diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp index 08af566..081a6e6 100644 --- a/services/camera/libcameraservice/api1/client2/Parameters.cpp +++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp @@ -16,7 +16,7 @@ #define LOG_TAG "Camera2-Parameters" #define ATRACE_TAG ATRACE_TAG_CAMERA -//#define LOG_NDEBUG 0 +// #define LOG_NDEBUG 0 #include <utils/Log.h> #include <utils/Trace.h> @@ -92,26 +92,6 @@ status_t Parameters::initialize(const CameraMetadata *info) { staticInfo(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, 2); if (!availableFpsRanges.count) return NO_INIT; - previewFpsRange[0] = availableFpsRanges.data.i32[0]; - previewFpsRange[1] = availableFpsRanges.data.i32[1]; - - params.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, - String8::format("%d,%d", - previewFpsRange[0] * kFpsToApiScale, - previewFpsRange[1] * kFpsToApiScale)); - - { - String8 supportedPreviewFpsRange; - for (size_t i=0; i < availableFpsRanges.count; i += 2) { - if (i != 0) supportedPreviewFpsRange += ","; - supportedPreviewFpsRange += String8::format("(%d,%d)", - availableFpsRanges.data.i32[i] * kFpsToApiScale, - availableFpsRanges.data.i32[i+1] * kFpsToApiScale); - } - params.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, - supportedPreviewFpsRange); - } - previewFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; params.set(CameraParameters::KEY_PREVIEW_FORMAT, formatEnumToString(previewFormat)); // NV21 @@ -179,6 +159,9 @@ status_t Parameters::initialize(const CameraMetadata *info) { supportedPreviewFormats); } + previewFpsRange[0] = availableFpsRanges.data.i32[0]; + previewFpsRange[1] = availableFpsRanges.data.i32[1]; + // PREVIEW_FRAME_RATE / SUPPORTED_PREVIEW_FRAME_RATES are deprecated, but // still have to do something sane for them @@ -187,6 +170,27 @@ status_t Parameters::initialize(const CameraMetadata *info) { params.set(CameraParameters::KEY_PREVIEW_FRAME_RATE, previewFps); + // PREVIEW_FPS_RANGE + // -- Order matters. Set range after single value to so that a roundtrip + // of setParameters(getParameters()) would keep the FPS range in higher + // order. + params.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, + String8::format("%d,%d", + previewFpsRange[0] * kFpsToApiScale, + previewFpsRange[1] * kFpsToApiScale)); + + { + String8 supportedPreviewFpsRange; + for (size_t i=0; i < availableFpsRanges.count; i += 2) { + if (i != 0) supportedPreviewFpsRange += ","; + supportedPreviewFpsRange += String8::format("(%d,%d)", + availableFpsRanges.data.i32[i] * kFpsToApiScale, + availableFpsRanges.data.i32[i+1] * kFpsToApiScale); + } + params.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, + supportedPreviewFpsRange); + } + { SortedVector<int32_t> sortedPreviewFrameRates; @@ -944,7 +948,7 @@ status_t Parameters::buildFastInfo() { if (sceneModeOverrides.count != availableSceneModes.count * kModesPerSceneMode) { ALOGE("%s: Camera %d: Scene mode override list is an " - "unexpected size: %d (expected %d)", __FUNCTION__, + "unexpected size: %zu (expected %zu)", __FUNCTION__, cameraId, sceneModeOverrides.count, availableSceneModes.count); return NO_INIT; @@ -1074,7 +1078,7 @@ camera_metadata_ro_entry_t Parameters::staticInfo(uint32_t tag, const char* tagName = get_camera_metadata_tag_name(tag); if (tagName == NULL) tagName = "<unknown>"; ALOGE("Malformed static metadata entry '%s.%s' (%x):" - "Expected between %d and %d values, but got %d values", + "Expected between %zu and %zu values, but got %zu values", tagSection, tagName, tag, minCount, maxCount, entry.count); } @@ -1084,7 +1088,7 @@ camera_metadata_ro_entry_t Parameters::staticInfo(uint32_t tag, status_t Parameters::set(const String8& paramString) { status_t res; - CameraParameters newParams(paramString); + CameraParameters2 newParams(paramString); // TODO: Currently ignoring any changes to supposedly read-only parameters // such as supported preview sizes, etc. Should probably produce an error if @@ -1127,29 +1131,73 @@ status_t Parameters::set(const String8& paramString) { // RECORDING_HINT (always supported) validatedParams.recordingHint = boolFromString( newParams.get(CameraParameters::KEY_RECORDING_HINT) ); - bool recordingHintChanged = validatedParams.recordingHint != recordingHint; - ALOGV_IF(recordingHintChanged, "%s: Recording hint changed to %d", - __FUNCTION__, recordingHintChanged); + IF_ALOGV() { // Avoid unused variable warning + bool recordingHintChanged = + validatedParams.recordingHint != recordingHint; + if (recordingHintChanged) { + ALOGV("%s: Recording hint changed to %d", + __FUNCTION__, validatedParams.recordingHint); + } + } // PREVIEW_FPS_RANGE - bool fpsRangeChanged = false; - int32_t lastSetFpsRange[2]; - params.getPreviewFpsRange(&lastSetFpsRange[0], &lastSetFpsRange[1]); - lastSetFpsRange[0] /= kFpsToApiScale; - lastSetFpsRange[1] /= kFpsToApiScale; + /** + * Use the single FPS value if it was set later than the range. + * Otherwise, use the range value. + */ + bool fpsUseSingleValue; + { + const char *fpsRange, *fpsSingle; + + fpsRange = newParams.get(CameraParameters::KEY_PREVIEW_FRAME_RATE); + fpsSingle = newParams.get(CameraParameters::KEY_PREVIEW_FPS_RANGE); + /** + * Pick either the range or the single key if only one was set. + * + * If both are set, pick the one that has greater set order. + */ + if (fpsRange == NULL && fpsSingle == NULL) { + ALOGE("%s: FPS was not set. One of %s or %s must be set.", + __FUNCTION__, CameraParameters::KEY_PREVIEW_FRAME_RATE, + CameraParameters::KEY_PREVIEW_FPS_RANGE); + return BAD_VALUE; + } else if (fpsRange == NULL) { + fpsUseSingleValue = true; + ALOGV("%s: FPS range not set, using FPS single value", + __FUNCTION__); + } else if (fpsSingle == NULL) { + fpsUseSingleValue = false; + ALOGV("%s: FPS single not set, using FPS range value", + __FUNCTION__); + } else { + int fpsKeyOrder; + res = newParams.compareSetOrder( + CameraParameters::KEY_PREVIEW_FRAME_RATE, + CameraParameters::KEY_PREVIEW_FPS_RANGE, + &fpsKeyOrder); + LOG_ALWAYS_FATAL_IF(res != OK, "Impossibly bad FPS keys"); + + fpsUseSingleValue = (fpsKeyOrder > 0); + + } + + ALOGV("%s: Preview FPS value is used from '%s'", + __FUNCTION__, fpsUseSingleValue ? "single" : "range"); + } newParams.getPreviewFpsRange(&validatedParams.previewFpsRange[0], &validatedParams.previewFpsRange[1]); + validatedParams.previewFpsRange[0] /= kFpsToApiScale; validatedParams.previewFpsRange[1] /= kFpsToApiScale; - // Compare the FPS range value from the last set() to the current set() - // to determine if the client has changed it - if (validatedParams.previewFpsRange[0] != lastSetFpsRange[0] || - validatedParams.previewFpsRange[1] != lastSetFpsRange[1]) { + // Ignore the FPS range if the FPS single has higher precedence + if (!fpsUseSingleValue) { + ALOGV("%s: Preview FPS range (%d, %d)", __FUNCTION__, + validatedParams.previewFpsRange[0], + validatedParams.previewFpsRange[1]); - fpsRangeChanged = true; camera_metadata_ro_entry_t availablePreviewFpsRanges = staticInfo(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, 2); for (i = 0; i < availablePreviewFpsRanges.count; i += 2) { @@ -1200,14 +1248,13 @@ status_t Parameters::set(const String8& paramString) { } } - // PREVIEW_FRAME_RATE Deprecated, only use if the preview fps range is - // unchanged this time. The single-value FPS is the same as the minimum of - // the range. To detect whether the application has changed the value of - // previewFps, compare against their last-set preview FPS. - if (!fpsRangeChanged) { + // PREVIEW_FRAME_RATE Deprecated + // - Use only if the single FPS value was set later than the FPS range + if (fpsUseSingleValue) { int previewFps = newParams.getPreviewFrameRate(); - int lastSetPreviewFps = params.getPreviewFrameRate(); - if (previewFps != lastSetPreviewFps || recordingHintChanged) { + ALOGV("%s: Preview FPS single value requested: %d", + __FUNCTION__, previewFps); + { camera_metadata_ro_entry_t availableFrameRates = staticInfo(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES); /** @@ -1276,6 +1323,35 @@ status_t Parameters::set(const String8& paramString) { } } + /** + * Update Preview FPS and Preview FPS ranges based on + * what we actually set. + * + * This updates the API-visible (Camera.Parameters#getParameters) values of + * the FPS fields, not only the internal versions. + * + * Order matters: The value that was set last takes precedence. + * - If the client does a setParameters(getParameters()) we retain + * the same order for preview FPS. + */ + if (!fpsUseSingleValue) { + // Set fps single, then fps range (range wins) + newParams.setPreviewFrameRate( + fpsFromRange(/*min*/validatedParams.previewFpsRange[0], + /*max*/validatedParams.previewFpsRange[1])); + newParams.setPreviewFpsRange( + validatedParams.previewFpsRange[0] * kFpsToApiScale, + validatedParams.previewFpsRange[1] * kFpsToApiScale); + } else { + // Set fps range, then fps single (single wins) + newParams.setPreviewFpsRange( + validatedParams.previewFpsRange[0] * kFpsToApiScale, + validatedParams.previewFpsRange[1] * kFpsToApiScale); + // Set this to the same value, but with higher priority + newParams.setPreviewFrameRate( + newParams.getPreviewFrameRate()); + } + // PICTURE_SIZE newParams.getPictureSize(&validatedParams.pictureWidth, &validatedParams.pictureHeight); @@ -1750,6 +1826,9 @@ status_t Parameters::updateRequest(CameraMetadata *request) const { camera_metadata_entry_t intent = request->find(ANDROID_CONTROL_CAPTURE_INTENT); + + if (intent.count == 0) return BAD_VALUE; + if (intent.data.u8[0] == ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE) { res = request->update(ANDROID_CONTROL_AE_TARGET_FPS_RANGE, fastInfo.bestStillCaptureFpsRange, 2); @@ -1858,23 +1937,23 @@ status_t Parameters::updateRequest(CameraMetadata *request) const { size_t reqFocusingAreasSize = focusingAreas.size() * 5; int32_t *reqFocusingAreas = new int32_t[reqFocusingAreasSize]; - for (size_t i = 0; i < reqFocusingAreasSize; i += 5) { - if (focusingAreas[i].weight != 0) { + for (size_t i = 0, j = 0; i < reqFocusingAreasSize; i += 5, j++) { + if (focusingAreas[j].weight != 0) { reqFocusingAreas[i + 0] = - normalizedXToArray(focusingAreas[i].left); + normalizedXToArray(focusingAreas[j].left); reqFocusingAreas[i + 1] = - normalizedYToArray(focusingAreas[i].top); + normalizedYToArray(focusingAreas[j].top); reqFocusingAreas[i + 2] = - normalizedXToArray(focusingAreas[i].right); + normalizedXToArray(focusingAreas[j].right); reqFocusingAreas[i + 3] = - normalizedYToArray(focusingAreas[i].bottom); + normalizedYToArray(focusingAreas[j].bottom); } else { reqFocusingAreas[i + 0] = 0; reqFocusingAreas[i + 1] = 0; reqFocusingAreas[i + 2] = 0; reqFocusingAreas[i + 3] = 0; } - reqFocusingAreas[i + 4] = focusingAreas[i].weight; + reqFocusingAreas[i + 4] = focusingAreas[j].weight; } res = request->update(ANDROID_CONTROL_AF_REGIONS, reqFocusingAreas, reqFocusingAreasSize); @@ -1887,23 +1966,23 @@ status_t Parameters::updateRequest(CameraMetadata *request) const { size_t reqMeteringAreasSize = meteringAreas.size() * 5; int32_t *reqMeteringAreas = new int32_t[reqMeteringAreasSize]; - for (size_t i = 0; i < reqMeteringAreasSize; i += 5) { - if (meteringAreas[i].weight != 0) { + for (size_t i = 0, j = 0; i < reqMeteringAreasSize; i += 5, j++) { + if (meteringAreas[j].weight != 0) { reqMeteringAreas[i + 0] = - normalizedXToArray(meteringAreas[i].left); + normalizedXToArray(meteringAreas[j].left); reqMeteringAreas[i + 1] = - normalizedYToArray(meteringAreas[i].top); + normalizedYToArray(meteringAreas[j].top); reqMeteringAreas[i + 2] = - normalizedXToArray(meteringAreas[i].right); + normalizedXToArray(meteringAreas[j].right); reqMeteringAreas[i + 3] = - normalizedYToArray(meteringAreas[i].bottom); + normalizedYToArray(meteringAreas[j].bottom); } else { reqMeteringAreas[i + 0] = 0; reqMeteringAreas[i + 1] = 0; reqMeteringAreas[i + 2] = 0; reqMeteringAreas[i + 3] = 0; } - reqMeteringAreas[i + 4] = meteringAreas[i].weight; + reqMeteringAreas[i + 4] = meteringAreas[j].weight; } res = request->update(ANDROID_CONTROL_AE_REGIONS, reqMeteringAreas, reqMeteringAreasSize); @@ -2330,7 +2409,7 @@ status_t Parameters::validateAreas(const Vector<Parameters::Area> &areas, } if (areas.size() > maxRegions) { - ALOGE("%s: Too many areas requested: %d", + ALOGE("%s: Too many areas requested: %zu", __FUNCTION__, areas.size()); return BAD_VALUE; } diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h index 32dbd42..da07ccf 100644 --- a/services/camera/libcameraservice/api1/client2/Parameters.h +++ b/services/camera/libcameraservice/api1/client2/Parameters.h @@ -25,6 +25,7 @@ #include <utils/Vector.h> #include <utils/KeyedVector.h> #include <camera/CameraParameters.h> +#include <camera/CameraParameters2.h> #include <camera/CameraMetadata.h> namespace android { @@ -32,7 +33,7 @@ namespace camera2 { /** * Current camera state; this is the full state of the Camera under the old - * camera API (contents of the CameraParameters object in a more-efficient + * camera API (contents of the CameraParameters2 object in a more-efficient * format, plus other state). The enum values are mostly based off the * corresponding camera2 enums, not the camera1 strings. A few are defined here * if they don't cleanly map to camera2 values. @@ -128,7 +129,7 @@ struct Parameters { LIGHTFX_HDR } lightFx; - CameraParameters params; + CameraParameters2 params; String8 paramsFlattened; // These parameters are also part of the camera API-visible state, but not diff --git a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp index 6076dae..77ae7ec 100644 --- a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp +++ b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp @@ -225,14 +225,14 @@ status_t StreamingProcessor::setRecordingBufferCount(size_t count) { ATRACE_CALL(); // Make sure we can support this many buffer slots if (count > BufferQueue::NUM_BUFFER_SLOTS) { - ALOGE("%s: Camera %d: Too many recording buffers requested: %d, max %d", + ALOGE("%s: Camera %d: Too many recording buffers requested: %zu, max %d", __FUNCTION__, mId, count, BufferQueue::NUM_BUFFER_SLOTS); return BAD_VALUE; } Mutex::Autolock m(mMutex); - ALOGV("%s: Camera %d: New recording buffer count from encoder: %d", + ALOGV("%s: Camera %d: New recording buffer count from encoder: %zu", __FUNCTION__, mId, count); // Need to re-size consumer and heap @@ -314,7 +314,7 @@ status_t StreamingProcessor::updateRecordingStream(const Parameters ¶ms) { bool newConsumer = false; if (mRecordingConsumer == 0) { - ALOGV("%s: Camera %d: Creating recording consumer with %d + 1 " + ALOGV("%s: Camera %d: Creating recording consumer with %zu + 1 " "consumer-side buffers", __FUNCTION__, mId, mRecordingHeapCount); // Create CPU buffer queue endpoint. We need one more buffer here so that we can // always acquire and free a buffer when the heap is full; otherwise the consumer @@ -435,7 +435,7 @@ status_t StreamingProcessor::startStream(StreamType type, releaseAllRecordingFramesLocked(); } - ALOGV("%s: Camera %d: %s started, recording heap has %d free of %d", + ALOGV("%s: Camera %d: %s started, recording heap has %zu free of %zu", __FUNCTION__, mId, (type == PREVIEW) ? "preview" : "recording", mRecordingHeapFree, mRecordingHeapCount); @@ -658,8 +658,8 @@ status_t StreamingProcessor::processRecordingFrame() { if (mRecordingHeap == 0) { const size_t bufferSize = 4 + sizeof(buffer_handle_t); - ALOGV("%s: Camera %d: Creating recording heap with %d buffers of " - "size %d bytes", __FUNCTION__, mId, + ALOGV("%s: Camera %d: Creating recording heap with %zu buffers of " + "size %zu bytes", __FUNCTION__, mId, mRecordingHeapCount, bufferSize); mRecordingHeap = new Camera2Heap(bufferSize, mRecordingHeapCount, @@ -819,10 +819,10 @@ void StreamingProcessor::releaseAllRecordingFramesLocked() { } if (releasedCount > 0) { - ALOGW("%s: Camera %d: Force-freed %d outstanding buffers " + ALOGW("%s: Camera %d: Force-freed %zu outstanding buffers " "from previous recording session", __FUNCTION__, mId, releasedCount); ALOGE_IF(releasedCount != mRecordingHeapCount - mRecordingHeapFree, - "%s: Camera %d: Force-freed %d buffers, but expected %d", + "%s: Camera %d: Force-freed %zu buffers, but expected %zu", __FUNCTION__, mId, releasedCount, mRecordingHeapCount - mRecordingHeapFree); } diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp index 4207ba9..130f81a 100644 --- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp +++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp @@ -25,6 +25,8 @@ #define ALOGVV(...) ((void)0) #endif +#include <inttypes.h> + #include <utils/Log.h> #include <utils/Trace.h> #include <gui/Surface.h> @@ -78,7 +80,7 @@ void ZslProcessor::onFrameAvailable(int32_t /*requestId*/, entry = frame.find(ANDROID_SENSOR_TIMESTAMP); nsecs_t timestamp = entry.data.i64[0]; (void)timestamp; - ALOGVV("Got preview frame for timestamp %lld", timestamp); + ALOGVV("Got preview frame for timestamp %" PRId64, timestamp); if (mState != RUNNING) return; @@ -461,7 +463,7 @@ status_t ZslProcessor::processNewZslBuffer() { mZslQueueHead = (mZslQueueHead + 1) % kZslBufferDepth; - ALOGVV(" Acquired buffer, timestamp %lld", queueHead.buffer.mTimestamp); + ALOGVV(" Acquired buffer, timestamp %" PRId64, queueHead.buffer.mTimestamp); findMatchesLocked(); @@ -480,7 +482,7 @@ void ZslProcessor::findMatchesLocked() { entry = queueEntry.frame.find(ANDROID_SENSOR_TIMESTAMP); frameTimestamp = entry.data.i64[0]; } - ALOGVV(" %d: b: %lld\tf: %lld", i, + ALOGVV(" %d: b: %" PRId64 "\tf: %" PRId64, i, bufferTimestamp, frameTimestamp ); } if (queueEntry.frame.isEmpty() && bufferTimestamp != 0) { @@ -498,13 +500,13 @@ void ZslProcessor::findMatchesLocked() { } nsecs_t frameTimestamp = entry.data.i64[0]; if (bufferTimestamp == frameTimestamp) { - ALOGVV("%s: Found match %lld", __FUNCTION__, + ALOGVV("%s: Found match %" PRId64, __FUNCTION__, frameTimestamp); match = true; } else { int64_t delta = abs(bufferTimestamp - frameTimestamp); if ( delta < 1000000) { - ALOGVV("%s: Found close match %lld (delta %lld)", + ALOGVV("%s: Found close match %" PRId64 " (delta %" PRId64 ")", __FUNCTION__, bufferTimestamp, delta); match = true; } @@ -540,7 +542,7 @@ void ZslProcessor::dumpZslQueue(int fd) const { if (entry.count > 0) frameAeState = entry.data.u8[0]; } String8 result = - String8::format(" %d: b: %lld\tf: %lld, AE state: %d", i, + String8::format(" %zu: b: %" PRId64 "\tf: %" PRId64 ", AE state: %d", i, bufferTimestamp, frameTimestamp, frameAeState); ALOGV("%s", result.string()); if (fd != -1) { diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor3.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor3.cpp index 776ebe2..2fce2b6 100644 --- a/services/camera/libcameraservice/api1/client2/ZslProcessor3.cpp +++ b/services/camera/libcameraservice/api1/client2/ZslProcessor3.cpp @@ -25,6 +25,8 @@ #define ALOGVV(...) ((void)0) #endif +#include <inttypes.h> + #include <utils/Log.h> #include <utils/Trace.h> #include <gui/Surface.h> @@ -68,7 +70,7 @@ void ZslProcessor3::onFrameAvailable(int32_t /*requestId*/, entry = frame.find(ANDROID_SENSOR_TIMESTAMP); nsecs_t timestamp = entry.data.i64[0]; (void)timestamp; - ALOGVV("Got preview metadata for timestamp %lld", timestamp); + ALOGVV("Got preview metadata for timestamp %" PRId64, timestamp); if (mState != RUNNING) return; @@ -355,7 +357,7 @@ void ZslProcessor3::dumpZslQueue(int fd) const { if (entry.count > 0) frameAeState = entry.data.u8[0]; } String8 result = - String8::format(" %d: b: %lld\tf: %lld, AE state: %d", i, + String8::format(" %zu: b: %" PRId64 "\tf: %" PRId64 ", AE state: %d", i, bufferTimestamp, frameTimestamp, frameAeState); ALOGV("%s", result.string()); if (fd != -1) { @@ -415,7 +417,7 @@ nsecs_t ZslProcessor3::getCandidateTimestampLocked(size_t* metadataIdx) const { idx = j; } - ALOGVV("%s: Saw timestamp %lld", __FUNCTION__, frameTimestamp); + ALOGVV("%s: Saw timestamp %" PRId64, __FUNCTION__, frameTimestamp); } } @@ -435,7 +437,7 @@ nsecs_t ZslProcessor3::getCandidateTimestampLocked(size_t* metadataIdx) const { ALOGW("%s: ZSL queue has no metadata frames", __FUNCTION__); } - ALOGV("%s: Candidate timestamp %lld (idx %d), empty frames: %d", + ALOGV("%s: Candidate timestamp %" PRId64 " (idx %zu), empty frames: %zu", __FUNCTION__, minTimestamp, idx, emptyCount); if (metadataIdx) { diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp index 1cdf8dc..142da9e 100644 --- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp +++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp @@ -284,7 +284,7 @@ status_t CameraDeviceClient::createStream(int width, int height, int format, ssize_t index = mStreamMap.indexOfKey(bufferProducer->asBinder()); if (index != NAME_NOT_FOUND) { ALOGW("%s: Camera %d: Buffer producer already has a stream for it " - "(ID %d)", + "(ID %zd)", __FUNCTION__, mCameraId, index); return ALREADY_EXISTS; } diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp index 2d1253f..6a88c87 100644 --- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp +++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp @@ -18,6 +18,8 @@ #define ATRACE_TAG ATRACE_TAG_CAMERA //#define LOG_NDEBUG 0 +#include <inttypes.h> + #include <utils/Log.h> #include <utils/Trace.h> @@ -236,7 +238,7 @@ void Camera2ClientBase<TClientBase>::notifyShutter(int requestId, (void)requestId; (void)timestamp; - ALOGV("%s: Shutter notification for request id %d at time %lld", + ALOGV("%s: Shutter notification for request id %d at time %" PRId64, __FUNCTION__, requestId, timestamp); } diff --git a/services/camera/libcameraservice/common/FrameProcessorBase.cpp b/services/camera/libcameraservice/common/FrameProcessorBase.cpp index f2064fb..4d31667 100644 --- a/services/camera/libcameraservice/common/FrameProcessorBase.cpp +++ b/services/camera/libcameraservice/common/FrameProcessorBase.cpp @@ -183,7 +183,7 @@ status_t FrameProcessorBase::processListeners(const CameraMetadata &frame, item++; } } - ALOGV("Got %d range listeners out of %d", listeners.size(), mRangeListeners.size()); + ALOGV("Got %zu range listeners out of %zu", listeners.size(), mRangeListeners.size()); List<sp<FilteredListener> >::iterator item = listeners.begin(); for (; item != listeners.end(); item++) { (*item)->onFrameAvailable(requestId, frame); diff --git a/services/camera/libcameraservice/device2/Camera2Device.cpp b/services/camera/libcameraservice/device2/Camera2Device.cpp index 2bc1a8a..2966d82 100644 --- a/services/camera/libcameraservice/device2/Camera2Device.cpp +++ b/services/camera/libcameraservice/device2/Camera2Device.cpp @@ -25,6 +25,7 @@ #define ALOGVV(...) ((void)0) #endif +#include <inttypes.h> #include <utils/Log.h> #include <utils/Trace.h> #include <utils/Timers.h> @@ -822,7 +823,7 @@ status_t Camera2Device::MetadataQueue::dump(int fd, result.append(" Stream slot: Empty\n"); write(fd, result.string(), result.size()); } else { - result.appendFormat(" Stream slot: %d entries\n", + result.appendFormat(" Stream slot: %zu entries\n", mStreamSlot.size()); int i = 0; for (List<camera_metadata_t*>::iterator r = mStreamSlot.begin(); @@ -837,7 +838,7 @@ status_t Camera2Device::MetadataQueue::dump(int fd, result = " Main queue is empty\n"; write(fd, result.string(), result.size()); } else { - result = String8::format(" Main queue has %d entries:\n", + result = String8::format(" Main queue has %zu entries:\n", mEntries.size()); int i = 0; for (List<camera_metadata_t*>::iterator r = mEntries.begin(); @@ -1000,7 +1001,7 @@ status_t Camera2Device::StreamAdapter::connectToDevice( return BAD_VALUE; } - ALOGV("%s: New stream parameters %d x %d, format 0x%x, size %d", + ALOGV("%s: New stream parameters %d x %d, format 0x%x, size %zu", __FUNCTION__, width, height, format, size); mConsumerInterface = consumer; @@ -1072,7 +1073,7 @@ status_t Camera2Device::StreamAdapter::connectToDevice( mSize, 1, mFormat); if (res != OK) { ALOGE("%s: Unable to configure compressed stream buffer geometry" - " %d x %d, size %d for stream %d", + " %d x %d, size %zu for stream %d", __FUNCTION__, mWidth, mHeight, mSize, mId); return res; } @@ -1214,11 +1215,11 @@ status_t Camera2Device::StreamAdapter::dump(int fd, ATRACE_CALL(); String8 result = String8::format(" Stream %d: %d x %d, format 0x%x\n", mId, mWidth, mHeight, mFormat); - result.appendFormat(" size %d, usage 0x%x, requested format 0x%x\n", + result.appendFormat(" size %zu, usage 0x%x, requested format 0x%x\n", mSize, mUsage, mFormatRequested); result.appendFormat(" total buffers: %d, dequeued buffers: %d\n", mTotalBuffers, mActiveBuffers); - result.appendFormat(" frame count: %d, last timestamp %lld\n", + result.appendFormat(" frame count: %d, last timestamp %" PRId64 "\n", mFrameCount, mLastTimestamp); write(fd, result.string(), result.size()); return OK; diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp index 3dbc1b0..1d4768c 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.cpp +++ b/services/camera/libcameraservice/device3/Camera3Device.cpp @@ -37,6 +37,8 @@ "%s: " fmt, __FUNCTION__, \ ##__VA_ARGS__) +#include <inttypes.h> + #include <utils/Log.h> #include <utils/Trace.h> #include <utils/Timers.h> @@ -345,7 +347,7 @@ status_t Camera3Device::dump(int fd, const Vector<String16> &args) { } else { for (size_t i = 0; i < mInFlightMap.size(); i++) { InFlightRequest r = mInFlightMap.valueAt(i); - lines.appendFormat(" Frame %d | Timestamp: %lld, metadata" + lines.appendFormat(" Frame %d | Timestamp: %" PRId64 ", metadata" " arrived: %s, buffers left: %d\n", mInFlightMap.keyAt(i), r.captureTimestamp, r.haveResultMetadata ? "true" : "false", r.numBuffersLeft); @@ -652,6 +654,8 @@ status_t Camera3Device::createZslStream( } mInputStream = newStream; + mNeedConfig = true; + *id = mNextStreamId++; *zslStream = newStream; @@ -676,7 +680,7 @@ status_t Camera3Device::createStream(sp<ANativeWindow> consumer, ATRACE_CALL(); Mutex::Autolock il(mInterfaceLock); Mutex::Autolock l(mLock); - ALOGV("Camera %d: Creating new stream %d: %d x %d, format %d, size %d", + ALOGV("Camera %d: Creating new stream %d: %d x %d, format %d, size %zu", mId, mNextStreamId, width, height, format, size); status_t res; @@ -1018,7 +1022,7 @@ status_t Camera3Device::waitForNextFrame(nsecs_t timeout) { if (res == TIMED_OUT) { return res; } else if (res != OK) { - ALOGW("%s: Camera %d: No frame in %lld ns: %s (%d)", + ALOGW("%s: Camera %d: No frame in %" PRId64 " ns: %s (%d)", __FUNCTION__, mId, timeout, strerror(-res), res); return res; } @@ -1673,7 +1677,7 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) { // Sanity check - if we have too many in-flight frames, something has // likely gone wrong if (mInFlightMap.size() > kInFlightWarnLimit) { - CLOGE("In-flight list too large: %d", mInFlightMap.size()); + CLOGE("In-flight list too large: %zu", mInFlightMap.size()); } } @@ -1723,7 +1727,7 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) { gotResult = false; } else if (timestamp != entry.data.i64[0]) { SET_ERR("Timestamp mismatch between shutter notify and result" - " metadata for frame %d (%lld vs %lld respectively)", + " metadata for frame %d (%" PRId64 " vs %" PRId64 " respectively)", frameNumber, timestamp, entry.data.i64[0]); gotResult = false; } @@ -1745,7 +1749,7 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) { // Note: stream may be deallocated at this point, if this buffer was the // last reference to it. if (res != OK) { - ALOGE("Can't return buffer %d for frame %d to its stream: " + ALOGE("Can't return buffer %zu for frame %d to its stream: " " %s (%d)", i, frameNumber, strerror(-res), res); } } @@ -1835,7 +1839,7 @@ void Camera3Device::notify(const camera3_notify_msg *msg) { frameNumber); break; } - ALOGVV("Camera %d: %s: Shutter fired for frame %d (id %d) at %lld", + ALOGVV("Camera %d: %s: Shutter fired for frame %d (id %d) at %" PRId64, mId, __FUNCTION__, frameNumber, requestId, timestamp); // Call listener, if any if (listener != NULL) { diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp index da51228..d662cc2 100644 --- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp +++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp @@ -18,8 +18,7 @@ #define ATRACE_TAG ATRACE_TAG_CAMERA //#define LOG_NDEBUG 0 -// This is needed for stdint.h to define INT64_MAX in C++ -#define __STDC_LIMIT_MACROS +#include <inttypes.h> #include <utils/Log.h> #include <utils/Trace.h> @@ -54,8 +53,8 @@ Camera3IOStreamBase::~Camera3IOStreamBase() { bool Camera3IOStreamBase::hasOutstandingBuffersLocked() const { nsecs_t signalTime = mCombinedFence->getSignalTime(); - ALOGV("%s: Stream %d: Has %d outstanding buffers," - " buffer signal time is %lld", + ALOGV("%s: Stream %d: Has %zu outstanding buffers," + " buffer signal time is %" PRId64, __FUNCTION__, mId, mDequeuedBufferCount, signalTime); if (mDequeuedBufferCount > 0 || signalTime == INT64_MAX) { return true; @@ -70,12 +69,12 @@ void Camera3IOStreamBase::dump(int fd, const Vector<String16> &args) const { lines.appendFormat(" Dims: %d x %d, format 0x%x\n", camera3_stream::width, camera3_stream::height, camera3_stream::format); - lines.appendFormat(" Max size: %d\n", mMaxSize); + lines.appendFormat(" Max size: %zu\n", mMaxSize); lines.appendFormat(" Usage: %d, max HAL buffers: %d\n", camera3_stream::usage, camera3_stream::max_buffers); - lines.appendFormat(" Frames produced: %d, last timestamp: %lld ns\n", + lines.appendFormat(" Frames produced: %d, last timestamp: %" PRId64 " ns\n", mFrameCount, mLastTimestamp); - lines.appendFormat(" Total buffers: %d, currently dequeued: %d\n", + lines.appendFormat(" Total buffers: %zu, currently dequeued: %zu\n", mTotalBufferCount, mDequeuedBufferCount); write(fd, lines.string(), lines.size()); } @@ -119,7 +118,7 @@ status_t Camera3IOStreamBase::disconnectLocked() { } if (mDequeuedBufferCount > 0) { - ALOGE("%s: Can't disconnect with %d buffers still dequeued!", + ALOGE("%s: Can't disconnect with %zu buffers still dequeued!", __FUNCTION__, mDequeuedBufferCount); return INVALID_OPERATION; } diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp index 6d2cf94..70406f1 100644 --- a/services/camera/libcameraservice/device3/Camera3Stream.cpp +++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp @@ -353,7 +353,7 @@ status_t Camera3Stream::registerBuffersLocked(camera3_device *hal3Device) { } if (bufferIdx == bufferCount) { // Got all buffers, register with HAL - ALOGV("%s: Registering %d buffers with camera HAL", + ALOGV("%s: Registering %zu buffers with camera HAL", __FUNCTION__, bufferCount); ATRACE_BEGIN("camera3->register_stream_buffers"); res = hal3Device->ops->register_stream_buffers(hal3Device, diff --git a/services/camera/libcameraservice/device3/Camera3ZslStream.cpp b/services/camera/libcameraservice/device3/Camera3ZslStream.cpp index 04f5dc5..44d8188 100644 --- a/services/camera/libcameraservice/device3/Camera3ZslStream.cpp +++ b/services/camera/libcameraservice/device3/Camera3ZslStream.cpp @@ -18,6 +18,8 @@ #define ATRACE_TAG ATRACE_TAG_CAMERA //#define LOG_NDEBUG 0 +#include <inttypes.h> + #include <utils/Log.h> #include <utils/Trace.h> #include "Camera3ZslStream.h" @@ -271,7 +273,7 @@ void Camera3ZslStream::dump(int fd, const Vector<String16> &args) const { Camera3IOStreamBase::dump(fd, args); lines = String8(); - lines.appendFormat(" Input buffers pending: %d, in flight %d\n", + lines.appendFormat(" Input buffers pending: %zu, in flight %zu\n", mInputBufferQueue.size(), mBuffersInFlight.size()); write(fd, lines.string(), lines.size()); } @@ -297,7 +299,7 @@ status_t Camera3ZslStream::enqueueInputBufferByTimestamp( if (actual != timestamp) { ALOGW("%s: ZSL buffer candidate search didn't find an exact match --" - " requested timestamp = %lld, actual timestamp = %lld", + " requested timestamp = %" PRId64 ", actual timestamp = %" PRId64, __FUNCTION__, timestamp, actual); } diff --git a/services/camera/libcameraservice/device3/StatusTracker.cpp b/services/camera/libcameraservice/device3/StatusTracker.cpp index ab5419f..723b5c2 100644 --- a/services/camera/libcameraservice/device3/StatusTracker.cpp +++ b/services/camera/libcameraservice/device3/StatusTracker.cpp @@ -18,9 +18,6 @@ #define ATRACE_TAG ATRACE_TAG_CAMERA //#define LOG_NDEBUG 0 -// This is needed for stdint.h to define INT64_MAX in C++ -#define __STDC_LIMIT_MACROS - #include <utils/Log.h> #include <utils/Trace.h> #include <ui/Fence.h> @@ -52,7 +49,7 @@ int StatusTracker::addComponent() { ALOGV("%s: Adding new component %d", __FUNCTION__, id); err = mStates.add(id, IDLE); - ALOGE_IF(err < 0, "%s: Can't add new component %d: %s (%d)", + ALOGE_IF(err < 0, "%s: Can't add new component %d: %s (%zd)", __FUNCTION__, id, strerror(-err), err); } diff --git a/services/camera/libcameraservice/gui/RingBufferConsumer.cpp b/services/camera/libcameraservice/gui/RingBufferConsumer.cpp index ebc7ea7..e4ec5fd 100644 --- a/services/camera/libcameraservice/gui/RingBufferConsumer.cpp +++ b/services/camera/libcameraservice/gui/RingBufferConsumer.cpp @@ -17,15 +17,18 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "RingBufferConsumer" #define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include <inttypes.h> + #include <utils/Log.h> #include <gui/RingBufferConsumer.h> -#define BI_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__) -#define BI_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__) -#define BI_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__) -#define BI_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__) -#define BI_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__) +#define BI_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__) +#define BI_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__) +#define BI_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__) +#define BI_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__) +#define BI_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__) #undef assert #define assert(x) ALOG_ASSERT((x), #x) @@ -164,10 +167,10 @@ void RingBufferConsumer::pinBufferLocked(const BufferItem& item) { } if (it == end) { - BI_LOGE("Failed to pin buffer (timestamp %lld, framenumber %lld)", + BI_LOGE("Failed to pin buffer (timestamp %" PRId64 ", framenumber %" PRIu64 ")", item.mTimestamp, item.mFrameNumber); } else { - BI_LOGV("Pinned buffer (frame %lld, timestamp %lld)", + BI_LOGV("Pinned buffer (frame %" PRIu64 ", timestamp %" PRId64 ")", item.mFrameNumber, item.mTimestamp); } } @@ -222,12 +225,12 @@ status_t RingBufferConsumer::releaseOldestBufferLocked(size_t* pinnedFrames) { if (err != OK) { BI_LOGE("Failed to add release fence to buffer " - "(timestamp %lld, framenumber %lld", + "(timestamp %" PRId64 ", framenumber %" PRIu64, item.mTimestamp, item.mFrameNumber); return err; } - BI_LOGV("Attempting to release buffer timestamp %lld, frame %lld", + BI_LOGV("Attempting to release buffer timestamp %" PRId64 ", frame %" PRIu64, item.mTimestamp, item.mFrameNumber); // item.mGraphicBuffer was populated with the proper graphic-buffer @@ -241,7 +244,7 @@ status_t RingBufferConsumer::releaseOldestBufferLocked(size_t* pinnedFrames) { return err; } - BI_LOGV("Buffer timestamp %lld, frame %lld evicted", + BI_LOGV("Buffer timestamp %" PRId64 ", frame %" PRIu64 " evicted", item.mTimestamp, item.mFrameNumber); size_t currentSize = mBufferItemList.size(); @@ -294,8 +297,8 @@ void RingBufferConsumer::onFrameAvailable() { return; } - BI_LOGV("New buffer acquired (timestamp %lld), " - "buffer items %u out of %d", + BI_LOGV("New buffer acquired (timestamp %" PRId64 "), " + "buffer items %zu out of %d", item.mTimestamp, mBufferItemList.size(), mBufferCount); @@ -321,7 +324,7 @@ void RingBufferConsumer::unpinBuffer(const BufferItem& item) { if (res != OK) { BI_LOGE("Failed to add release fence to buffer " - "(timestamp %lld, framenumber %lld", + "(timestamp %" PRId64 ", framenumber %" PRIu64, item.mTimestamp, item.mFrameNumber); return; } @@ -333,10 +336,10 @@ void RingBufferConsumer::unpinBuffer(const BufferItem& item) { if (it == end) { // This should never happen. If it happens, we have a bug. - BI_LOGE("Failed to unpin buffer (timestamp %lld, framenumber %lld)", + BI_LOGE("Failed to unpin buffer (timestamp %" PRId64 ", framenumber %" PRIu64 ")", item.mTimestamp, item.mFrameNumber); } else { - BI_LOGV("Unpinned buffer (timestamp %lld, framenumber %lld)", + BI_LOGV("Unpinned buffer (timestamp %" PRId64 ", framenumber %" PRIu64 ")", item.mTimestamp, item.mFrameNumber); } } diff --git a/services/camera/libcameraservice/utils/CameraTraces.cpp b/services/camera/libcameraservice/utils/CameraTraces.cpp index 346e15f..374dc5e 100644 --- a/services/camera/libcameraservice/utils/CameraTraces.cpp +++ b/services/camera/libcameraservice/utils/CameraTraces.cpp @@ -74,10 +74,10 @@ status_t CameraTraces::dump(int fd, const Vector<String16> &args __attribute__(( return BAD_VALUE; } - fdprintf(fd, "Camera traces (%zu):\n", pcsList.size()); + dprintf(fd, "Camera traces (%zu):\n", pcsList.size()); if (pcsList.empty()) { - fdprintf(fd, " No camera traces collected.\n"); + dprintf(fd, " No camera traces collected.\n"); } // Print newest items first diff --git a/services/medialog/Android.mk b/services/medialog/Android.mk index 08006c8..95f2fef 100644 --- a/services/medialog/Android.mk +++ b/services/medialog/Android.mk @@ -8,4 +8,6 @@ LOCAL_SHARED_LIBRARIES := libmedia libbinder libutils liblog libnbaio LOCAL_MODULE:= libmedialogservice +LOCAL_32_BIT_ONLY := true + include $(BUILD_SHARED_LIBRARY) diff --git a/services/medialog/MediaLogService.cpp b/services/medialog/MediaLogService.cpp index 683fdf3..e53b3a6 100644 --- a/services/medialog/MediaLogService.cpp +++ b/services/medialog/MediaLogService.cpp @@ -60,7 +60,7 @@ status_t MediaLogService::dump(int fd, const Vector<String16>& args) static const String16 sDump("android.permission.DUMP"); if (!(IPCThreadState::self()->getCallingUid() == AID_MEDIA || PermissionCache::checkCallingPermission(sDump))) { - fdprintf(fd, "Permission Denial: can't dump media.log from pid=%d, uid=%d\n", + dprintf(fd, "Permission Denial: can't dump media.log from pid=%d, uid=%d\n", IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid()); return NO_ERROR; @@ -74,7 +74,7 @@ status_t MediaLogService::dump(int fd, const Vector<String16>& args) for (size_t i = 0; i < namedReaders.size(); i++) { const NamedReader& namedReader = namedReaders[i]; if (fd >= 0) { - fdprintf(fd, "\n%s:\n", namedReader.name()); + dprintf(fd, "\n%s:\n", namedReader.name()); } else { ALOGI("%s:", namedReader.name()); } diff --git a/tools/resampler_tools/fir.cpp b/tools/resampler_tools/fir.cpp index cc3d509..8c8a4ea 100644 --- a/tools/resampler_tools/fir.cpp +++ b/tools/resampler_tools/fir.cpp @@ -243,7 +243,7 @@ int main(int argc, char** argv) } } } else { - for (int j=0 ; j<polyN ; j++) { + for (unsigned int j=0 ; j<polyN ; j++) { // calculate the phase double p = ((polyM*j) % polyN) / double(polyN); if (!debug) printf("\n "); |