Merge "Revert^5 "Conditional start the media.transcoding service.""" into sc-dev
diff --git a/apex/manifest.json b/apex/manifest.json
index c7e56be..5d72031 100644
--- a/apex/manifest.json
+++ b/apex/manifest.json
@@ -1,6 +1,6 @@
{
"name": "com.android.media",
- "version": 309999910,
+ "version": 319999900,
"requireNativeLibs": [
"libandroid.so",
"libbinder_ndk.so",
diff --git a/apex/manifest_codec.json b/apex/manifest_codec.json
index d36e914..b0d962d 100644
--- a/apex/manifest_codec.json
+++ b/apex/manifest_codec.json
@@ -1,6 +1,6 @@
{
"name": "com.android.media.swcodec",
- "version": 309999910,
+ "version": 319999900,
"requireNativeLibs": [
":sphal"
]
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 1cde4c6..52cd4b4 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -8908,13 +8908,27 @@
* camera's crop region is set to maximum size, the FOV of the physical streams for the
* ultrawide lens will be the same as the logical stream, by making the crop region
* smaller than its active array size to compensate for the smaller focal length.</p>
- * <p>Even if the underlying physical cameras have different RAW characteristics (such as
- * size or CFA pattern), a logical camera can still advertise RAW capability. In this
- * case, when the application configures a RAW stream, the camera device will make sure
- * the active physical camera will remain active to ensure consistent RAW output
- * behavior, and not switch to other physical cameras.</p>
+ * <p>There are two ways for the application to capture RAW images from a logical camera
+ * with RAW capability:</p>
+ * <ul>
+ * <li>Because the underlying physical cameras may have different RAW capabilities (such
+ * as resolution or CFA pattern), to maintain backward compatibility, when a RAW stream
+ * is configured, the camera device makes sure the default active physical camera remains
+ * active and does not switch to other physical cameras. (One exception is that, if the
+ * logical camera consists of identical image sensors and advertises multiple focalLength
+ * due to different lenses, the camera device may generate RAW images from different
+ * physical cameras based on the focalLength being set by the application.) This
+ * backward-compatible approach usually results in loss of optical zoom, to telephoto
+ * lens or to ultrawide lens.</li>
+ * <li>Alternatively, to take advantage of the full zoomRatio range of the logical camera,
+ * the application should use <a href="https://developer.android.com/reference/android/hardware/camera2/MultiResolutionImageReader.html">MultiResolutionImageReader</a>
+ * to capture RAW images from the currently active physical camera. Because different
+ * physical camera may have different RAW characteristics, the application needs to use
+ * the characteristics and result metadata of the active physical camera for the
+ * relevant RAW metadata.</li>
+ * </ul>
* <p>The capture request and result metadata tags required for backward compatible camera
- * functionalities will be solely based on the logical camera capabiltity. On the other
+ * functionalities will be solely based on the logical camera capability. On the other
* hand, the use of manual capture controls (sensor or post-processing) with a
* logical camera may result in unexpected behavior when the HAL decides to switch
* between physical cameras with different characteristics under the hood. For example,
diff --git a/drm/drmserver/drmserver.rc b/drm/drmserver/drmserver.rc
index de46fb9..eb176c1 100644
--- a/drm/drmserver/drmserver.rc
+++ b/drm/drmserver/drmserver.rc
@@ -1,5 +1,12 @@
service drm /system/bin/drmserver
+ disabled
class main
user drm
group drm system inet drmrpc readproc
writepid /dev/cpuset/foreground/tasks
+
+on property:drm.service.enabled=true
+ start drm
+
+on property:drm.service.enabled=1
+ start drm
diff --git a/drm/libdrmframework/DrmManagerClientImpl.cpp b/drm/libdrmframework/DrmManagerClientImpl.cpp
index b0a441b..a2cac3f 100644
--- a/drm/libdrmframework/DrmManagerClientImpl.cpp
+++ b/drm/libdrmframework/DrmManagerClientImpl.cpp
@@ -52,25 +52,13 @@
const sp<IDrmManagerService>& DrmManagerClientImpl::getDrmManagerService() {
Mutex::Autolock lock(sMutex);
if (NULL == sDrmManagerService.get()) {
- char value[PROPERTY_VALUE_MAX];
- if (property_get("drm.service.enabled", value, NULL) == 0) {
- // Drm is undefined for this device
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16("drm.drmManager"));
+ if (binder == NULL) {
+ // Do NOT retry; IServiceManager already waits for ~5 seconds
+ // in getService if a service doesn't yet exist.
return sDrmManagerService;
}
-
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder;
- do {
- binder = sm->getService(String16("drm.drmManager"));
- if (binder != 0) {
- break;
- }
- ALOGW("DrmManagerService not published, waiting...");
- struct timespec reqt;
- reqt.tv_sec = 0;
- reqt.tv_nsec = 500000000; //0.5 sec
- nanosleep(&reqt, NULL);
- } while (true);
if (NULL == sDeathNotifier.get()) {
sDeathNotifier = new DeathNotifier();
}
diff --git a/media/codec2/components/mp3/C2SoftMp3Dec.cpp b/media/codec2/components/mp3/C2SoftMp3Dec.cpp
index 7137767..30d7394 100644
--- a/media/codec2/components/mp3/C2SoftMp3Dec.cpp
+++ b/media/codec2/components/mp3/C2SoftMp3Dec.cpp
@@ -16,6 +16,7 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "C2SoftMp3Dec"
+#include <inttypes.h>
#include <log/log.h>
#include <numeric>
@@ -485,10 +486,10 @@
}
}
- uint64_t outTimeStamp = mProcessedSamples * 1000000ll / samplingRate;
+ int64_t outTimeStamp = mProcessedSamples * 1000000ll / samplingRate;
mProcessedSamples += ((outSize - outOffset) / (numChannels * sizeof(int16_t)));
- ALOGV("out buffer attr. offset %d size %d timestamp %u", outOffset, outSize - outOffset,
- (uint32_t)(mAnchorTimeStamp + outTimeStamp));
+ ALOGV("out buffer attr. offset %d size %d timestamp %" PRId64 " ", outOffset,
+ outSize - outOffset, mAnchorTimeStamp + outTimeStamp);
decodedSizes.clear();
work->worklets.front()->output.flags = work->input.flags;
work->worklets.front()->output.buffers.clear();
diff --git a/media/codec2/components/mp3/C2SoftMp3Dec.h b/media/codec2/components/mp3/C2SoftMp3Dec.h
index 402bdc4..e2dfcf3 100644
--- a/media/codec2/components/mp3/C2SoftMp3Dec.h
+++ b/media/codec2/components/mp3/C2SoftMp3Dec.h
@@ -63,7 +63,7 @@
bool mSignalledError;
bool mSignalledOutputEos;
bool mGaplessBytes;
- uint64_t mAnchorTimeStamp;
+ int64_t mAnchorTimeStamp;
uint64_t mProcessedSamples;
status_t initDecoder();
diff --git a/media/codec2/hidl/1.0/vts/functional/video/Android.bp b/media/codec2/hidl/1.0/vts/functional/video/Android.bp
index f211ecf..ecc4f9d 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/Android.bp
+++ b/media/codec2/hidl/1.0/vts/functional/video/Android.bp
@@ -36,6 +36,8 @@
"libgui",
"libutils",
"libcrypto",
+ "libdatasource",
+ "libui",
],
data: [":media_c2_v1_video_decode_res"],
test_config: "VtsHalMediaC2V1_0TargetVideoDecTest.xml",
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
index c331d0b..4c90eee 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
@@ -33,11 +33,18 @@
#include <gui/IConsumerListener.h>
#include <gui/IProducerListener.h>
#include <system/window.h>
+#include <gui/GLConsumer.h>
+#include <gui/Surface.h>
+#include <gui/SurfaceComposerClient.h>
#include "media_c2_hidl_test_common.h"
#include "media_c2_video_hidl_test_common.h"
-using DecodeTestParameters = std::tuple<std::string, std::string, uint32_t, bool>;
+constexpr size_t kSmoothnessFactor = 4;
+constexpr size_t kRenderingDepth = 3;
+enum surfaceMode_t { NO_SURFACE, NULL_SURFACE, SURFACE };
+
+using DecodeTestParameters = std::tuple<std::string, std::string, uint32_t, bool, surfaceMode_t>;
static std::vector<DecodeTestParameters> gDecodeTestParameters;
using CsdFlushTestParameters = std::tuple<std::string, std::string, bool>;
@@ -392,6 +399,36 @@
return false;
}
+void setOutputSurface(const std::shared_ptr<android::Codec2Client::Component>& component,
+ surfaceMode_t surfMode) {
+ using namespace android;
+ sp<IGraphicBufferProducer> producer = nullptr;
+ static std::atomic_uint32_t surfaceGeneration{0};
+ uint32_t generation =
+ (getpid() << 10) |
+ ((surfaceGeneration.fetch_add(1, std::memory_order_relaxed) + 1) & ((1 << 10) - 1));
+ int32_t maxDequeueBuffers = kSmoothnessFactor + kRenderingDepth;
+ if (surfMode == SURFACE) {
+ sp<IGraphicBufferConsumer> consumer = nullptr;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+ ASSERT_NE(producer, nullptr) << "createBufferQueue returned invalid producer";
+ ASSERT_NE(consumer, nullptr) << "createBufferQueue returned invalid consumer";
+
+ sp<GLConsumer> texture =
+ new GLConsumer(consumer, 0 /* tex */, GLConsumer::TEXTURE_EXTERNAL,
+ true /* useFenceSync */, false /* isControlledByApp */);
+
+ sp<ANativeWindow> gSurface = new Surface(producer);
+ ASSERT_NE(gSurface, nullptr) << "getSurface failed";
+
+ producer->setGenerationNumber(generation);
+ }
+
+ c2_status_t err = component->setOutputSurface(C2BlockPool::BASIC_GRAPHIC, producer, generation,
+ maxDequeueBuffers);
+ ASSERT_EQ(err, C2_OK) << "setOutputSurface failed";
+}
+
void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& component,
std::mutex& queueLock, std::condition_variable& queueCondition,
std::list<std::unique_ptr<C2Work>>& workQueue,
@@ -550,6 +587,7 @@
if (mDisableTest) GTEST_SKIP() << "Test is disabled";
bool signalEOS = std::get<3>(GetParam());
+ surfaceMode_t surfMode = std::get<4>(GetParam());
mTimestampDevTest = true;
android::Vector<FrameInfo> Info;
@@ -594,6 +632,10 @@
refChksum.close();
}
+ if (surfMode != NO_SURFACE) {
+ ASSERT_NO_FATAL_FAILURE(setOutputSurface(mComponent, surfMode));
+ }
+
ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
mFlushedIndices, mLinearPool, eleStream, &Info, 0,
(int)Info.size(), signalEOS));
@@ -1061,18 +1103,23 @@
parseArgs(argc, argv);
gTestParameters = getTestParameters(C2Component::DOMAIN_VIDEO, C2Component::KIND_DECODER);
for (auto params : gTestParameters) {
+ // mOutputBufferQueue->configure() crashes when surface is NULL
+ std::initializer_list<surfaceMode_t> surfaceMode = {
+ surfaceMode_t::NO_SURFACE, surfaceMode_t::NULL_SURFACE, surfaceMode_t::SURFACE};
+ for (surfaceMode_t mode : surfaceMode) {
+ gDecodeTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params), 0, false, mode));
+ gDecodeTestParameters.push_back(
+ std::make_tuple(std::get<0>(params), std::get<1>(params), 0, true, mode));
+ }
gDecodeTestParameters.push_back(
- std::make_tuple(std::get<0>(params), std::get<1>(params), 0, false));
+ std::make_tuple(std::get<0>(params), std::get<1>(params), 1, false, NO_SURFACE));
gDecodeTestParameters.push_back(
- std::make_tuple(std::get<0>(params), std::get<1>(params), 0, true));
+ std::make_tuple(std::get<0>(params), std::get<1>(params), 1, true, NO_SURFACE));
gDecodeTestParameters.push_back(
- std::make_tuple(std::get<0>(params), std::get<1>(params), 1, false));
+ std::make_tuple(std::get<0>(params), std::get<1>(params), 2, false, NO_SURFACE));
gDecodeTestParameters.push_back(
- std::make_tuple(std::get<0>(params), std::get<1>(params), 1, true));
- gDecodeTestParameters.push_back(
- std::make_tuple(std::get<0>(params), std::get<1>(params), 2, false));
- gDecodeTestParameters.push_back(
- std::make_tuple(std::get<0>(params), std::get<1>(params), 2, true));
+ std::make_tuple(std::get<0>(params), std::get<1>(params), 2, true, NO_SURFACE));
gCsdFlushTestParameters.push_back(
std::make_tuple(std::get<0>(params), std::get<1>(params), true));
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
index 6a00edd..a6507e7 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
@@ -334,6 +334,12 @@
int bytesCount = nWidth * nHeight * 3 >> 1;
int32_t timestampIncr = ENCODER_TIMESTAMP_INCREMENT;
c2_status_t err = C2_OK;
+
+ // Query component's memory usage flags
+ std::vector<std::unique_ptr<C2Param>> params;
+ C2StreamUsageTuning::input compUsage(0u, 0u);
+ component->query({&compUsage}, {}, C2_DONT_BLOCK, ¶ms);
+
while (1) {
if (nFrames == 0) break;
uint32_t flags = 0;
@@ -384,7 +390,8 @@
}
std::shared_ptr<C2GraphicBlock> block;
err = graphicPool->fetchGraphicBlock(nWidth, nHeight, HAL_PIXEL_FORMAT_YV12,
- {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE},
+ {C2MemoryUsage::CPU_READ | compUsage.value,
+ C2MemoryUsage::CPU_WRITE | compUsage.value},
&block);
if (err != C2_OK) {
fprintf(stderr, "fetchGraphicBlock failed : %d\n", err);
diff --git a/media/codec2/hidl/client/client.cpp b/media/codec2/hidl/client/client.cpp
index 71857e0..42b3c43 100644
--- a/media/codec2/hidl/client/client.cpp
+++ b/media/codec2/hidl/client/client.cpp
@@ -21,6 +21,7 @@
#include <codec2/hidl/client.h>
#include <C2Debug.h>
#include <C2BufferPriv.h>
+#include <C2Config.h> // for C2StreamUsageTuning
#include <C2PlatformSupport.h>
#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
@@ -41,7 +42,10 @@
#include <cutils/native_handle.h>
#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
+#include <hardware/gralloc.h> // for GRALLOC_USAGE_*
#include <hidl/HidlSupport.h>
+#include <system/window.h> // for NATIVE_WINDOW_QUERY_*
+#include <media/stagefright/foundation/ADebug.h> // for asString(status_t)
#include <deque>
@@ -81,6 +85,10 @@
// c2_status_t value that corresponds to hwbinder transaction failure.
constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
+// By default prepare buffer to be displayed on any of the common surfaces
+constexpr uint64_t kDefaultConsumerUsage =
+ (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER);
+
// Searches for a name in GetServiceNames() and returns the index found. If the
// name is not found, the returned index will be equal to
// GetServiceNames().size().
@@ -1507,8 +1515,43 @@
mOutputBufferQueue->configure(surface, generation, bqId, maxDequeueCount, mBase1_2 ?
&syncObj : nullptr);
}
- ALOGD("surface generation remote change %u HAL ver: %s",
- generation, syncObj ? "1.2" : "1.0");
+
+ // set consumer bits
+ // TODO: should this get incorporated into setOutputSurface method so that consumer bits
+ // can be set atomically?
+ uint64_t consumerUsage = kDefaultConsumerUsage;
+ {
+ if (surface) {
+ int usage = 0;
+ status_t err = surface->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &usage);
+ if (err != NO_ERROR) {
+ ALOGD("setOutputSurface -- failed to get consumer usage bits (%d/%s). ignoring",
+ err, asString(err));
+ } else {
+ // Note: we are adding the default usage because components must support
+ // producing output frames that can be displayed an all output surfaces.
+
+ // TODO: do not set usage for tunneled scenario. It is unclear if consumer usage
+ // is meaningful in a tunneled scenario; on one hand output buffers exist, but
+ // they do not exist inside of C2 scope. Any buffer usage shall be communicated
+ // through the sideband channel.
+
+ // do an unsigned conversion as bit-31 may be 1
+ consumerUsage = (uint32_t)usage | kDefaultConsumerUsage;
+ }
+ }
+
+ C2StreamUsageTuning::output outputUsage{
+ 0u, C2AndroidMemoryUsage::FromGrallocUsage(consumerUsage).expected};
+ std::vector<std::unique_ptr<C2SettingResult>> failures;
+ c2_status_t err = config({&outputUsage}, C2_MAY_BLOCK, &failures);
+ if (err != C2_OK) {
+ ALOGD("setOutputSurface -- failed to set consumer usage (%d/%s)",
+ err, asString(err));
+ }
+ }
+ ALOGD("setOutputSurface -- generation=%u consumer usage=%#llx%s",
+ generation, (long long)consumerUsage, syncObj ? " sync" : "");
Return<Status> transStatus = syncObj ?
mBase1_2->setOutputSurfaceWithSyncObj(
@@ -1517,6 +1560,7 @@
mBase1_0->setOutputSurface(
static_cast<uint64_t>(blockPoolId),
bqId == 0 ? nullHgbp : igbp);
+
if (!transStatus.isOk()) {
LOG(ERROR) << "setOutputSurface -- transaction failed.";
return C2_TRANSACTION_FAILED;
@@ -1694,4 +1738,3 @@
}
} // namespace android
-
diff --git a/media/codec2/hidl/client/output.cpp b/media/codec2/hidl/client/output.cpp
index 8cd4934..de34c24 100644
--- a/media/codec2/hidl/client/output.cpp
+++ b/media/codec2/hidl/client/output.cpp
@@ -181,7 +181,7 @@
int maxDequeueBufferCount,
std::shared_ptr<V1_2::SurfaceSyncObj> *syncObj) {
uint64_t consumerUsage = 0;
- if (igbp->getConsumerUsage(&consumerUsage) != OK) {
+ if (igbp && igbp->getConsumerUsage(&consumerUsage) != OK) {
ALOGW("failed to get consumer usage");
}
@@ -254,6 +254,9 @@
mBqId = bqId;
mOwner = std::make_shared<int>(0);
mMaxDequeueBufferCount = maxDequeueBufferCount;
+ if (igbp == nullptr) {
+ return false;
+ }
for (int i = 0; i < BufferQueueDefs::NUM_BUFFER_SLOTS; ++i) {
if (mBqId == 0 || !mBuffers[i]) {
continue;
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index f88408e..9e9bdfc 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -1341,6 +1341,15 @@
outputSurface,
outputGeneration,
maxDequeueCount);
+ } else {
+ // configure CPU read consumer usage
+ C2StreamUsageTuning::output outputUsage{0u, C2MemoryUsage::CPU_READ};
+ std::vector<std::unique_ptr<C2SettingResult>> failures;
+ err = mComponent->config({ &outputUsage }, C2_MAY_BLOCK, &failures);
+ // do not print error message for now as most components may not yet
+ // support this setting
+ ALOGD_IF(err != C2_BAD_INDEX, "[%s] Configured output usage [%#llx]",
+ mName, (long long)outputUsage.value);
}
if (oStreamFormat.value == C2BufferData::LINEAR) {
diff --git a/media/codec2/sfplugin/CCodecBuffers.cpp b/media/codec2/sfplugin/CCodecBuffers.cpp
index e7207a5..29cc564 100644
--- a/media/codec2/sfplugin/CCodecBuffers.cpp
+++ b/media/codec2/sfplugin/CCodecBuffers.cpp
@@ -1301,17 +1301,7 @@
sp<Codec2Buffer> RawGraphicOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
if (buffer == nullptr) {
- sp<Codec2Buffer> c2buffer = ConstGraphicBlockBuffer::AllocateEmpty(
- mFormat,
- [lbp = mLocalBufferPool](size_t capacity) {
- return lbp->newBuffer(capacity);
- });
- if (c2buffer == nullptr) {
- ALOGD("[%s] ConstGraphicBlockBuffer::AllocateEmpty failed", mName);
- return nullptr;
- }
- c2buffer->setRange(0, 0);
- return c2buffer;
+ return new Codec2Buffer(mFormat, new ABuffer(nullptr, 0));
} else {
return ConstGraphicBlockBuffer::Allocate(
mFormat,
diff --git a/media/codec2/sfplugin/Codec2InfoBuilder.cpp b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
index 77a63a7..7c4bfb6 100644
--- a/media/codec2/sfplugin/Codec2InfoBuilder.cpp
+++ b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
@@ -67,7 +67,8 @@
s.compare(s.size() - suffixLen, suffixLen, suffix) == 0;
}
-void addSupportedProfileLevels(
+// returns true if component advertised supported profile level(s)
+bool addSupportedProfileLevels(
std::shared_ptr<Codec2Client::Interface> intf,
MediaCodecInfo::CapabilitiesWriter *caps,
const Traits& trait, const std::string &mediaType) {
@@ -87,12 +88,12 @@
c2_status_t err = intf->querySupportedValues(profileQuery, C2_DONT_BLOCK);
ALOGV("query supported profiles -> %s | %s", asString(err), asString(profileQuery[0].status));
if (err != C2_OK || profileQuery[0].status != C2_OK) {
- return;
+ return false;
}
// we only handle enumerated values
if (profileQuery[0].values.type != C2FieldSupportedValues::VALUES) {
- return;
+ return false;
}
// determine if codec supports HDR
@@ -125,6 +126,8 @@
supportsHdr |= (mediaType == MIMETYPE_VIDEO_VP9);
supportsHdr |= (mediaType == MIMETYPE_VIDEO_AV1);
+ bool added = false;
+
for (C2Value::Primitive profile : profileQuery[0].values.values) {
pl.profile = (C2Config::profile_t)profile.ref<uint32_t>();
std::vector<std::unique_ptr<C2SettingResult>> failures;
@@ -165,6 +168,7 @@
} else if (!mapper) {
caps->addProfileLevel(pl.profile, pl.level);
}
+ added = true;
// for H.263 also advertise the second highest level if the
// codec supports level 45, as level 45 only covers level 10
@@ -188,6 +192,7 @@
}
}
}
+ return added;
}
void addSupportedColorFormats(
@@ -604,7 +609,15 @@
}
}
- addSupportedProfileLevels(intf, caps.get(), trait, mediaType);
+ if (!addSupportedProfileLevels(intf, caps.get(), trait, mediaType)) {
+ // TODO(b/193279646) This will get fixed in C2InterfaceHelper
+ // Some components may not advertise supported values if they use a const
+ // param for profile/level (they support only one profile). For now cover
+ // only VP8 here until it is fixed.
+ if (mediaType == MIMETYPE_VIDEO_VP8) {
+ caps->addProfileLevel(VP8ProfileMain, VP8Level_Version0);
+ }
+ }
addSupportedColorFormats(intf, caps.get(), trait, mediaType);
}
}
diff --git a/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp b/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
index 66b7622..41e4fff 100644
--- a/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
+++ b/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
@@ -106,6 +106,19 @@
}
}
+TEST(RawGraphicOutputBuffersTest, WrapNullBuffer) {
+ constexpr int32_t kWidth = 320;
+ constexpr int32_t kHeight = 240;
+
+ std::shared_ptr<RawGraphicOutputBuffers> buffers =
+ GetRawGraphicOutputBuffers(kWidth, kHeight);
+
+ sp<Codec2Buffer> buffer = buffers->wrap(nullptr);
+ ASSERT_EQ(nullptr, buffer->base());
+ ASSERT_EQ(0, buffer->size());
+ ASSERT_EQ(0, buffer->offset());
+}
+
TEST(RawGraphicOutputBuffersTest, FlexYuvColorFormat) {
constexpr int32_t kWidth = 320;
constexpr int32_t kHeight = 240;
diff --git a/media/codec2/vndk/C2AllocatorGralloc.cpp b/media/codec2/vndk/C2AllocatorGralloc.cpp
index 4ffa3f1..6a7f19c 100644
--- a/media/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/codec2/vndk/C2AllocatorGralloc.cpp
@@ -750,6 +750,16 @@
// We really don't know what this is; lock the buffer and pass it through ---
// the client may know how to interpret it.
+
+ // unlock previous allocation if it was successful
+ if (err == OK) {
+ err = GraphicBufferMapper::get().unlock(mBuffer);
+ if (err) {
+ ALOGE("failed transaction: unlock");
+ return C2_CORRUPTED;
+ }
+ }
+
void *pointer = nullptr;
err = GraphicBufferMapper::get().lock(
const_cast<native_handle_t *>(mBuffer), grallocUsage, rect, &pointer);
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 1ed240a..09d9535 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -452,8 +452,8 @@
void* threadArg)
{
if (mHasThread) {
- ALOGE("%s() - mHasThread already true", __func__);
- return AAUDIO_ERROR_INVALID_STATE;
+ ALOGD("%s() - previous thread was not joined, join now to be safe", __func__);
+ joinThread_l(nullptr);
}
if (threadProc == nullptr) {
return AAUDIO_ERROR_NULL;
@@ -462,6 +462,7 @@
mThreadProc = threadProc;
mThreadArg = threadArg;
setPeriodNanoseconds(periodNanoseconds);
+ mHasThread = true;
// Prevent this object from getting deleted before the thread has a chance to create
// its strong pointer. Assume the thread will call decStrong().
this->incStrong(nullptr);
@@ -470,6 +471,7 @@
android::status_t status = -errno;
ALOGE("%s() - pthread_create() failed, %d", __func__, status);
this->decStrong(nullptr); // Because the thread won't do it.
+ mHasThread = false;
return AAudioConvert_androidToAAudioResult(status);
} else {
// TODO Use AAudioThread or maybe AndroidThread
@@ -484,7 +486,6 @@
err = pthread_setname_np(mThread, name);
ALOGW_IF((err != 0), "Could not set name of AAudio thread. err = %d", err);
- mHasThread = true;
return AAUDIO_OK;
}
}
@@ -498,7 +499,7 @@
// This must be called under mStreamLock.
aaudio_result_t AudioStream::joinThread_l(void** returnArg) {
if (!mHasThread) {
- ALOGD("joinThread() - but has no thread");
+ ALOGD("joinThread() - but has no thread or already join()ed");
return AAUDIO_ERROR_INVALID_STATE;
}
aaudio_result_t result = AAUDIO_OK;
@@ -515,8 +516,7 @@
result = AAudioConvert_androidToAAudioResult(-err);
} else {
ALOGD("%s() pthread_join succeeded", __func__);
- // This must be set false so that the callback thread can be created
- // when the stream is restarted.
+ // Prevent joining a second time, which has undefined behavior.
mHasThread = false;
}
} else {
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index 2b45ed3..9835c8c 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -157,9 +157,13 @@
virtual aaudio_result_t setBufferSize(int32_t requestedFrames) = 0;
- virtual aaudio_result_t createThread_l(int64_t periodNanoseconds,
- aaudio_audio_thread_proc_t threadProc,
- void *threadArg);
+ aaudio_result_t createThread(int64_t periodNanoseconds,
+ aaudio_audio_thread_proc_t threadProc,
+ void *threadArg)
+ EXCLUDES(mStreamLock) {
+ std::lock_guard<std::mutex> lock(mStreamLock);
+ return createThread_l(periodNanoseconds, threadProc, threadArg);
+ }
aaudio_result_t joinThread(void **returnArg);
@@ -535,6 +539,11 @@
mSessionId = sessionId;
}
+ aaudio_result_t createThread_l(int64_t periodNanoseconds,
+ aaudio_audio_thread_proc_t threadProc,
+ void *threadArg)
+ REQUIRES(mStreamLock);
+
aaudio_result_t joinThread_l(void **returnArg) REQUIRES(mStreamLock);
std::atomic<bool> mCallbackEnabled{false};
@@ -658,6 +667,7 @@
std::atomic<pid_t> mErrorCallbackThread{CALLBACK_THREAD_NONE};
// background thread ----------------------------------
+ // Use mHasThread to prevent joining twice, which has undefined behavior.
bool mHasThread GUARDED_BY(mStreamLock) = false;
pthread_t mThread GUARDED_BY(mStreamLock) = {};
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 6765bdb..5f802de 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -472,7 +472,7 @@
status = BAD_VALUE;
goto exit;
}
- mStreamType = streamType;
+ mOriginalStreamType = streamType;
} else {
// stream type shouldn't be looked at, this track has audio attributes
@@ -481,7 +481,7 @@
" usage=%d content=%d flags=0x%x tags=[%s]",
__func__,
mAttributes.usage, mAttributes.content_type, mAttributes.flags, mAttributes.tags);
- mStreamType = AUDIO_STREAM_DEFAULT;
+ mOriginalStreamType = AUDIO_STREAM_DEFAULT;
audio_flags_to_audio_output_flags(mAttributes.flags, &flags);
}
@@ -1605,9 +1605,6 @@
audio_stream_type_t AudioTrack::streamType() const
{
- if (mStreamType == AUDIO_STREAM_DEFAULT) {
- return AudioSystem::attributesToStreamType(mAttributes);
- }
return mStreamType;
}
@@ -1688,8 +1685,9 @@
}
IAudioFlinger::CreateTrackInput input;
- if (mStreamType != AUDIO_STREAM_DEFAULT) {
- input.attr = AudioSystem::streamTypeToAttributes(mStreamType);
+ if (mOriginalStreamType != AUDIO_STREAM_DEFAULT) {
+ // Legacy: This is based on original parameters even if the track is recreated.
+ input.attr = AudioSystem::streamTypeToAttributes(mOriginalStreamType);
} else {
input.attr = mAttributes;
}
@@ -1745,6 +1743,7 @@
mNotificationFramesAct = (uint32_t)output.notificationFrameCount;
mRoutedDeviceId = output.selectedDeviceId;
mSessionId = output.sessionId;
+ mStreamType = output.streamType;
mSampleRate = output.sampleRate;
if (mOriginalSampleRate == 0) {
@@ -3284,8 +3283,6 @@
result.appendFormat(" id(%d) status(%d), state(%d), session Id(%d), flags(%#x)\n",
mPortId, mStatus, mState, mSessionId, mFlags);
result.appendFormat(" stream type(%d), left - right volume(%f, %f)\n",
- (mStreamType == AUDIO_STREAM_DEFAULT) ?
- AudioSystem::attributesToStreamType(mAttributes) :
mStreamType,
mVolume[AUDIO_INTERLEAVE_LEFT], mVolume[AUDIO_INTERLEAVE_RIGHT]);
result.appendFormat(" format(%#x), channel mask(%#x), channel count(%u)\n",
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 0564cdf..e46b349 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -101,6 +101,8 @@
legacy2aidl_audio_port_handle_t_int32_t(selectedDeviceId));
aidl.sessionId = VALUE_OR_RETURN(legacy2aidl_audio_session_t_int32_t(sessionId));
aidl.sampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(sampleRate));
+ aidl.streamType = VALUE_OR_RETURN(
+ legacy2aidl_audio_stream_type_t_AudioStreamType(streamType));
aidl.afFrameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(afFrameCount));
aidl.afSampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(afSampleRate));
aidl.afLatencyMs = VALUE_OR_RETURN(convertIntegral<int32_t>(afLatencyMs));
@@ -122,6 +124,8 @@
aidl2legacy_int32_t_audio_port_handle_t(aidl.selectedDeviceId));
legacy.sessionId = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_session_t(aidl.sessionId));
legacy.sampleRate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.sampleRate));
+ legacy.streamType = VALUE_OR_RETURN(
+ aidl2legacy_AudioStreamType_audio_stream_type_t(aidl.streamType));
legacy.afFrameCount = VALUE_OR_RETURN(convertIntegral<size_t>(aidl.afFrameCount));
legacy.afSampleRate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.afSampleRate));
legacy.afLatencyMs = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.afLatencyMs));
diff --git a/media/libaudioclient/aidl/android/media/CreateTrackResponse.aidl b/media/libaudioclient/aidl/android/media/CreateTrackResponse.aidl
index 6bdd8e4..40473fa 100644
--- a/media/libaudioclient/aidl/android/media/CreateTrackResponse.aidl
+++ b/media/libaudioclient/aidl/android/media/CreateTrackResponse.aidl
@@ -16,6 +16,7 @@
package android.media;
+import android.media.AudioStreamType;
import android.media.IAudioTrack;
/**
@@ -34,6 +35,7 @@
int selectedDeviceId;
int sessionId;
int sampleRate;
+ AudioStreamType streamType;
long afFrameCount;
int afSampleRate;
int afLatencyMs;
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index f61eef2..cb00990 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -1164,8 +1164,9 @@
// constant after constructor or set()
audio_format_t mFormat; // as requested by client, not forced to 16-bit
- audio_stream_type_t mStreamType; // mStreamType == AUDIO_STREAM_DEFAULT implies
- // this AudioTrack has valid attributes
+ // mOriginalStreamType == AUDIO_STREAM_DEFAULT implies this AudioTrack has valid attributes
+ audio_stream_type_t mOriginalStreamType = AUDIO_STREAM_DEFAULT;
+ audio_stream_type_t mStreamType = AUDIO_STREAM_DEFAULT;
uint32_t mChannelCount;
audio_channel_mask_t mChannelMask;
sp<IMemory> mSharedBuffer;
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 327b37e..0e059f7 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -110,6 +110,7 @@
/* output */
uint32_t sampleRate;
+ audio_stream_type_t streamType;
size_t afFrameCount;
uint32_t afSampleRate;
uint32_t afLatencyMs;
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index 9533ae5..8e05de8 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -145,15 +145,17 @@
return;
}
- // Close socket before posting message to RTSPSource message handler.
- if (mHandler != NULL) {
- close(mHandler->getARTSPConnection()->getSocket());
- }
-
sp<AMessage> msg = new AMessage(kWhatDisconnect, this);
sp<AMessage> dummy;
msg->postAndAwaitResponse(&dummy);
+
+ // Close socket after posting message to RTSPSource message handler.
+ if (mHandler != NULL && mHandler->getARTSPConnection()->getSocket() >= 0) {
+ ALOGD("closing rtsp socket if not closed yet.");
+ close(mHandler->getARTSPConnection()->getSocket());
+ }
+
}
status_t NuPlayer::RTSPSource::feedMoreTSData() {
diff --git a/media/libstagefright/rtsp/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp
index 8f4df8e..169df46 100644
--- a/media/libstagefright/rtsp/APacketSource.cpp
+++ b/media/libstagefright/rtsp/APacketSource.cpp
@@ -594,4 +594,15 @@
return mFormat;
}
+bool APacketSource::isVideo() {
+ bool isVideo = false;
+
+ const char *mime;
+ if (mFormat->findCString(kKeyMIMEType, &mime)) {
+ isVideo = !strncasecmp(mime, "video/", 6);
+ }
+
+ return isVideo;
+}
+
} // namespace android
diff --git a/media/libstagefright/rtsp/APacketSource.h b/media/libstagefright/rtsp/APacketSource.h
index 530e537..2b9b5ba 100644
--- a/media/libstagefright/rtsp/APacketSource.h
+++ b/media/libstagefright/rtsp/APacketSource.h
@@ -33,6 +33,8 @@
virtual sp<MetaData> getFormat();
+ bool isVideo();
+
protected:
virtual ~APacketSource();
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index 33c85a7..a4da433 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -104,6 +104,11 @@
msg->post();
}
+void ARTPConnection::seekStream() {
+ sp<AMessage> msg = new AMessage(kWhatSeekStream, this);
+ msg->post();
+}
+
void ARTPConnection::removeStream(int rtpSocket, int rtcpSocket) {
sp<AMessage> msg = new AMessage(kWhatRemoveStream, this);
msg->setInt32("rtp-socket", rtpSocket);
@@ -283,6 +288,12 @@
break;
}
+ case kWhatSeekStream:
+ {
+ onSeekStream(msg);
+ break;
+ }
+
case kWhatRemoveStream:
{
onRemoveStream(msg);
@@ -353,6 +364,18 @@
}
}
+void ARTPConnection::onSeekStream(const sp<AMessage> &msg) {
+ (void)msg; // unused param as of now.
+ List<StreamInfo>::iterator it = mStreams.begin();
+ while (it != mStreams.end()) {
+ for (size_t i = 0; i < it->mSources.size(); ++i) {
+ sp<ARTPSource> source = it->mSources.valueAt(i);
+ source->timeReset();
+ }
+ ++it;
+ }
+}
+
void ARTPConnection::onRemoveStream(const sp<AMessage> &msg) {
int32_t rtpSocket, rtcpSocket;
CHECK(msg->findInt32("rtp-socket", &rtpSocket));
diff --git a/media/libstagefright/rtsp/ARTPConnection.h b/media/libstagefright/rtsp/ARTPConnection.h
index ea0a374..adf9670 100644
--- a/media/libstagefright/rtsp/ARTPConnection.h
+++ b/media/libstagefright/rtsp/ARTPConnection.h
@@ -40,7 +40,7 @@
const sp<ASessionDescription> &sessionDesc, size_t index,
const sp<AMessage> ¬ify,
bool injected);
-
+ void seekStream();
void removeStream(int rtpSocket, int rtcpSocket);
void injectPacket(int index, const sp<ABuffer> &buffer);
@@ -69,6 +69,7 @@
private:
enum {
kWhatAddStream,
+ kWhatSeekStream,
kWhatRemoveStream,
kWhatPollStreams,
kWhatInjectPacket,
@@ -94,6 +95,7 @@
int32_t mCumulativeBytes;
void onAddStream(const sp<AMessage> &msg);
+ void onSeekStream(const sp<AMessage> &msg);
void onRemoveStream(const sp<AMessage> &msg);
void onPollStreams();
void onInjectPacket(const sp<AMessage> &msg);
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
index 8787d65..f960482 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -130,6 +130,24 @@
notify->post();
}
+void ARTPSource::timeReset() {
+ mFirstRtpTime = 0;
+ mFirstSysTime = 0;
+ mFirstSsrc = 0;
+ mHighestNackNumber = 0;
+ mHighestSeqNumber = 0;
+ mPrevExpected = 0;
+ mBaseSeqNumber = 0;
+ mNumBuffersReceived = 0;
+ mPrevNumBuffersReceived = 0;
+ mPrevExpectedForRR = 0;
+ mPrevNumBuffersReceivedForRR = 0;
+ mLastNTPTime = 0;
+ mLastNTPTimeUpdateUs = 0;
+ mIssueFIRByAssembler = false;
+ mLastFIRRequestUs = -1;
+}
+
bool ARTPSource::queuePacket(const sp<ABuffer> &buffer) {
uint32_t seqNum = (uint32_t)buffer->int32Data();
@@ -147,6 +165,11 @@
ALOGD("first-rtp arrived: first-rtp-time=%u, sys-time=%lld, seq-num=%u, ssrc=%d",
mFirstRtpTime, (long long)mFirstSysTime, mHighestSeqNumber, mFirstSsrc);
mJitterCalc->init(mFirstRtpTime, mFirstSysTime, 0, mStaticJbTimeMs * 1000);
+ if (mQueue.size() > 0) {
+ ALOGD("clearing buffers which belonged to previous timeline"
+ " since a base timeline has been changed.");
+ mQueue.clear();
+ }
mQueue.push_back(buffer);
return true;
}
diff --git a/media/libstagefright/rtsp/ARTPSource.h b/media/libstagefright/rtsp/ARTPSource.h
index 0edff23..2d804d8 100644
--- a/media/libstagefright/rtsp/ARTPSource.h
+++ b/media/libstagefright/rtsp/ARTPSource.h
@@ -56,6 +56,7 @@
};
void processRTPPacket(const sp<ABuffer> &buffer);
+ void timeReset();
void timeUpdate(uint32_t rtpTime, uint64_t ntpTime);
void byeReceived();
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index ec70952..29e263d 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -327,16 +327,17 @@
while (buffer->range_length() > 0) {
const uint8_t *NALPtr = (const uint8_t *)buffer->data() + buffer->range_offset();
+ uint8_t nalType = (*NALPtr) & H264_NALU_MASK;
MediaBufferBase **targetPtr = NULL;
- if ((*NALPtr & H264_NALU_MASK) == H264_NALU_SPS) {
+ if (nalType == H264_NALU_SPS) {
targetPtr = spsBuffer;
- } else if ((*NALPtr & H264_NALU_MASK) == H264_NALU_PPS) {
+ } else if (nalType == H264_NALU_PPS) {
targetPtr = ppsBuffer;
} else {
return;
}
- ALOGV("SPS(7) or PPS(8) found. Type %d", *NALPtr & H264_NALU_MASK);
+ ALOGV("SPS(7) or PPS(8) found. Type %d", nalType);
uint32_t bufferSize = buffer->range_length();
MediaBufferBase *&target = *targetPtr;
@@ -417,18 +418,18 @@
}
}
+ uint32_t targetSize;
if (target != NULL) {
target->release();
}
- uint32_t targetSize;
// note that targetSize is never 0 as the first byte is never part
// of a start prefix
if (isBoundFound) {
targetSize = i - SPCSize + 1;
- target = MediaBufferBase::Create(j);
+ target = MediaBufferBase::Create(targetSize);
memcpy(target->data(),
(const uint8_t *)buffer->data() + buffer->range_offset(),
- j);
+ targetSize);
buffer->set_range(buffer->range_offset() + targetSize + SPCSize,
buffer->range_length() - targetSize - SPCSize);
} else {
@@ -994,12 +995,14 @@
}
sp<ABuffer> buffer = new ABuffer(kMaxPacketSize);
-
if (mediaBuf->range_length() + TCPIP_HEADER_SIZE + RTP_HEADER_SIZE + RTP_HEADER_EXT_SIZE
+ RTP_PAYLOAD_ROOM_SIZE <= buffer->capacity()) {
// The data fits into a single packet
uint8_t *data = buffer->data();
data[0] = 0x80;
+ if (mRTPCVOExtMap > 0) {
+ data[0] |= 0x10;
+ }
if (isNonVCL) {
data[1] = mPayloadType; // Marker bit should not be set in case of Non-VCL
} else {
@@ -1016,144 +1019,6 @@
data[10] = (mSourceID >> 8) & 0xff;
data[11] = mSourceID & 0xff;
- memcpy(&data[12],
- mediaData, mediaBuf->range_length());
-
- buffer->setRange(0, mediaBuf->range_length() + 12);
-
- send(buffer, false /* isRTCP */);
-
- ++mSeqNo;
- ++mNumRTPSent;
- mNumRTPOctetsSent += buffer->size() - 12;
- } else {
- // FU-A
-
- unsigned nalType = (mediaData[0] >> 1) & H265_NALU_MASK;
- ALOGV("H265 nalType 0x%x, data[0]=0x%x", nalType, mediaData[0]);
- size_t offset = 2; //H265 payload header is 16 bit.
-
- bool firstPacket = true;
- while (offset < mediaBuf->range_length()) {
- size_t size = mediaBuf->range_length() - offset;
- bool lastPacket = true;
- if (size + TCPIP_HEADER_SIZE + RTP_HEADER_SIZE + RTP_HEADER_EXT_SIZE +
- RTP_FU_HEADER_SIZE + RTP_PAYLOAD_ROOM_SIZE > buffer->capacity()) {
- lastPacket = false;
- size = buffer->capacity() - TCPIP_HEADER_SIZE - RTP_HEADER_SIZE -
- RTP_HEADER_EXT_SIZE - RTP_FU_HEADER_SIZE - RTP_PAYLOAD_ROOM_SIZE;
- }
-
- uint8_t *data = buffer->data();
- data[0] = 0x80;
- data[1] = (lastPacket ? (1 << 7) : 0x00) | mPayloadType; // M-bit
- data[2] = (mSeqNo >> 8) & 0xff;
- data[3] = mSeqNo & 0xff;
- data[4] = rtpTime >> 24;
- data[5] = (rtpTime >> 16) & 0xff;
- data[6] = (rtpTime >> 8) & 0xff;
- data[7] = rtpTime & 0xff;
- data[8] = mSourceID >> 24;
- data[9] = (mSourceID >> 16) & 0xff;
- data[10] = (mSourceID >> 8) & 0xff;
- data[11] = mSourceID & 0xff;
-
- /* H265 payload header is 16 bit
- 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- |F| Type | Layer ID | TID |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
- ALOGV("H265 payload header 0x%x %x", mediaData[0], mediaData[1]);
- // excludes Type from 1st byte of H265 payload header.
- data[12] = mediaData[0] & 0x81;
- // fills Type as FU (49 == 0x31)
- data[12] = data[12] | (0x31 << 1);
- data[13] = mediaData[1];
-
- ALOGV("H265 FU header 0x%x %x", data[12], data[13]);
-
- CHECK(!firstPacket || !lastPacket);
- /*
- FU INDICATOR HDR
- 0 1 2 3 4 5 6 7
- +-+-+-+-+-+-+-+
- |S|E| Type |
- +-+-+-+-+-+-+-+
- */
-
- data[14] =
- (firstPacket ? 0x80 : 0x00)
- | (lastPacket ? 0x40 : 0x00)
- | (nalType & H265_NALU_MASK);
- ALOGV("H265 FU indicator 0x%x", data[14]);
-
- memcpy(&data[15], &mediaData[offset], size);
-
- buffer->setRange(0, 15 + size);
-
- send(buffer, false /* isRTCP */);
-
- ++mSeqNo;
- ++mNumRTPSent;
- mNumRTPOctetsSent += buffer->size() - 12;
-
- firstPacket = false;
- offset += size;
- }
- }
-
- mLastRTPTime = rtpTime;
- mLastNTPTime = GetNowNTP();
-
-}
-
-void ARTPWriter::sendAVCData(MediaBufferBase *mediaBuf) {
- // 12 bytes RTP header + 2 bytes for the FU-indicator and FU-header.
- CHECK_GE(kMaxPacketSize, 12u + 2u);
-
- int64_t timeUs;
- CHECK(mediaBuf->meta_data().findInt64(kKeyTime, &timeUs));
-
- sendSPSPPSIfIFrame(mediaBuf, timeUs);
-
- uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100LL);
-
- CHECK(mediaBuf->range_length() > 0);
- const uint8_t *mediaData =
- (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
-
- int32_t sps, pps;
- bool isSpsPps = false;
- if (mediaBuf->meta_data().findInt32(kKeySps, &sps) ||
- mediaBuf->meta_data().findInt32(kKeyPps, &pps)) {
- isSpsPps = true;
- }
-
- mTrafficRec->updateClock(ALooper::GetNowUs() / 1000);
- sp<ABuffer> buffer = new ABuffer(kMaxPacketSize);
- if (mediaBuf->range_length() + TCPIP_HEADER_SIZE + RTP_HEADER_SIZE + RTP_HEADER_EXT_SIZE
- + RTP_PAYLOAD_ROOM_SIZE <= buffer->capacity()) {
- // The data fits into a single packet
- uint8_t *data = buffer->data();
- data[0] = 0x80;
- if (mRTPCVOExtMap > 0)
- data[0] |= 0x10;
- if (isSpsPps)
- data[1] = mPayloadType; // Marker bit should not be set in case of sps/pps
- else
- data[1] = (1 << 7) | mPayloadType;
- data[2] = (mSeqNo >> 8) & 0xff;
- data[3] = mSeqNo & 0xff;
- data[4] = rtpTime >> 24;
- data[5] = (rtpTime >> 16) & 0xff;
- data[6] = (rtpTime >> 8) & 0xff;
- data[7] = rtpTime & 0xff;
- data[8] = mSourceID >> 24;
- data[9] = (mSourceID >> 16) & 0xff;
- data[10] = (mSourceID >> 8) & 0xff;
- data[11] = mSourceID & 0xff;
-
int rtpExtIndex = 0;
if (mRTPCVOExtMap > 0) {
/*
@@ -1202,8 +1067,9 @@
} else {
// FU-A
- unsigned nalType = mediaData[0];
- size_t offset = 1;
+ unsigned nalType = (mediaData[0] >> 1) & H265_NALU_MASK;
+ ALOGV("H265 nalType 0x%x, data[0]=0x%x", nalType, mediaData[0]);
+ size_t offset = 2; //H265 payload header is 16 bit.
bool firstPacket = true;
while (offset < mediaBuf->range_length()) {
@@ -1218,8 +1084,9 @@
uint8_t *data = buffer->data();
data[0] = 0x80;
- if (lastPacket && mRTPCVOExtMap > 0)
+ if (lastPacket && mRTPCVOExtMap > 0) {
data[0] |= 0x10;
+ }
data[1] = (lastPacket ? (1 << 7) : 0x00) | mPayloadType; // M-bit
data[2] = (mSeqNo >> 8) & 0xff;
data[3] = mSeqNo & 0xff;
@@ -1245,14 +1112,222 @@
rtpExtIndex = 8;
}
- data[12 + rtpExtIndex] = 28 | (nalType & 0xe0);
+ /* H265 payload header is 16 bit
+ 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |F| Type | Layer ID | TID |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ ALOGV("H265 payload header 0x%x %x", mediaData[0], mediaData[1]);
+ // excludes Type from 1st byte of H265 payload header.
+ data[12 + rtpExtIndex] = mediaData[0] & 0x81;
+ // fills Type as FU (49 == 0x31)
+ data[12 + rtpExtIndex] = data[12 + rtpExtIndex] | (0x31 << 1);
+ data[13 + rtpExtIndex] = mediaData[1];
+
+ ALOGV("H265 FU header 0x%x %x", data[12 + rtpExtIndex], data[13 + rtpExtIndex]);
CHECK(!firstPacket || !lastPacket);
+ /*
+ FU INDICATOR HDR
+ 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+
+ |S|E| Type |
+ +-+-+-+-+-+-+-+-+
+ */
+
+ data[14 + rtpExtIndex] =
+ (firstPacket ? 0x80 : 0x00)
+ | (lastPacket ? 0x40 : 0x00)
+ | (nalType & H265_NALU_MASK);
+ ALOGV("H265 FU indicator 0x%x", data[14]);
+
+ memcpy(&data[15 + rtpExtIndex], &mediaData[offset], size);
+
+ buffer->setRange(0, 15 + rtpExtIndex + size);
+
+ send(buffer, false /* isRTCP */);
+
+ ++mSeqNo;
+ ++mNumRTPSent;
+ mNumRTPOctetsSent += buffer->size() - (12 + rtpExtIndex);
+
+ firstPacket = false;
+ offset += size;
+ }
+ }
+
+ mLastRTPTime = rtpTime;
+ mLastNTPTime = GetNowNTP();
+}
+
+void ARTPWriter::sendAVCData(MediaBufferBase *mediaBuf) {
+ // 12 bytes RTP header + 2 bytes for the FU-indicator and FU-header.
+ CHECK_GE(kMaxPacketSize, 12u + 2u);
+
+ int64_t timeUs;
+ CHECK(mediaBuf->meta_data().findInt64(kKeyTime, &timeUs));
+
+ sendSPSPPSIfIFrame(mediaBuf, timeUs);
+
+ uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100LL);
+
+ CHECK(mediaBuf->range_length() > 0);
+ const uint8_t *mediaData =
+ (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
+
+ int32_t sps, pps;
+ bool isSpsPps = false;
+ if (mediaBuf->meta_data().findInt32(kKeySps, &sps) ||
+ mediaBuf->meta_data().findInt32(kKeyPps, &pps)) {
+ isSpsPps = true;
+ }
+
+ mTrafficRec->updateClock(ALooper::GetNowUs() / 1000);
+ sp<ABuffer> buffer = new ABuffer(kMaxPacketSize);
+ if (mediaBuf->range_length() + TCPIP_HEADER_SIZE + RTP_HEADER_SIZE + RTP_HEADER_EXT_SIZE
+ + RTP_PAYLOAD_ROOM_SIZE <= buffer->capacity()) {
+ // The data fits into a single packet
+ uint8_t *data = buffer->data();
+ data[0] = 0x80;
+ if (mRTPCVOExtMap > 0) {
+ data[0] |= 0x10;
+ }
+ if (isSpsPps) {
+ data[1] = mPayloadType; // Marker bit should not be set in case of sps/pps
+ } else {
+ data[1] = (1 << 7) | mPayloadType;
+ }
+ data[2] = (mSeqNo >> 8) & 0xff;
+ data[3] = mSeqNo & 0xff;
+ data[4] = rtpTime >> 24;
+ data[5] = (rtpTime >> 16) & 0xff;
+ data[6] = (rtpTime >> 8) & 0xff;
+ data[7] = rtpTime & 0xff;
+ data[8] = mSourceID >> 24;
+ data[9] = (mSourceID >> 16) & 0xff;
+ data[10] = (mSourceID >> 8) & 0xff;
+ data[11] = mSourceID & 0xff;
+
+ int rtpExtIndex = 0;
+ if (mRTPCVOExtMap > 0) {
+ /*
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 0xBE | 0xDE | length=3 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | ID | L=0 | data | ID | L=1 | data...
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ...data | 0 (pad) | 0 (pad) | ID | L=3 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | data |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+ In the one-byte header form of extensions, the 16-bit value required
+ by the RTP specification for a header extension, labeled in the RTP
+ specification as "defined by profile", takes the fixed bit pattern
+ 0xBEDE (the first version of this specification was written on the
+ feast day of the Venerable Bede).
+ */
+ data[12] = 0xBE;
+ data[13] = 0xDE;
+ // put a length of RTP Extension.
+ data[14] = 0x00;
+ data[15] = 0x01;
+ // put extmap of RTP assigned for CVO.
+ data[16] = (mRTPCVOExtMap << 4) | 0x0;
+ // put image degrees as per CVO specification.
+ data[17] = mRTPCVODegrees;
+ data[18] = 0x0;
+ data[19] = 0x0;
+ rtpExtIndex = 8;
+ }
+
+ memcpy(&data[12 + rtpExtIndex],
+ mediaData, mediaBuf->range_length());
+
+ buffer->setRange(0, mediaBuf->range_length() + (12 + rtpExtIndex));
+
+ send(buffer, false /* isRTCP */);
+
+ ++mSeqNo;
+ ++mNumRTPSent;
+ mNumRTPOctetsSent += buffer->size() - (12 + rtpExtIndex);
+ } else {
+ // FU-A
+
+ unsigned nalType = mediaData[0] & H264_NALU_MASK;
+ ALOGV("H264 nalType 0x%x, data[0]=0x%x", nalType, mediaData[0]);
+ size_t offset = 1;
+
+ bool firstPacket = true;
+ while (offset < mediaBuf->range_length()) {
+ size_t size = mediaBuf->range_length() - offset;
+ bool lastPacket = true;
+ if (size + TCPIP_HEADER_SIZE + RTP_HEADER_SIZE + RTP_HEADER_EXT_SIZE +
+ RTP_FU_HEADER_SIZE + RTP_PAYLOAD_ROOM_SIZE > buffer->capacity()) {
+ lastPacket = false;
+ size = buffer->capacity() - TCPIP_HEADER_SIZE - RTP_HEADER_SIZE -
+ RTP_HEADER_EXT_SIZE - RTP_FU_HEADER_SIZE - RTP_PAYLOAD_ROOM_SIZE;
+ }
+
+ uint8_t *data = buffer->data();
+ data[0] = 0x80;
+ if (lastPacket && mRTPCVOExtMap > 0) {
+ data[0] |= 0x10;
+ }
+ data[1] = (lastPacket ? (1 << 7) : 0x00) | mPayloadType; // M-bit
+ data[2] = (mSeqNo >> 8) & 0xff;
+ data[3] = mSeqNo & 0xff;
+ data[4] = rtpTime >> 24;
+ data[5] = (rtpTime >> 16) & 0xff;
+ data[6] = (rtpTime >> 8) & 0xff;
+ data[7] = rtpTime & 0xff;
+ data[8] = mSourceID >> 24;
+ data[9] = (mSourceID >> 16) & 0xff;
+ data[10] = (mSourceID >> 8) & 0xff;
+ data[11] = mSourceID & 0xff;
+
+ int rtpExtIndex = 0;
+ if (lastPacket && mRTPCVOExtMap > 0) {
+ data[12] = 0xBE;
+ data[13] = 0xDE;
+ data[14] = 0x00;
+ data[15] = 0x01;
+ data[16] = (mRTPCVOExtMap << 4) | 0x0;
+ data[17] = mRTPCVODegrees;
+ data[18] = 0x0;
+ data[19] = 0x0;
+ rtpExtIndex = 8;
+ }
+
+ /* H264 payload header is 8 bit
+ 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+
+ |F|NRI| Type |
+ +-+-+-+-+-+-+-+-+
+ */
+ ALOGV("H264 payload header 0x%x", mediaData[0]);
+ // excludes Type from 1st byte of H264 payload header.
+ data[12 + rtpExtIndex] = mediaData[0] & 0xe0;
+ // fills Type as FU (28 == 0x1C)
+ data[12 + rtpExtIndex] = data[12 + rtpExtIndex] | 0x1C;
+
+ CHECK(!firstPacket || !lastPacket);
+ /*
+ FU header
+ 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+
+ |S|E|R| Type |
+ +-+-+-+-+-+-+-+-+
+ */
data[13 + rtpExtIndex] =
(firstPacket ? 0x80 : 0x00)
| (lastPacket ? 0x40 : 0x00)
- | (nalType & 0x1f);
+ | (nalType & H264_NALU_MASK);
+ ALOGV("H264 FU header 0x%x", data[13]);
memcpy(&data[14 + rtpExtIndex], &mediaData[offset], size);
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 0fdf431..988cec7 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -74,7 +74,8 @@
// The allowed maximum number of stale access units at the beginning of
// a new sequence.
-static int32_t kMaxAllowedStaleAccessUnits = 20;
+static int32_t kMaxAllowedStaleAudioAccessUnits = 20;
+static int32_t kMaxAllowedStaleVideoAccessUnits = 400;
static int64_t kTearDownTimeoutUs = 3000000ll;
@@ -108,6 +109,10 @@
}
}
+static int32_t GetMaxAllowedStaleCount(bool isVideo) {
+ return isVideo ? kMaxAllowedStaleVideoAccessUnits : kMaxAllowedStaleAudioAccessUnits;
+}
+
struct MyHandler : public AHandler {
enum {
kWhatConnected = 'conn',
@@ -1330,6 +1335,8 @@
ALOGV("rtp-info: %s", response->mHeaders.valueAt(i).c_str());
+ mRTPConn->seekStream();
+
ALOGI("seek completed.");
}
}
@@ -1514,7 +1521,7 @@
TrackInfo *info = &mTracks.editItemAt(trackIndex);
info->mFirstSeqNumInSegment = seq;
info->mNewSegment = true;
- info->mAllowedStaleAccessUnits = kMaxAllowedStaleAccessUnits;
+ info->mAllowedStaleAccessUnits = GetMaxAllowedStaleCount(info->mIsVideo);
CHECK(GetAttribute((*it).c_str(), "rtptime", &val));
@@ -1556,6 +1563,7 @@
int mRTPSocket;
int mRTCPSocket;
bool mUsingInterleavedTCP;
+ bool mIsVideo;
uint32_t mFirstSeqNumInSegment;
bool mNewSegment;
int32_t mAllowedStaleAccessUnits;
@@ -1640,9 +1648,10 @@
info->mURL = trackURL;
info->mPacketSource = source;
info->mUsingInterleavedTCP = false;
+ info->mIsVideo = source->isVideo();
info->mFirstSeqNumInSegment = 0;
info->mNewSegment = true;
- info->mAllowedStaleAccessUnits = kMaxAllowedStaleAccessUnits;
+ info->mAllowedStaleAccessUnits = GetMaxAllowedStaleCount(info->mIsVideo);
info->mRTPSocket = -1;
info->mRTCPSocket = -1;
info->mRTPAnchor = 0;
@@ -1838,11 +1847,12 @@
// by ARTPSource. Only the low 16 bits of seq in RTP-Info of reply of
// RTSP "PLAY" command should be used to detect the first RTP packet
// after seeking.
+ int32_t maxAllowedStaleAccessUnits = GetMaxAllowedStaleCount(track->mIsVideo);
if (mSeekable) {
if (track->mAllowedStaleAccessUnits > 0) {
uint32_t seqNum16 = seqNum & 0xffff;
uint32_t firstSeqNumInSegment16 = track->mFirstSeqNumInSegment & 0xffff;
- if (seqNum16 > firstSeqNumInSegment16 + kMaxAllowedStaleAccessUnits
+ if (seqNum16 > firstSeqNumInSegment16 + maxAllowedStaleAccessUnits
|| seqNum16 < firstSeqNumInSegment16) {
// Not the first rtp packet of the stream after seeking, discarding.
track->mAllowedStaleAccessUnits--;
@@ -1857,7 +1867,7 @@
mNumAccessUnitsReceived = 0;
ALOGW_IF(track->mAllowedStaleAccessUnits == 0,
"Still no first rtp packet after %d stale ones",
- kMaxAllowedStaleAccessUnits);
+ maxAllowedStaleAccessUnits);
track->mAllowedStaleAccessUnits = -1;
return UNKNOWN_ERROR;
}
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 54a6425..65a163f 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -947,6 +947,7 @@
output.frameCount = input.frameCount;
output.notificationFrameCount = input.notificationFrameCount;
output.flags = input.flags;
+ output.streamType = streamType;
track = thread->createTrack_l(client, streamType, localAttr, &output.sampleRate,
input.config.format, input.config.channel_mask,
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 9e099ce..b9cdab8 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -8220,6 +8220,7 @@
status_t AudioFlinger::RecordThread::shareAudioHistory_l(
const std::string& sharedAudioPackageName, audio_session_t sharedSessionId,
int64_t sharedAudioStartMs) {
+
if ((hasAudioSession_l(sharedSessionId) & ThreadBase::TRACK_SESSION) == 0) {
return BAD_VALUE;
}
@@ -8234,18 +8235,21 @@
// after one wraparound
// We assume recent wraparounds on mRsmpInRear only given it is unlikely that the requesting
// app waits several hours after the start time was computed.
- const int64_t sharedAudioStartFrames = sharedAudioStartMs * mSampleRate / 1000;
+ int64_t sharedAudioStartFrames = sharedAudioStartMs * mSampleRate / 1000;
const int32_t sharedOffset = audio_utils::safe_sub_overflow(mRsmpInRear,
(int32_t)sharedAudioStartFrames);
- if (sharedOffset < 0
- || sharedOffset > mRsmpInFrames) {
- return BAD_VALUE;
+ // Bring the start frame position within the input buffer to match the documented
+ // "best effort" behavior of the API.
+ if (sharedOffset < 0) {
+ sharedAudioStartFrames = mRsmpInRear;
+ } else if (sharedOffset > mRsmpInFrames) {
+ sharedAudioStartFrames =
+ audio_utils::safe_sub_overflow(mRsmpInRear, (int32_t)mRsmpInFrames);
}
mSharedAudioPackageName = sharedAudioPackageName;
if (mSharedAudioPackageName.empty()) {
- mSharedAudioSessionId = AUDIO_SESSION_NONE;
- mSharedAudioStartFrames = -1;
+ resetAudioHistory_l();
} else {
mSharedAudioSessionId = sharedSessionId;
mSharedAudioStartFrames = (int32_t)sharedAudioStartFrames;
@@ -8253,6 +8257,12 @@
return NO_ERROR;
}
+void AudioFlinger::RecordThread::resetAudioHistory_l() {
+ mSharedAudioSessionId = AUDIO_SESSION_NONE;
+ mSharedAudioStartFrames = -1;
+ mSharedAudioPackageName = "";
+}
+
void AudioFlinger::RecordThread::updateMetadata_l()
{
if (!isStreamInitialized() || !mActiveTracks.readAndClearHasChanged()) {
@@ -8862,23 +8872,22 @@
int32_t AudioFlinger::RecordThread::getOldestFront_l()
{
if (mTracks.size() == 0) {
- return 0;
+ return mRsmpInRear;
}
int32_t oldestFront = mRsmpInRear;
int32_t maxFilled = 0;
for (size_t i = 0; i < mTracks.size(); i++) {
int32_t front = mTracks[i]->mResamplerBufferProvider->getFront();
int32_t filled;
- if (front <= mRsmpInRear) {
- filled = mRsmpInRear - front;
- } else {
- filled = (int32_t)((int64_t)mRsmpInRear + UINT32_MAX + 1 - front);
- }
+ (void)__builtin_sub_overflow(mRsmpInRear, front, &filled);
if (filled > maxFilled) {
oldestFront = front;
maxFilled = filled;
}
}
+ if (maxFilled > mRsmpInFrames) {
+ (void)__builtin_sub_overflow(mRsmpInRear, mRsmpInFrames, &oldestFront);
+ }
return oldestFront;
}
@@ -8928,7 +8937,7 @@
"resizeInputBuffer_l() called with shared history and unallocated buffer");
size_t rsmpInFrames = (size_t)maxSharedAudioHistoryMs * mSampleRate / 1000;
// never reduce resampler input buffer size
- if (rsmpInFrames < mRsmpInFrames) {
+ if (rsmpInFrames <= mRsmpInFrames) {
return;
}
mRsmpInFrames = rsmpInFrames;
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index eee1f2b..16082a9 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1789,6 +1789,7 @@
status_t shareAudioHistory_l(const std::string& sharedAudioPackageName,
audio_session_t sharedSessionId = AUDIO_SESSION_NONE,
int64_t sharedAudioStartMs = -1);
+ void resetAudioHistory_l();
virtual bool isStreamInitialized() {
return !(mInput == nullptr || mInput->stream == nullptr);
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index a6e3c06..d2a30b1 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -2458,7 +2458,7 @@
RecordThread *recordThread = (RecordThread *) thread.get();
priorState = mState;
if (!mSharedAudioPackageName.empty()) {
- recordThread->shareAudioHistory_l("");
+ recordThread->resetAudioHistory_l();
}
recordThread->destroyTrack_l(this); // move mState to STOPPED, terminate
}
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index ca8e96c..c73c17d 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -393,12 +393,14 @@
|| outputs.isActiveLocally(
toVolumeSource(AUDIO_STREAM_ACCESSIBILITY),
SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY);
- // - for STRATEGY_SONIFICATION:
+
+ bool ringActiveLocally = outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_RING), 0);
+ // - for STRATEGY_SONIFICATION and ringtone active:
// if SPEAKER was selected, and SPEAKER_SAFE is available, use SPEAKER_SAFE instead
// - for STRATEGY_SONIFICATION_RESPECTFUL:
// if no media is playing on the device, check for mandatory use of "safe" speaker
// when media would have played on speaker, and the safe speaker path is available
- if (strategy == STRATEGY_SONIFICATION
+ if (strategy == STRATEGY_SONIFICATION || ringActiveLocally
|| (strategy == STRATEGY_SONIFICATION_RESPECTFUL && !mediaActiveLocally)) {
devices.replaceDevicesByType(
AUDIO_DEVICE_OUT_SPEAKER,
@@ -506,7 +508,7 @@
switch (commDeviceType) {
case AUDIO_DEVICE_OUT_BLE_HEADSET:
device = availableDevices.getDevice(
- AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
+ AUDIO_DEVICE_IN_BLE_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
break;
case AUDIO_DEVICE_OUT_SPEAKER:
device = availableDevices.getFirstExistingDevice({
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 0c4608a..cc2d8e8 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2531,12 +2531,14 @@
ALOGW("%s input %d client %d already stopped", __FUNCTION__, input, client->portId());
return INVALID_OPERATION;
}
-
+ auto old_source = inputDesc->source();
inputDesc->setClientActive(client, false);
inputDesc->stop();
if (inputDesc->isActive()) {
- setInputDevice(input, getNewInputDevice(inputDesc), false /* force */);
+ auto current_source = inputDesc->source();
+ setInputDevice(input, getNewInputDevice(inputDesc),
+ old_source != current_source /* force */);
} else {
sp<AudioPolicyMix> policyMix = inputDesc->mPolicyMix.promote();
// if input maps to a dynamic policy with an activity listener, notify of state change
@@ -5847,12 +5849,11 @@
// With low-latency playing on speaker, music on WFD, when the first low-latency
// output is stopped, getNewOutputDevices checks for a product strategy
// from the list, as STRATEGY_SONIFICATION comes prior to STRATEGY_MEDIA.
- // If an ALARM, RING or ENFORCED_AUDIBLE stream is supported by the product strategy,
+ // If an ALARM or ENFORCED_AUDIBLE stream is supported by the product strategy,
// devices are returned for STRATEGY_SONIFICATION without checking whether the
// stream is associated to the output descriptor.
if (doGetOutputDevicesForVoice() || outputDesc->isStrategyActive(productStrategy) ||
((hasStreamActive(AUDIO_STREAM_ALARM) ||
- hasStreamActive(AUDIO_STREAM_RING) ||
hasStreamActive(AUDIO_STREAM_ENFORCED_AUDIBLE)) &&
mOutputs.isStrategyActiveOnSameModule(productStrategy, outputDesc))) {
// Retrieval of devices for voice DL is done on primary output profile, cannot
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index b4b6ddf..9987252 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -675,7 +675,7 @@
sp<AudioRecordClient> client = new AudioRecordClient(attr, input, session, portId,
selectedDeviceId, adjAttributionSource,
canCaptureOutput, canCaptureHotword,
- mAudioCommandThread);
+ mOutputCommandThread);
mAudioRecordClients.add(portId, client);
}
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 3deea6b..dc101ff 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -237,10 +237,16 @@
}
}
- //Derive primary rear/front cameras, and filter their charactierstics.
- //This needs to be done after all cameras are enumerated and camera ids are sorted.
+ // Derive primary rear/front cameras, and filter their charactierstics.
+ // This needs to be done after all cameras are enumerated and camera ids are sorted.
if (SessionConfigurationUtils::IS_PERF_CLASS) {
- filterSPerfClassCharacteristics();
+ // Assume internal cameras are advertised from the same
+ // provider. If multiple providers are registered at different time,
+ // and each provider contains multiple internal color cameras, the current
+ // logic may filter the characteristics of more than one front/rear color
+ // cameras.
+ Mutex::Autolock l(mServiceLock);
+ filterSPerfClassCharacteristicsLocked();
}
return OK;
@@ -313,7 +319,7 @@
filterAPI1SystemCameraLocked(mNormalDeviceIds);
}
-void CameraService::filterSPerfClassCharacteristics() {
+void CameraService::filterSPerfClassCharacteristicsLocked() {
// To claim to be S Performance primary cameras, the cameras must be
// backward compatible. So performance class primary camera Ids must be API1
// compatible.
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 1fb7104..9021170 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -945,9 +945,10 @@
void updateCameraNumAndIds();
/**
- * Filter camera characteristics for S Performance class primary cameras
+ * Filter camera characteristics for S Performance class primary cameras.
+ * mServiceLock should be locked.
*/
- void filterSPerfClassCharacteristics();
+ void filterSPerfClassCharacteristicsLocked();
// File descriptor to temp file used for caching previous open
// session dumpsys info.
diff --git a/services/camera/libcameraservice/api2/DepthCompositeStream.cpp b/services/camera/libcameraservice/api2/DepthCompositeStream.cpp
index 19b54e0..a66a592 100644
--- a/services/camera/libcameraservice/api2/DepthCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/DepthCompositeStream.cpp
@@ -42,17 +42,29 @@
mDepthBufferAcquired(false),
mBlobBufferAcquired(false),
mProducerListener(new ProducerListener()),
- mMaxJpegSize(-1),
+ mMaxJpegBufferSize(-1),
+ mUHRMaxJpegBufferSize(-1),
mIsLogicalCamera(false) {
if (device != nullptr) {
CameraMetadata staticInfo = device->info();
auto entry = staticInfo.find(ANDROID_JPEG_MAX_SIZE);
if (entry.count > 0) {
- mMaxJpegSize = entry.data.i32[0];
+ mMaxJpegBufferSize = entry.data.i32[0];
} else {
ALOGW("%s: Maximum jpeg size absent from camera characteristics", __FUNCTION__);
}
+ mUHRMaxJpegSize =
+ SessionConfigurationUtils::getMaxJpegResolution(staticInfo,
+ /*ultraHighResolution*/true);
+ mDefaultMaxJpegSize =
+ SessionConfigurationUtils::getMaxJpegResolution(staticInfo,
+ /*isUltraHighResolution*/false);
+
+ mUHRMaxJpegBufferSize =
+ SessionConfigurationUtils::getUHRMaxJpegBufferSize(mUHRMaxJpegSize, mDefaultMaxJpegSize,
+ mMaxJpegBufferSize);
+
entry = staticInfo.find(ANDROID_LENS_INTRINSIC_CALIBRATION);
if (entry.count == 5) {
mIntrinsicCalibration.reserve(5);
@@ -243,13 +255,22 @@
jpegSize = inputFrame.jpegBuffer.width;
}
- size_t maxDepthJpegSize;
- if (mMaxJpegSize > 0) {
- maxDepthJpegSize = mMaxJpegSize;
+ size_t maxDepthJpegBufferSize = 0;
+ if (mMaxJpegBufferSize > 0) {
+ // If this is an ultra high resolution sensor and the input frames size
+ // is > default res jpeg.
+ if (mUHRMaxJpegSize.width != 0 &&
+ inputFrame.jpegBuffer.width * inputFrame.jpegBuffer.height >
+ mDefaultMaxJpegSize.width * mDefaultMaxJpegSize.height) {
+ maxDepthJpegBufferSize = mUHRMaxJpegBufferSize;
+ } else {
+ maxDepthJpegBufferSize = mMaxJpegBufferSize;
+ }
} else {
- maxDepthJpegSize = std::max<size_t> (jpegSize,
+ maxDepthJpegBufferSize = std::max<size_t> (jpegSize,
inputFrame.depthBuffer.width * inputFrame.depthBuffer.height * 3 / 2);
}
+
uint8_t jpegQuality = 100;
auto entry = inputFrame.result.find(ANDROID_JPEG_QUALITY);
if (entry.count > 0) {
@@ -259,7 +280,7 @@
// The final depth photo will consist of the main jpeg buffer, the depth map buffer (also in
// jpeg format) and confidence map (jpeg as well). Assume worst case that all 3 jpeg need
// max jpeg size.
- size_t finalJpegBufferSize = maxDepthJpegSize * 3;
+ size_t finalJpegBufferSize = maxDepthJpegBufferSize * 3;
if ((res = native_window_set_buffers_dimensions(mOutputSurface.get(), finalJpegBufferSize, 1))
!= OK) {
@@ -302,7 +323,7 @@
depthPhoto.mDepthMapStride = inputFrame.depthBuffer.stride;
depthPhoto.mJpegQuality = jpegQuality;
depthPhoto.mIsLogical = mIsLogicalCamera;
- depthPhoto.mMaxJpegSize = maxDepthJpegSize;
+ depthPhoto.mMaxJpegSize = maxDepthJpegBufferSize;
// The camera intrinsic calibration layout is as follows:
// [focalLengthX, focalLengthY, opticalCenterX, opticalCenterY, skew]
if (mIntrinsicCalibration.size() == 5) {
diff --git a/services/camera/libcameraservice/api2/DepthCompositeStream.h b/services/camera/libcameraservice/api2/DepthCompositeStream.h
index a520bbf..c1c75c1 100644
--- a/services/camera/libcameraservice/api2/DepthCompositeStream.h
+++ b/services/camera/libcameraservice/api2/DepthCompositeStream.h
@@ -132,7 +132,12 @@
sp<Surface> mDepthSurface, mBlobSurface, mOutputSurface;
sp<ProducerListener> mProducerListener;
- ssize_t mMaxJpegSize;
+ ssize_t mMaxJpegBufferSize;
+ ssize_t mUHRMaxJpegBufferSize;
+
+ camera3::Size mDefaultMaxJpegSize;
+ camera3::Size mUHRMaxJpegSize;
+
std::vector<std::tuple<size_t, size_t>> mSupportedDepthSizes;
std::vector<std::tuple<size_t, size_t>> mSupportedDepthSizesMaximumResolution;
std::vector<float> mIntrinsicCalibration, mLensDistortion;
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 7045128..4f2b878 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -476,15 +476,16 @@
const hardware::hidl_string& /*fqName*/,
const hardware::hidl_string& name,
bool preexisting) {
+ status_t res = OK;
std::lock_guard<std::mutex> providerLock(mProviderLifecycleLock);
{
std::lock_guard<std::mutex> lock(mInterfaceMutex);
- addProviderLocked(name, preexisting);
+ res = addProviderLocked(name, preexisting);
}
sp<StatusListener> listener = getStatusListener();
- if (nullptr != listener.get()) {
+ if (nullptr != listener.get() && res == OK) {
listener->onNewProviderRegistered();
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index aefc75e..0101c58 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -499,42 +499,6 @@
return gotLock;
}
-camera3::Size Camera3Device::getMaxJpegResolution() const {
- int32_t maxJpegWidth = 0, maxJpegHeight = 0;
- const int STREAM_CONFIGURATION_SIZE = 4;
- const int STREAM_FORMAT_OFFSET = 0;
- const int STREAM_WIDTH_OFFSET = 1;
- const int STREAM_HEIGHT_OFFSET = 2;
- const int STREAM_IS_INPUT_OFFSET = 3;
- bool isHighResolutionSensor =
- camera3::SessionConfigurationUtils::isUltraHighResolutionSensor(mDeviceInfo);
- int32_t scalerSizesTag = isHighResolutionSensor ?
- ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION :
- ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS;
- camera_metadata_ro_entry_t availableStreamConfigs =
- mDeviceInfo.find(scalerSizesTag);
- if (availableStreamConfigs.count == 0 ||
- availableStreamConfigs.count % STREAM_CONFIGURATION_SIZE != 0) {
- return camera3::Size(0, 0);
- }
-
- // Get max jpeg size (area-wise).
- for (size_t i=0; i < availableStreamConfigs.count; i+= STREAM_CONFIGURATION_SIZE) {
- int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
- int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
- int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
- int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
- if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT
- && format == HAL_PIXEL_FORMAT_BLOB &&
- (width * height > maxJpegWidth * maxJpegHeight)) {
- maxJpegWidth = width;
- maxJpegHeight = height;
- }
- }
-
- return camera3::Size(maxJpegWidth, maxJpegHeight);
-}
-
nsecs_t Camera3Device::getMonoToBoottimeOffset() {
// try three times to get the clock offset, choose the one
// with the minimum gap in measurements.
@@ -625,13 +589,26 @@
}
ssize_t Camera3Device::getJpegBufferSize(uint32_t width, uint32_t height) const {
- // Get max jpeg size (area-wise).
- camera3::Size maxJpegResolution = getMaxJpegResolution();
- if (maxJpegResolution.width == 0) {
+ // Get max jpeg size (area-wise) for default sensor pixel mode
+ camera3::Size maxDefaultJpegResolution =
+ SessionConfigurationUtils::getMaxJpegResolution(mDeviceInfo,
+ /*isUltraHighResolutionSensor*/false);
+ // Get max jpeg size (area-wise) for max resolution sensor pixel mode / 0 if
+ // not ultra high res sensor
+ camera3::Size uhrMaxJpegResolution =
+ SessionConfigurationUtils::getMaxJpegResolution(mDeviceInfo,
+ /*isUltraHighResolution*/true);
+ if (maxDefaultJpegResolution.width == 0) {
ALOGE("%s: Camera %s: Can't find valid available jpeg sizes in static metadata!",
__FUNCTION__, mId.string());
return BAD_VALUE;
}
+ bool useMaxSensorPixelModeThreshold = false;
+ if (uhrMaxJpegResolution.width != 0 &&
+ width * height > maxDefaultJpegResolution.width * maxDefaultJpegResolution.height) {
+ // Use the ultra high res max jpeg size and max jpeg buffer size
+ useMaxSensorPixelModeThreshold = true;
+ }
// Get max jpeg buffer size
ssize_t maxJpegBufferSize = 0;
@@ -642,11 +619,19 @@
return BAD_VALUE;
}
maxJpegBufferSize = jpegBufMaxSize.data.i32[0];
+
+ camera3::Size chosenMaxJpegResolution = maxDefaultJpegResolution;
+ if (useMaxSensorPixelModeThreshold) {
+ maxJpegBufferSize =
+ SessionConfigurationUtils::getUHRMaxJpegBufferSize(uhrMaxJpegResolution,
+ maxDefaultJpegResolution, maxJpegBufferSize);
+ chosenMaxJpegResolution = uhrMaxJpegResolution;
+ }
assert(kMinJpegBufferSize < maxJpegBufferSize);
// Calculate final jpeg buffer size for the given resolution.
float scaleFactor = ((float) (width * height)) /
- (maxJpegResolution.width * maxJpegResolution.height);
+ (chosenMaxJpegResolution.width * chosenMaxJpegResolution.height);
ssize_t jpegBufferSize = scaleFactor * (maxJpegBufferSize - kMinJpegBufferSize) +
kMinJpegBufferSize;
if (jpegBufferSize > maxJpegBufferSize) {
@@ -654,7 +639,6 @@
__FUNCTION__, maxJpegBufferSize);
jpegBufferSize = maxJpegBufferSize;
}
-
return jpegBufferSize;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index aeae042..53a696f 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -776,12 +776,6 @@
bool tryLockSpinRightRound(Mutex& lock);
/**
- * Helper function to get the largest Jpeg resolution (in area)
- * Return Size(0, 0) if static metatdata is invalid
- */
- camera3::Size getMaxJpegResolution() const;
-
- /**
* Helper function to get the offset between MONOTONIC and BOOTTIME
* timestamp.
*/
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 225dee9..03b77fc 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -657,17 +657,17 @@
size_t remainingBuffers = (mState == STATE_PREPARING ? mTotalBufferCount :
camera_stream::max_buffers) - mHandoutTotalBufferCount;
mLock.unlock();
- std::unique_lock<std::mutex> batchLock(mBatchLock);
nsecs_t dequeueStart = systemTime(SYSTEM_TIME_MONOTONIC);
- if (mBatchSize == 1) {
+ size_t batchSize = mBatchSize.load();
+ if (batchSize == 1) {
sp<ANativeWindow> anw = consumer;
res = anw->dequeueBuffer(anw.get(), anb, fenceFd);
} else {
+ std::unique_lock<std::mutex> batchLock(mBatchLock);
res = OK;
if (mBatchedBuffers.size() == 0) {
- size_t batchSize = mBatchSize;
if (remainingBuffers == 0) {
ALOGE("%s: cannot get buffer while all buffers are handed out", __FUNCTION__);
return INVALID_OPERATION;
@@ -675,13 +675,17 @@
if (batchSize > remainingBuffers) {
batchSize = remainingBuffers;
}
+ batchLock.unlock();
// Refill batched buffers
- mBatchedBuffers.resize(batchSize);
- res = consumer->dequeueBuffers(&mBatchedBuffers);
+ std::vector<Surface::BatchBuffer> batchedBuffers;
+ batchedBuffers.resize(batchSize);
+ res = consumer->dequeueBuffers(&batchedBuffers);
+ batchLock.lock();
if (res != OK) {
ALOGE("%s: batch dequeueBuffers call failed! %s (%d)",
__FUNCTION__, strerror(-res), res);
- mBatchedBuffers.clear();
+ } else {
+ mBatchedBuffers = std::move(batchedBuffers);
}
}
@@ -692,7 +696,6 @@
mBatchedBuffers.pop_back();
}
}
- batchLock.unlock();
nsecs_t dequeueEnd = systemTime(SYSTEM_TIME_MONOTONIC);
mDequeueBufferLatency.add(dequeueStart, dequeueEnd);
@@ -1092,7 +1095,7 @@
time_t now = time(0);
tm *localTime = localtime(&now);
snprintf(imageFileName, sizeof(imageFileName), "IMG_%4d%02d%02d_%02d%02d%02d_%" PRId64 ".%s",
- 1900 + localTime->tm_year, localTime->tm_mon, localTime->tm_mday,
+ 1900 + localTime->tm_year, localTime->tm_mon + 1, localTime->tm_mday,
localTime->tm_hour, localTime->tm_min, localTime->tm_sec,
timestamp, fileExtension.c_str());
@@ -1129,7 +1132,6 @@
status_t Camera3OutputStream::setBatchSize(size_t batchSize) {
Mutex::Autolock l(mLock);
- std::lock_guard<std::mutex> lock(mBatchLock);
if (batchSize == 0) {
ALOGE("%s: invalid batch size 0", __FUNCTION__);
return BAD_VALUE;
@@ -1145,31 +1147,36 @@
return INVALID_OPERATION;
}
- if (batchSize != mBatchSize) {
- if (mBatchedBuffers.size() != 0) {
- ALOGE("%s: change batch size from %zu to %zu dynamically is not supported",
- __FUNCTION__, mBatchSize, batchSize);
- return INVALID_OPERATION;
- }
-
- if (camera_stream::max_buffers < batchSize) {
- ALOGW("%s: batch size is capped by max_buffers %d", __FUNCTION__,
- camera_stream::max_buffers);
- batchSize = camera_stream::max_buffers;
- }
- mBatchSize = batchSize;
+ if (camera_stream::max_buffers < batchSize) {
+ ALOGW("%s: batch size is capped by max_buffers %d", __FUNCTION__,
+ camera_stream::max_buffers);
+ batchSize = camera_stream::max_buffers;
}
+
+ size_t defaultBatchSize = 1;
+ if (!mBatchSize.compare_exchange_strong(defaultBatchSize, batchSize)) {
+ ALOGE("%s: change batch size from %zu to %zu dynamically is not supported",
+ __FUNCTION__, defaultBatchSize, batchSize);
+ return INVALID_OPERATION;
+ }
+
return OK;
}
void Camera3OutputStream::returnPrefetchedBuffersLocked() {
- std::lock_guard<std::mutex> batchLock(mBatchLock);
- if (mBatchedBuffers.size() != 0) {
- ALOGW("%s: %zu extra prefetched buffers detected. Returning",
- __FUNCTION__, mBatchedBuffers.size());
+ std::vector<Surface::BatchBuffer> batchedBuffers;
- mConsumer->cancelBuffers(mBatchedBuffers);
- mBatchedBuffers.clear();
+ {
+ std::lock_guard<std::mutex> batchLock(mBatchLock);
+ if (mBatchedBuffers.size() != 0) {
+ ALOGW("%s: %zu extra prefetched buffers detected. Returning",
+ __FUNCTION__, mBatchedBuffers.size());
+ batchedBuffers = std::move(mBatchedBuffers);
+ }
+ }
+
+ if (batchedBuffers.size() > 0) {
+ mConsumer->cancelBuffers(batchedBuffers);
}
}
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index 00e4854..ad03b53 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -312,15 +312,14 @@
bool mDropBuffers;
- // Protecting batch states below, must be acquired after mLock
- std::mutex mBatchLock;
// The batch size for buffer operation
- size_t mBatchSize = 1;
+ std::atomic_size_t mBatchSize = 1;
+ // Protecting batch states below, must be acquired after mLock
+ std::mutex mBatchLock;
// Prefetched buffers (ready to be handed to client)
std::vector<Surface::BatchBuffer> mBatchedBuffers;
-
// ---- End of mBatchLock protected scope ----
/**
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
index ed6ee9b..454c05f 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
@@ -36,6 +36,48 @@
bool SessionConfigurationUtils::IS_PERF_CLASS = (PERF_CLASS_LEVEL == SDK_VERSION_S);
+camera3::Size SessionConfigurationUtils::getMaxJpegResolution(const CameraMetadata &metadata,
+ bool ultraHighResolution) {
+ int32_t maxJpegWidth = 0, maxJpegHeight = 0;
+ const int STREAM_CONFIGURATION_SIZE = 4;
+ const int STREAM_FORMAT_OFFSET = 0;
+ const int STREAM_WIDTH_OFFSET = 1;
+ const int STREAM_HEIGHT_OFFSET = 2;
+ const int STREAM_IS_INPUT_OFFSET = 3;
+
+ int32_t scalerSizesTag = ultraHighResolution ?
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION :
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS;
+ camera_metadata_ro_entry_t availableStreamConfigs =
+ metadata.find(scalerSizesTag);
+ if (availableStreamConfigs.count == 0 ||
+ availableStreamConfigs.count % STREAM_CONFIGURATION_SIZE != 0) {
+ return camera3::Size(0, 0);
+ }
+
+ // Get max jpeg size (area-wise).
+ for (size_t i= 0; i < availableStreamConfigs.count; i+= STREAM_CONFIGURATION_SIZE) {
+ int32_t format = availableStreamConfigs.data.i32[i + STREAM_FORMAT_OFFSET];
+ int32_t width = availableStreamConfigs.data.i32[i + STREAM_WIDTH_OFFSET];
+ int32_t height = availableStreamConfigs.data.i32[i + STREAM_HEIGHT_OFFSET];
+ int32_t isInput = availableStreamConfigs.data.i32[i + STREAM_IS_INPUT_OFFSET];
+ if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT
+ && format == HAL_PIXEL_FORMAT_BLOB &&
+ (width * height > maxJpegWidth * maxJpegHeight)) {
+ maxJpegWidth = width;
+ maxJpegHeight = height;
+ }
+ }
+
+ return camera3::Size(maxJpegWidth, maxJpegHeight);
+}
+
+size_t SessionConfigurationUtils::getUHRMaxJpegBufferSize(camera3::Size uhrMaxJpegSize,
+ camera3::Size defaultMaxJpegSize, size_t defaultMaxJpegBufferSize) {
+ return (uhrMaxJpegSize.width * uhrMaxJpegSize.height) /
+ (defaultMaxJpegSize.width * defaultMaxJpegSize.height) * defaultMaxJpegBufferSize;
+}
+
void StreamConfiguration::getStreamConfigurations(
const CameraMetadata &staticInfo, int configuration,
std::unordered_map<int, std::vector<StreamConfiguration>> *scm) {
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
index b4814b6..1fbaa69 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
@@ -71,6 +71,12 @@
class SessionConfigurationUtils {
public:
+ static camera3::Size getMaxJpegResolution(const CameraMetadata &metadata,
+ bool ultraHighResolution);
+
+ static size_t getUHRMaxJpegBufferSize(camera3::Size uhrMaxJpegSize,
+ camera3::Size defaultMaxJpegSize, size_t defaultMaxJpegBufferSize);
+
static int64_t euclidDistSquare(int32_t x0, int32_t y0, int32_t x1, int32_t y1);
// Find the closest dimensions for a given format in available stream configurations with
diff --git a/services/mediametrics/statsd_codec.cpp b/services/mediametrics/statsd_codec.cpp
index 065c594..46cbdc8 100644
--- a/services/mediametrics/statsd_codec.cpp
+++ b/services/mediametrics/statsd_codec.cpp
@@ -34,6 +34,7 @@
#include "cleaner.h"
#include "MediaMetricsService.h"
+#include "StringUtils.h"
#include "frameworks/proto_logging/stats/message/mediametrics_message.pb.h"
#include "iface_statsd.h"
@@ -227,6 +228,7 @@
std::string sessionId;
if (item->getString("android.media.mediacodec.log-session-id", &sessionId)) {
+ sessionId = mediametrics::stringutils::sanitizeLogSessionId(sessionId);
metrics_proto.set_log_session_id(sessionId);
}
AStatsEvent_writeString(event, codec.c_str());
diff --git a/services/mediametrics/statsd_extractor.cpp b/services/mediametrics/statsd_extractor.cpp
index 4ac5621..bcf2e0a 100644
--- a/services/mediametrics/statsd_extractor.cpp
+++ b/services/mediametrics/statsd_extractor.cpp
@@ -32,6 +32,7 @@
#include <statslog.h>
#include "MediaMetricsService.h"
+#include "StringUtils.h"
#include "frameworks/proto_logging/stats/message/mediametrics_message.pb.h"
#include "iface_statsd.h"
@@ -85,6 +86,7 @@
std::string log_session_id;
if (item->getString("android.media.mediaextractor.logSessionId", &log_session_id)) {
+ log_session_id = mediametrics::stringutils::sanitizeLogSessionId(log_session_id);
metrics_proto.set_log_session_id(log_session_id);
}
diff --git a/services/mediametrics/statsd_mediaparser.cpp b/services/mediametrics/statsd_mediaparser.cpp
index af2946b..921b320 100644
--- a/services/mediametrics/statsd_mediaparser.cpp
+++ b/services/mediametrics/statsd_mediaparser.cpp
@@ -31,6 +31,7 @@
#include <statslog.h>
#include "MediaMetricsService.h"
+#include "StringUtils.h"
#include "frameworks/proto_logging/stats/enums/stats/mediametrics/mediametrics.pb.h"
#include "iface_statsd.h"
@@ -80,6 +81,7 @@
std::string logSessionId;
item->getString("android.media.mediaparser.logSessionId", &logSessionId);
+ logSessionId = mediametrics::stringutils::sanitizeLogSessionId(logSessionId);
int result = android::util::stats_write(android::util::MEDIAMETRICS_MEDIAPARSER_REPORTED,
timestamp_nanos,
diff --git a/services/mediametrics/statsd_recorder.cpp b/services/mediametrics/statsd_recorder.cpp
index 1b312b5..b29ad73 100644
--- a/services/mediametrics/statsd_recorder.cpp
+++ b/services/mediametrics/statsd_recorder.cpp
@@ -32,6 +32,7 @@
#include <statslog.h>
#include "MediaMetricsService.h"
+#include "StringUtils.h"
#include "frameworks/proto_logging/stats/message/mediametrics_message.pb.h"
#include "iface_statsd.h"
@@ -58,6 +59,7 @@
// string kRecorderLogSessionId = "android.media.mediarecorder.log-session-id";
std::string log_session_id;
if (item->getString("android.media.mediarecorder.log-session-id", &log_session_id)) {
+ log_session_id = mediametrics::stringutils::sanitizeLogSessionId(log_session_id);
metrics_proto.set_log_session_id(log_session_id);
}
// string kRecorderAudioMime = "android.media.mediarecorder.audio.mime";
diff --git a/services/oboeservice/AAudioServiceEndpointShared.cpp b/services/oboeservice/AAudioServiceEndpointShared.cpp
index 0d453cf..5fbcadb 100644
--- a/services/oboeservice/AAudioServiceEndpointShared.cpp
+++ b/services/oboeservice/AAudioServiceEndpointShared.cpp
@@ -126,9 +126,9 @@
// Prevent this object from getting deleted before the thread has a chance to create
// its strong pointer. Assume the thread will call decStrong().
this->incStrong(nullptr);
- aaudio_result_t result = getStreamInternal()->createThread_l(periodNanos,
- aaudio_endpoint_thread_proc,
- this);
+ aaudio_result_t result = getStreamInternal()->createThread(periodNanos,
+ aaudio_endpoint_thread_proc,
+ this);
if (result != AAUDIO_OK) {
this->decStrong(nullptr); // Because the thread won't do it.
}