Merge "Revert "Camera: Use fully qualified name for camera eviction logic"" into pi-dev
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index fc60fd4..1826cc1 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -37,7 +37,9 @@
#include <media/stagefright/MetaDataUtils.h>
#include <utils/String8.h>
+#include <arpa/inet.h>
#include <inttypes.h>
+#include <vector>
namespace android {
@@ -584,31 +586,15 @@
}
const uint8_t *data = (const uint8_t *)mbuf->data() + mbuf->range_offset();
- bool blockEncrypted = data[0] & 0x1;
- if (blockEncrypted && mbuf->range_length() < 9) {
+ bool encrypted = data[0] & 0x1;
+ bool partitioned = data[0] & 0x2;
+ if (encrypted && mbuf->range_length() < 9) {
// 1-byte signal + 8-byte IV
return ERROR_MALFORMED;
}
MetaDataBase &meta = mbuf->meta_data();
- if (blockEncrypted) {
- /*
- * 0 1 2 3
- * 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
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Signal Byte | |
- * +-+-+-+-+-+-+-+-+ IV |
- * | |
- * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | | |
- * |-+-+-+-+-+-+-+-+ |
- * : Bytes 1..N of encrypted frame :
- * | |
- * | |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
- int32_t plainSizes[] = { 0 };
- int32_t encryptedSizes[] = { static_cast<int32_t>(mbuf->range_length() - 9) };
+ if (encrypted) {
uint8_t ctrCounter[16] = { 0 };
uint32_t type;
const uint8_t *keyId;
@@ -618,9 +604,83 @@
meta.setData(kKeyCryptoKey, 0, keyId, keyIdSize);
memcpy(ctrCounter, data + 1, 8);
meta.setData(kKeyCryptoIV, 0, ctrCounter, 16);
- meta.setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes));
- meta.setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes));
- mbuf->set_range(9, mbuf->range_length() - 9);
+ if (partitioned) {
+ /* 0 1 2 3
+ * 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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Signal Byte | |
+ * +-+-+-+-+-+-+-+-+ IV |
+ * | |
+ * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | | num_partition | Partition 0 offset -> |
+ * |-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
+ * | -> Partition 0 offset | ... |
+ * |-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
+ * | ... | Partition n-1 offset -> |
+ * |-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
+ * | -> Partition n-1 offset | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
+ * | Clear/encrypted sample data |
+ * | |
+ * | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ if (mbuf->range_length() < 10) {
+ return ERROR_MALFORMED;
+ }
+ uint8_t numPartitions = data[9];
+ if (mbuf->range_length() - 10 < numPartitions * sizeof(uint32_t)) {
+ return ERROR_MALFORMED;
+ }
+ std::vector<uint32_t> plainSizes, encryptedSizes;
+ uint32_t prev = 0;
+ uint32_t frameOffset = 10 + numPartitions * sizeof(uint32_t);
+ const uint32_t *partitions = reinterpret_cast<const uint32_t*>(data + 10);
+ for (uint32_t i = 0; i <= numPartitions; ++i) {
+ uint32_t p_i = i < numPartitions
+ ? ntohl(partitions[i])
+ : (mbuf->range_length() - frameOffset);
+ if (p_i < prev) {
+ return ERROR_MALFORMED;
+ }
+ uint32_t size = p_i - prev;
+ prev = p_i;
+ if (i % 2) {
+ encryptedSizes.push_back(size);
+ } else {
+ plainSizes.push_back(size);
+ }
+ }
+ if (plainSizes.size() > encryptedSizes.size()) {
+ encryptedSizes.push_back(0);
+ }
+ uint32_t sizeofPlainSizes = sizeof(uint32_t) * plainSizes.size();
+ uint32_t sizeofEncryptedSizes = sizeof(uint32_t) * encryptedSizes.size();
+ meta.setData(kKeyPlainSizes, 0, plainSizes.data(), sizeofPlainSizes);
+ meta.setData(kKeyEncryptedSizes, 0, encryptedSizes.data(), sizeofEncryptedSizes);
+ mbuf->set_range(frameOffset, mbuf->range_length() - frameOffset);
+ } else {
+ /*
+ * 0 1 2 3
+ * 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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Signal Byte | |
+ * +-+-+-+-+-+-+-+-+ IV |
+ * | |
+ * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | | |
+ * |-+-+-+-+-+-+-+-+ |
+ * : Bytes 1..N of encrypted frame :
+ * | |
+ * | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ int32_t plainSizes[] = { 0 };
+ int32_t encryptedSizes[] = { static_cast<int32_t>(mbuf->range_length() - 9) };
+ meta.setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes));
+ meta.setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes));
+ mbuf->set_range(9, mbuf->range_length() - 9);
+ }
} else {
/*
* 0 1 2 3
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 99f32d5..dad36ec 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -321,8 +321,13 @@
case FOURCC('h', 'e', 'v', '1'):
return MEDIA_MIMETYPE_VIDEO_HEVC;
default:
- CHECK(!"should not be here.");
- return NULL;
+ ALOGW("Unknown fourcc: %c%c%c%c",
+ (fourcc >> 24) & 0xff,
+ (fourcc >> 16) & 0xff,
+ (fourcc >> 8) & 0xff,
+ fourcc & 0xff
+ );
+ return "application/octet-stream";
}
}
diff --git a/media/libaaudio/examples/loopback/src/LoopbackAnalyzer.h b/media/libaaudio/examples/loopback/src/LoopbackAnalyzer.h
index 1e282d1..2623697 100644
--- a/media/libaaudio/examples/loopback/src/LoopbackAnalyzer.h
+++ b/media/libaaudio/examples/loopback/src/LoopbackAnalyzer.h
@@ -684,7 +684,7 @@
}
void printStatus() override {
- printf(" state = %d, glitches = %d,", mState, mGlitchCount);
+ printf(" state = %d, glitches = %3d,", mState, mGlitchCount);
}
double calculateMagnitude(double *phasePtr = NULL) {
diff --git a/media/libaaudio/examples/loopback/src/loopback.cpp b/media/libaaudio/examples/loopback/src/loopback.cpp
index 026ff0f..0ebcdbd 100644
--- a/media/libaaudio/examples/loopback/src/loopback.cpp
+++ b/media/libaaudio/examples/loopback/src/loopback.cpp
@@ -41,19 +41,24 @@
#define NUM_INPUT_CHANNELS 1
#define FILENAME_ALL "/data/loopback_all.wav"
#define FILENAME_ECHOS "/data/loopback_echos.wav"
-#define APP_VERSION "0.1.22"
+#define APP_VERSION "0.2.01"
struct LoopbackData {
AAudioStream *inputStream = nullptr;
int32_t inputFramesMaximum = 0;
- int16_t *inputData = nullptr;
+ int16_t *inputShortData = nullptr;
+ float *inputFloatData = nullptr;
int16_t peakShort = 0;
- float *conversionBuffer = nullptr;
+ aaudio_format_t actualInputFormat = AAUDIO_FORMAT_INVALID;
int32_t actualInputChannelCount = 0;
int32_t actualOutputChannelCount = 0;
int32_t inputBuffersToDiscard = 10;
int32_t minNumFrames = INT32_MAX;
int32_t maxNumFrames = 0;
+ int32_t insufficientReadCount = 0;
+ int32_t insufficientReadFrames = 0;
+ int32_t framesReadTotal = 0;
+ int32_t framesWrittenTotal = 0;
bool isDone = false;
aaudio_result_t inputError = AAUDIO_OK;
@@ -68,7 +73,7 @@
static void convertPcm16ToFloat(const int16_t *source,
float *destination,
int32_t numSamples) {
- const float scaler = 1.0f / 32768.0f;
+ constexpr float scaler = 1.0f / 32768.0f;
for (int i = 0; i < numSamples; i++) {
destination[i] = source[i] * scaler;
}
@@ -78,6 +83,28 @@
// ========================= CALLBACK =================================================
// ====================================================================================
// Callback function that fills the audio output buffer.
+
+static int32_t readFormattedData(LoopbackData *myData, int32_t numFrames) {
+ int32_t framesRead = AAUDIO_ERROR_INVALID_FORMAT;
+ if (myData->actualInputFormat == AAUDIO_FORMAT_PCM_I16) {
+ framesRead = AAudioStream_read(myData->inputStream, myData->inputShortData,
+ numFrames,
+ 0 /* timeoutNanoseconds */);
+ } else if (myData->actualInputFormat == AAUDIO_FORMAT_PCM_FLOAT) {
+ framesRead = AAudioStream_read(myData->inputStream, myData->inputFloatData,
+ numFrames,
+ 0 /* timeoutNanoseconds */);
+ }
+ if (framesRead < 0) {
+ myData->inputError = framesRead;
+ printf("ERROR in read = %d = %s\n", framesRead,
+ AAudio_convertResultToText(framesRead));
+ } else {
+ myData->framesReadTotal += framesRead;
+ }
+ return framesRead;
+}
+
static aaudio_data_callback_result_t MyDataCallbackProc(
AAudioStream *outputStream,
void *userData,
@@ -107,43 +134,58 @@
if (myData->inputBuffersToDiscard > 0) {
// Drain the input.
do {
- framesRead = AAudioStream_read(myData->inputStream, myData->inputData,
- numFrames, 0);
+ framesRead = readFormattedData(myData, numFrames);
if (framesRead < 0) {
- myData->inputError = framesRead;
- printf("ERROR in read = %d", framesRead);
result = AAUDIO_CALLBACK_RESULT_STOP;
} else if (framesRead > 0) {
myData->inputBuffersToDiscard--;
}
- } while(framesRead > 0);
- } else {
- framesRead = AAudioStream_read(myData->inputStream, myData->inputData,
- numFrames, 0);
- if (framesRead < 0) {
- myData->inputError = framesRead;
- printf("ERROR in read = %d", framesRead);
- result = AAUDIO_CALLBACK_RESULT_STOP;
- } else if (framesRead > 0) {
+ } while (framesRead > 0);
- myData->audioRecording.write(myData->inputData,
- myData->actualInputChannelCount,
- framesRead);
+ // Silence the output.
+ int32_t numBytes = numFrames * myData->actualOutputChannelCount * sizeof(float);
+ memset(audioData, 0 /* value */, numBytes);
+
+ } else {
+
+ int64_t inputFramesWritten = AAudioStream_getFramesWritten(myData->inputStream);
+ int64_t inputFramesRead = AAudioStream_getFramesRead(myData->inputStream);
+ int64_t framesAvailable = inputFramesWritten - inputFramesRead;
+ framesRead = readFormattedData(myData, numFrames);
+ if (framesRead < 0) {
+ result = AAUDIO_CALLBACK_RESULT_STOP;
+ } else {
+ if (framesRead < numFrames) {
+ if(framesRead < (int32_t) framesAvailable) {
+ printf("insufficient but numFrames = %d, framesRead = %d, available = %d\n",
+ numFrames, framesRead, (int) framesAvailable);
+ }
+ myData->insufficientReadCount++;
+ myData->insufficientReadFrames += numFrames - framesRead; // deficit
+ }
int32_t numSamples = framesRead * myData->actualInputChannelCount;
- convertPcm16ToFloat(myData->inputData, myData->conversionBuffer, numSamples);
- myData->loopbackProcessor->process(myData->conversionBuffer,
- myData->actualInputChannelCount,
- outputData,
- myData->actualOutputChannelCount,
- framesRead);
+ if (myData->actualInputFormat == AAUDIO_FORMAT_PCM_I16) {
+ convertPcm16ToFloat(myData->inputShortData, myData->inputFloatData, numSamples);
+ }
+ // Save for later.
+ myData->audioRecording.write(myData->inputFloatData,
+ myData->actualInputChannelCount,
+ framesRead);
+ // Analyze the data.
+ myData->loopbackProcessor->process(myData->inputFloatData,
+ myData->actualInputChannelCount,
+ outputData,
+ myData->actualOutputChannelCount,
+ framesRead);
myData->isDone = myData->loopbackProcessor->isDone();
if (myData->isDone) {
result = AAUDIO_CALLBACK_RESULT_STOP;
}
}
}
+ myData->framesWrittenTotal += numFrames;
return result;
}
@@ -161,6 +203,7 @@
printf("Usage: aaudio_loopback [OPTION]...\n\n");
AAudioArgsParser::usage();
printf(" -C{channels} number of input channels\n");
+ printf(" -F{0,1,2} input format, 1=I16, 2=FLOAT\n");
printf(" -g{gain} recirculating loopback gain\n");
printf(" -P{inPerf} set input AAUDIO_PERFORMANCE_MODE*\n");
printf(" n for _NONE\n");
@@ -236,9 +279,10 @@
}
}
float gain = 0.98f / maxSample;
+
for (int32_t i = start; i < end; i++) {
float sample = data[i];
- printf("%5.3f ", sample); // actual value
+ printf("%6d: %7.4f ", i, sample); // actual value
sample *= gain;
printAudioScope(sample);
}
@@ -254,23 +298,22 @@
AAudioSimplePlayer player;
AAudioSimpleRecorder recorder;
LoopbackData loopbackData;
- AAudioStream *outputStream = nullptr;
+ AAudioStream *inputStream = nullptr;
+ AAudioStream *outputStream = nullptr;
aaudio_result_t result = AAUDIO_OK;
- aaudio_sharing_mode_t requestedInputSharingMode = AAUDIO_SHARING_MODE_SHARED;
+ aaudio_sharing_mode_t requestedInputSharingMode = AAUDIO_SHARING_MODE_SHARED;
int requestedInputChannelCount = NUM_INPUT_CHANNELS;
- const aaudio_format_t requestedInputFormat = AAUDIO_FORMAT_PCM_I16;
- const aaudio_format_t requestedOutputFormat = AAUDIO_FORMAT_PCM_FLOAT;
- aaudio_format_t actualInputFormat;
- aaudio_format_t actualOutputFormat;
- aaudio_performance_mode_t inputPerformanceLevel = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
- int32_t actualSampleRate = 0;
+ aaudio_format_t requestedInputFormat = AAUDIO_FORMAT_UNSPECIFIED;
+ const aaudio_format_t requestedOutputFormat = AAUDIO_FORMAT_PCM_FLOAT;
+ aaudio_performance_mode_t inputPerformanceLevel = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
- int testMode = TEST_ECHO_LATENCY;
- double gain = 1.0;
+ aaudio_format_t actualOutputFormat = AAUDIO_FORMAT_INVALID;
+ int32_t actualSampleRate = 0;
+ int written = 0;
- int32_t framesPerBurst = 0;
- float *outputData = NULL;
+ int testMode = TEST_ECHO_LATENCY;
+ double gain = 1.0;
// Make printf print immediately so that debug info is not stuck
// in a buffer if we hang or crash.
@@ -288,6 +331,9 @@
case 'C':
requestedInputChannelCount = atoi(&arg[2]);
break;
+ case 'F':
+ requestedInputFormat = atoi(&arg[2]);
+ break;
case 'g':
gain = atof(&arg[2]);
break;
@@ -353,7 +399,6 @@
exit(1);
}
outputStream = player.getStream();
- argParser.compareWithStream(outputStream);
actualOutputFormat = AAudioStream_getFormat(outputStream);
assert(actualOutputFormat == AAUDIO_FORMAT_PCM_FLOAT);
@@ -362,40 +407,56 @@
loopbackData.audioRecording.allocate(recordingDuration * actualSampleRate);
loopbackData.audioRecording.setSampleRate(actualSampleRate);
- printf("INPUT stream ----------------------------------------\n");
+ argParser.compareWithStream(outputStream);
+
+ printf("INPUT stream ----------------------------------------\n");
// Use different parameters for the input.
argParser.setNumberOfBursts(AAUDIO_UNSPECIFIED);
argParser.setFormat(requestedInputFormat);
argParser.setPerformanceMode(inputPerformanceLevel);
argParser.setChannelCount(requestedInputChannelCount);
argParser.setSharingMode(requestedInputSharingMode);
+
+ // Make sure the input buffer has plenty of capacity.
+ // Extra capacity on input should not increase latency if we keep it drained.
+ int32_t outputBufferCapacity = AAudioStream_getBufferCapacityInFrames(outputStream);
+ int32_t inputBufferCapacity = 2 * outputBufferCapacity;
+ argParser.setBufferCapacity(inputBufferCapacity);
+
result = recorder.open(argParser);
if (result != AAUDIO_OK) {
fprintf(stderr, "ERROR - recorder.open() returned %d\n", result);
goto finish;
}
- loopbackData.inputStream = recorder.getStream();
- argParser.compareWithStream(loopbackData.inputStream);
+ inputStream = loopbackData.inputStream = recorder.getStream();
- // This is the number of frames that are read in one chunk by a DMA controller
- // or a DSP or a mixer.
- framesPerBurst = AAudioStream_getFramesPerBurst(outputStream);
+ {
+ int32_t actualCapacity = AAudioStream_getBufferCapacityInFrames(inputStream);
+ result = AAudioStream_setBufferSizeInFrames(inputStream, actualCapacity);
+ if (result < 0) {
+ fprintf(stderr, "ERROR - AAudioStream_setBufferSizeInFrames() returned %d\n", result);
+ goto finish;
+ } else {}
+ }
- actualInputFormat = AAudioStream_getFormat(outputStream);
- assert(actualInputFormat == AAUDIO_FORMAT_PCM_I16);
+ argParser.compareWithStream(inputStream);
+ // ------- Setup loopbackData -----------------------------
+ loopbackData.actualInputFormat = AAudioStream_getFormat(inputStream);
loopbackData.actualInputChannelCount = recorder.getChannelCount();
loopbackData.actualOutputChannelCount = player.getChannelCount();
// Allocate a buffer for the audio data.
- loopbackData.inputFramesMaximum = 32 * framesPerBurst;
+ loopbackData.inputFramesMaximum = 32 * AAudioStream_getFramesPerBurst(inputStream);
loopbackData.inputBuffersToDiscard = 200;
- loopbackData.inputData = new int16_t[loopbackData.inputFramesMaximum
- * loopbackData.actualInputChannelCount];
- loopbackData.conversionBuffer = new float[loopbackData.inputFramesMaximum *
- loopbackData.actualInputChannelCount];
+ if (loopbackData.actualInputFormat == AAUDIO_FORMAT_PCM_I16) {
+ loopbackData.inputShortData = new int16_t[loopbackData.inputFramesMaximum
+ * loopbackData.actualInputChannelCount]{};
+ }
+ loopbackData.inputFloatData = new float[loopbackData.inputFramesMaximum *
+ loopbackData.actualInputChannelCount]{};
loopbackData.loopbackProcessor->reset();
@@ -430,63 +491,119 @@
printf("%4d: ", i);
loopbackData.loopbackProcessor->printStatus();
- int64_t inputFramesWritten = AAudioStream_getFramesWritten(loopbackData.inputStream);
- int64_t inputFramesRead = AAudioStream_getFramesRead(loopbackData.inputStream);
+ printf(" insf %3d,", (int) loopbackData.insufficientReadCount);
+
+ int64_t inputFramesWritten = AAudioStream_getFramesWritten(inputStream);
+ int64_t inputFramesRead = AAudioStream_getFramesRead(inputStream);
int64_t outputFramesWritten = AAudioStream_getFramesWritten(outputStream);
int64_t outputFramesRead = AAudioStream_getFramesRead(outputStream);
- printf(" INPUT: wr %lld rd %lld state %s, OUTPUT: wr %lld rd %lld state %s, xruns %d\n",
+ static const int textOffset = strlen("AAUDIO_STREAM_STATE_"); // strip this off
+ printf(" INPUT: wr %7lld - rd %7lld = %5lld, state %s, oruns %3d | ",
(long long) inputFramesWritten,
(long long) inputFramesRead,
- AAudio_convertStreamStateToText(AAudioStream_getState(loopbackData.inputStream)),
+ (long long) (inputFramesWritten - inputFramesRead),
+ &AAudio_convertStreamStateToText(
+ AAudioStream_getState(inputStream))[textOffset],
+ AAudioStream_getXRunCount(inputStream));
+
+ printf(" OUTPUT: wr %7lld - rd %7lld = %5lld, state %s, uruns %3d\n",
(long long) outputFramesWritten,
(long long) outputFramesRead,
- AAudio_convertStreamStateToText(AAudioStream_getState(outputStream)),
+ (long long) (outputFramesWritten - outputFramesRead),
+ &AAudio_convertStreamStateToText(
+ AAudioStream_getState(outputStream))[textOffset],
AAudioStream_getXRunCount(outputStream)
);
}
}
+ result = player.stop();
+ if (result != AAUDIO_OK) {
+ printf("ERROR - player.stop() returned %d = %s\n",
+ result, AAudio_convertResultToText(result));
+ goto finish;
+ }
+
+ result = recorder.stop();
+ if (result != AAUDIO_OK) {
+ printf("ERROR - recorder.stop() returned %d = %s\n",
+ result, AAudio_convertResultToText(result));
+ goto finish;
+ }
+
+ printf("input error = %d = %s\n",
+ loopbackData.inputError, AAudio_convertResultToText(loopbackData.inputError));
+
+ if (loopbackData.inputError == AAUDIO_OK) {
+ if (testMode == TEST_SINE_MAGNITUDE) {
+ printAudioGraph(loopbackData.audioRecording, 200);
+ }
+ // Print again so we don't have to scroll past waveform.
+ printf("OUTPUT Stream ----------------------------------------\n");
+ argParser.compareWithStream(outputStream);
+ printf("INPUT Stream ----------------------------------------\n");
+ argParser.compareWithStream(inputStream);
+
+ loopbackData.loopbackProcessor->report();
+ }
+
+ {
+ int32_t framesRead = AAudioStream_getFramesRead(inputStream);
+ int32_t framesWritten = AAudioStream_getFramesWritten(inputStream);
+ printf("Callback Results ---------------------------------------- INPUT\n");
+ printf(" input overruns = %d\n", AAudioStream_getXRunCount(inputStream));
+ printf(" framesWritten = %8d\n", framesWritten);
+ printf(" framesRead = %8d\n", framesRead);
+ printf(" myFramesRead = %8d\n", (int) loopbackData.framesReadTotal);
+ printf(" written - read = %8d\n", (int) (framesWritten - framesRead));
+ printf(" insufficient # = %8d\n", (int) loopbackData.insufficientReadCount);
+ if (loopbackData.insufficientReadCount > 0) {
+ printf(" insufficient frames = %8d\n", (int) loopbackData.insufficientReadFrames);
+ }
+ }
+ {
+ int32_t framesRead = AAudioStream_getFramesRead(outputStream);
+ int32_t framesWritten = AAudioStream_getFramesWritten(outputStream);
+ printf("Callback Results ---------------------------------------- OUTPUT\n");
+ printf(" output underruns = %d\n", AAudioStream_getXRunCount(outputStream));
+ printf(" myFramesWritten = %8d\n", (int) loopbackData.framesWrittenTotal);
+ printf(" framesWritten = %8d\n", framesWritten);
+ printf(" framesRead = %8d\n", framesRead);
+ printf(" min numFrames = %8d\n", (int) loopbackData.minNumFrames);
+ printf(" max numFrames = %8d\n", (int) loopbackData.maxNumFrames);
+ }
+
+ written = loopbackData.loopbackProcessor->save(FILENAME_ECHOS);
+ if (written > 0) {
+ printf("main() wrote %8d mono samples to \"%s\" on Android device\n",
+ written, FILENAME_ECHOS);
+ }
+
+ written = loopbackData.audioRecording.save(FILENAME_ALL);
+ if (written > 0) {
+ printf("main() wrote %8d mono samples to \"%s\" on Android device\n",
+ written, FILENAME_ALL);
+ }
+
if (loopbackData.loopbackProcessor->getResult() < 0) {
- printf("ERROR: Could not get a good loopback signal. Probably because the volume was too low.\n");
- } else {
- printf("input error = %d = %s\n",
- loopbackData.inputError, AAudio_convertResultToText(loopbackData.inputError));
-
- printf("AAudioStream_getXRunCount %d\n", AAudioStream_getXRunCount(outputStream));
- printf("framesRead = %8d\n", (int) AAudioStream_getFramesRead(outputStream));
- printf("framesWritten = %8d\n", (int) AAudioStream_getFramesWritten(outputStream));
- printf("min numFrames = %8d\n", (int) loopbackData.minNumFrames);
- printf("max numFrames = %8d\n", (int) loopbackData.maxNumFrames);
-
- if (loopbackData.inputError == AAUDIO_OK) {
- if (testMode == TEST_SINE_MAGNITUDE) {
- printAudioGraph(loopbackData.audioRecording, 200);
- }
- loopbackData.loopbackProcessor->report();
- }
-
- int written = loopbackData.loopbackProcessor->save(FILENAME_ECHOS);
- if (written > 0) {
- printf("main() wrote %8d mono samples to \"%s\" on Android device\n",
- written, FILENAME_ECHOS);
- }
-
- written = loopbackData.audioRecording.save(FILENAME_ALL);
- if (written > 0) {
- printf("main() wrote %8d mono samples to \"%s\" on Android device\n",
- written, FILENAME_ALL);
- }
+ printf("ERROR: LOOPBACK PROCESSING FAILED. Maybe because the volume was too low.\n");
+ result = loopbackData.loopbackProcessor->getResult();
+ }
+ if (loopbackData.insufficientReadCount > 3) {
+ printf("ERROR: LOOPBACK PROCESSING FAILED. insufficientReadCount too high\n");
+ result = AAUDIO_ERROR_UNAVAILABLE;
}
finish:
player.close();
recorder.close();
- delete[] loopbackData.conversionBuffer;
- delete[] loopbackData.inputData;
- delete[] outputData;
+ delete[] loopbackData.inputFloatData;
+ delete[] loopbackData.inputShortData;
- printf(RESULT_TAG "result = %s\n", AAudio_convertResultToText(result));
- if ((result != AAUDIO_OK)) {
+ printf(RESULT_TAG "result = %d \n", result); // machine readable
+ printf("result is %s\n", AAudio_convertResultToText(result)); // human readable
+ if (result != AAUDIO_OK) {
+ printf("FAILURE\n");
return EXIT_FAILURE;
} else {
printf("SUCCESS\n");
diff --git a/media/libaaudio/src/fifo/FifoBuffer.cpp b/media/libaaudio/src/fifo/FifoBuffer.cpp
index 9b9744e..b09258e 100644
--- a/media/libaaudio/src/fifo/FifoBuffer.cpp
+++ b/media/libaaudio/src/fifo/FifoBuffer.cpp
@@ -22,6 +22,8 @@
//#define LOG_NDEBUG 0
#include <utils/Log.h>
+#include <algorithm>
+
#include "FifoControllerBase.h"
#include "FifoController.h"
#include "FifoControllerIndirect.h"
@@ -85,15 +87,14 @@
wrappingBuffer->data[1] = nullptr;
wrappingBuffer->numFrames[1] = 0;
if (framesAvailable > 0) {
-
uint8_t *source = &mStorage[convertFramesToBytes(startIndex)];
// Does the available data cross the end of the FIFO?
if ((startIndex + framesAvailable) > mFrameCapacity) {
wrappingBuffer->data[0] = source;
- wrappingBuffer->numFrames[0] = mFrameCapacity - startIndex;
+ fifo_frames_t firstFrames = mFrameCapacity - startIndex;
+ wrappingBuffer->numFrames[0] = firstFrames;
wrappingBuffer->data[1] = &mStorage[0];
- wrappingBuffer->numFrames[1] = mFrameCapacity - startIndex;
-
+ wrappingBuffer->numFrames[1] = framesAvailable - firstFrames;
} else {
wrappingBuffer->data[0] = source;
wrappingBuffer->numFrames[0] = framesAvailable;
@@ -102,18 +103,19 @@
wrappingBuffer->data[0] = nullptr;
wrappingBuffer->numFrames[0] = 0;
}
-
}
fifo_frames_t FifoBuffer::getFullDataAvailable(WrappingBuffer *wrappingBuffer) {
- fifo_frames_t framesAvailable = mFifo->getFullFramesAvailable();
+ // The FIFO might be overfull so clip to capacity.
+ fifo_frames_t framesAvailable = std::min(mFifo->getFullFramesAvailable(), mFrameCapacity);
fifo_frames_t startIndex = mFifo->getReadIndex();
fillWrappingBuffer(wrappingBuffer, framesAvailable, startIndex);
return framesAvailable;
}
fifo_frames_t FifoBuffer::getEmptyRoomAvailable(WrappingBuffer *wrappingBuffer) {
- fifo_frames_t framesAvailable = mFifo->getEmptyFramesAvailable();
+ // The FIFO might have underrun so clip to capacity.
+ fifo_frames_t framesAvailable = std::min(mFifo->getEmptyFramesAvailable(), mFrameCapacity);
fifo_frames_t startIndex = mFifo->getWriteIndex();
fillWrappingBuffer(wrappingBuffer, framesAvailable, startIndex);
return framesAvailable;
diff --git a/media/libaudioclient/AudioTrackShared.cpp b/media/libaudioclient/AudioTrackShared.cpp
index b4c179d..dced3c4 100644
--- a/media/libaudioclient/AudioTrackShared.cpp
+++ b/media/libaudioclient/AudioTrackShared.cpp
@@ -725,12 +725,13 @@
const size_t mask = overflowBit - 1;
int32_t newRear = (rear & ~mask) | (stop & mask);
ssize_t filled = newRear - front;
- if (filled < 0) {
+ // overflowBit is unsigned, so cast to signed for comparison.
+ if (filled >= (ssize_t)overflowBit) {
// front and rear offsets span the overflow bit of the p2 mask
- // so rebasing newrear.
+ // so rebasing newRear on the rear offset is off by the overflow bit.
ALOGV("stop wrap: filled %zx >= overflowBit %zx", filled, overflowBit);
- newRear += overflowBit;
- filled += overflowBit;
+ newRear -= overflowBit;
+ filled -= overflowBit;
}
if (0 <= filled && (size_t) filled <= mFrameCount) {
// we're stopped, return the stop level as newRear
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 3bbba49..ad81f04 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -6777,9 +6777,14 @@
sp<RefBase> obj;
CHECK(msg->findObject("input-surface", &obj));
+ if (obj == NULL) {
+ ALOGE("[%s] NULL input surface", mCodec->mComponentName.c_str());
+ mCodec->mCallback->onInputSurfaceDeclined(BAD_VALUE);
+ return;
+ }
+
sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get());
mCodec->mGraphicBufferSource = surface->getBufferSource();
-
status_t err = setupInputSurface();
if (err == OK) {
@@ -7610,8 +7615,10 @@
config->param[paramIndex].bSet =
(OMX_BOOL)params->findString(existingKey->second.c_str(), &value);
if (config->param[paramIndex].bSet) {
- strncpy((char *)config->param[paramIndex].cString, value.c_str(),
- sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE::cString));
+ size_t dstSize = sizeof(config->param[paramIndex].cString);
+ strncpy((char *)config->param[paramIndex].cString, value.c_str(), dstSize - 1);
+ // null terminate value
+ config->param[paramIndex].cString[dstSize - 1] = '\0';
}
break;
}
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 949b570..3c4f500 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -3388,8 +3388,7 @@
// They would both traverse the directory, but the result would simply be
// failures at unlink() which are ignored. It's also unlikely since
// normally dumpsys is only done by bugreport or from the command line.
- char teePath[32+256];
- strcpy(teePath, "/data/misc/audioserver");
+ char teePath[PATH_MAX] = "/data/misc/audioserver";
size_t teePathLen = strlen(teePath);
DIR *dir = opendir(teePath);
teePath[teePathLen++] = '/';
@@ -3399,27 +3398,19 @@
struct Entry entries[TEE_MAX_SORT];
size_t entryCount = 0;
while (entryCount < TEE_MAX_SORT) {
- struct dirent de;
- struct dirent *result = NULL;
- int rc = readdir_r(dir, &de, &result);
- if (rc != 0) {
- ALOGW("readdir_r failed %d", rc);
- break;
- }
- if (result == NULL) {
- break;
- }
- if (result != &de) {
- ALOGW("readdir_r returned unexpected result %p != %p", result, &de);
+ errno = 0; // clear errno before readdir() to track potential errors.
+ const struct dirent *result = readdir(dir);
+ if (result == nullptr) {
+ ALOGW_IF(errno != 0, "tee readdir() failure %s", strerror(errno));
break;
}
// ignore non .wav file entries
- size_t nameLen = strlen(de.d_name);
+ const size_t nameLen = strlen(result->d_name);
if (nameLen <= 4 || nameLen >= TEE_MAX_FILENAME ||
- strcmp(&de.d_name[nameLen - 4], ".wav")) {
+ strcmp(&result->d_name[nameLen - 4], ".wav")) {
continue;
}
- strcpy(entries[entryCount++].mFileName, de.d_name);
+ (void)audio_utils_strlcpy(entries[entryCount++].mFileName, result->d_name);
}
(void) closedir(dir);
if (entryCount > TEE_MAX_KEEP) {
@@ -3490,8 +3481,13 @@
// FIXME not big-endian safe
write(teeFd, &temp, sizeof(temp));
close(teeFd);
- if (fd >= 0) {
- dprintf(fd, "tee copied to %s\n", teePath);
+ // TODO Should create file with temporary name and then rename to final if non-empty.
+ if (total > 0) {
+ if (fd >= 0) {
+ dprintf(fd, "tee copied to %s\n", teePath);
+ }
+ } else {
+ unlink(teePath);
}
} else {
if (fd >= 0) {
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 1fa9e37..20de97c 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -7898,7 +7898,9 @@
mSessionId(AUDIO_SESSION_NONE),
mDeviceId(AUDIO_PORT_HANDLE_NONE), mPortId(AUDIO_PORT_HANDLE_NONE),
mHalStream(stream), mHalDevice(hwDev->hwDevice()), mAudioHwDev(hwDev),
- mActiveTracks(&this->mLocalLog), mNoCallbackWarningCount(0)
+ mActiveTracks(&this->mLocalLog),
+ mHalVolFloat(-1.0f), // Initialize to illegal value so it always gets set properly later.
+ mNoCallbackWarningCount(0)
{
mStandby = true;
readHalParameters_l();
@@ -8065,7 +8067,10 @@
return PERMISSION_DENIED;
}
- if (!isOutput() && !silenced) {
+ if (isOutput()) {
+ // force volume update when a new track is added
+ mHalVolFloat = -1.0f;
+ } else if (!silenced) {
for (const sp<MmapTrack> &track : mActiveTracks) {
if (track->isSilenced_l() && track->uid() != client.clientUid)
track->invalidate();
@@ -8620,7 +8625,6 @@
mStreamType(AUDIO_STREAM_MUSIC),
mStreamVolume(1.0),
mStreamMute(false),
- mHalVolFloat(-1.0f), // Initialize to illegal value so it always gets set properly later.
mOutput(output)
{
snprintf(mThreadName, kThreadNameLength, "AudioMmapOut_%X", id);
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index bc4a534..28d4482 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1641,6 +1641,7 @@
sp<DeviceHalInterface> mHalDevice;
AudioHwDevice* const mAudioHwDev;
ActiveTracks<MmapTrack> mActiveTracks;
+ float mHalVolFloat;
int32_t mNoCallbackWarningCount;
static constexpr int32_t kMaxNoCallbackWarnings = 5;
@@ -1692,7 +1693,6 @@
float mStreamVolume;
bool mMasterMute;
bool mStreamMute;
- float mHalVolFloat;
AudioStreamOut* mOutput;
};
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index a54a71f..bb00c3f 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -26,7 +26,8 @@
#define AUDIO_POLICY_XML_CONFIG_FILE_PATH_MAX_LENGTH 128
#define AUDIO_POLICY_XML_CONFIG_FILE_NAME "audio_policy_configuration.xml"
-#define AUDIO_POLICY_A2DP_OFFLOAD_XML_CONFIG_FILE_NAME "audio_policy_a2dp_offload_configuration.xml"
+#define AUDIO_POLICY_A2DP_OFFLOAD_DISABLED_XML_CONFIG_FILE_NAME \
+ "audio_policy_configuration_a2dp_offload_disabled.xml"
#include <inttypes.h>
#include <math.h>
@@ -589,6 +590,16 @@
setOutputDevice(mPrimaryOutput, rxDevice, force, 0);
}
}
+
+ // reevaluate routing on all outputs in case tracks have been started during the call
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
+ audio_devices_t newDevice = getNewOutputDevice(desc, true /*fromCache*/);
+ if (state != AUDIO_MODE_IN_CALL || desc != mPrimaryOutput) {
+ setOutputDevice(desc, newDevice, (newDevice != AUDIO_DEVICE_NONE), delayMs);
+ }
+ }
+
// if entering in call state, handle special case of active streams
// pertaining to sonification strategy see handleIncallSonification()
if (isStateInCall(state)) {
@@ -3532,21 +3543,25 @@
static status_t deserializeAudioPolicyXmlConfig(AudioPolicyConfig &config) {
char audioPolicyXmlConfigFile[AUDIO_POLICY_XML_CONFIG_FILE_PATH_MAX_LENGTH];
+ std::vector<const char*> fileNames;
status_t ret;
- for (int i = 0; i < kConfigLocationListSize; i++) {
- PolicySerializer serializer;
- bool use_a2dp_offload_config =
- property_get_bool("persist.bluetooth.a2dp_offload.enable", false);
- snprintf(audioPolicyXmlConfigFile,
- sizeof(audioPolicyXmlConfigFile),
- "%s/%s",
- kConfigLocationList[i],
- use_a2dp_offload_config ? AUDIO_POLICY_A2DP_OFFLOAD_XML_CONFIG_FILE_NAME :
- AUDIO_POLICY_XML_CONFIG_FILE_NAME);
- ret = serializer.deserialize(audioPolicyXmlConfigFile, config);
- if (ret == NO_ERROR) {
- break;
+ if (property_get_bool("ro.bluetooth.a2dp_offload.supported", false) &&
+ property_get_bool("persist.bluetooth.a2dp_offload.disabled", false)) {
+ // A2DP offload supported but disabled: try to use special XML file
+ fileNames.push_back(AUDIO_POLICY_A2DP_OFFLOAD_DISABLED_XML_CONFIG_FILE_NAME);
+ }
+ fileNames.push_back(AUDIO_POLICY_XML_CONFIG_FILE_NAME);
+
+ for (const char* fileName : fileNames) {
+ for (int i = 0; i < kConfigLocationListSize; i++) {
+ PolicySerializer serializer;
+ snprintf(audioPolicyXmlConfigFile, sizeof(audioPolicyXmlConfigFile),
+ "%s/%s", kConfigLocationList[i], fileName);
+ ret = serializer.deserialize(audioPolicyXmlConfigFile, config);
+ if (ret == NO_ERROR) {
+ return ret;
+ }
}
}
return ret;