Merge "Clean up AudioTrackThread and AudioRecordThread constructor"
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 793cbf4..e584ffb 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -81,6 +81,7 @@
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libstagefright_xmlparser@1.0.so)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libstagefright_soft_*)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/vndk/libstagefright_soft_*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libaudiopolicyengineconfig*)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/media/bufferpool/2.0/Android.bp b/media/bufferpool/2.0/Android.bp
index cd4e06e..c71ac17 100644
--- a/media/bufferpool/2.0/Android.bp
+++ b/media/bufferpool/2.0/Android.bp
@@ -1,6 +1,9 @@
cc_library {
name: "libstagefright_bufferpool@2.0",
vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
srcs: [
"Accessor.cpp",
"AccessorImpl.cpp",
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.cpp b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
index 2c0a7a0..7045b6a 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,7 +39,7 @@
namespace android {
class C2SoftHevcEnc::IntfImpl : public C2InterfaceHelper {
- public:
+ public:
explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper>& helper)
: C2InterfaceHelper(helper) {
setDerivedInstance(this);
@@ -73,6 +73,7 @@
0u, (uint64_t)C2MemoryUsage::CPU_READ))
.build());
+ // matches size limits in codec library
addParameter(
DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
.withDefault(new C2StreamPictureSizeInfo::input(0u, 320, 240))
@@ -91,6 +92,7 @@
Setter<decltype(*mFrameRate)>::StrictValueWithNoDeps)
.build());
+ // matches limits in codec library
addParameter(
DefineParam(mBitrate, C2_PARAMKEY_BITRATE)
.withDefault(new C2StreamBitrateInfo::output(0u, 64000))
@@ -98,6 +100,7 @@
.withSetter(BitrateSetter)
.build());
+ // matches levels allowed within codec library
addParameter(
DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
.withDefault(new C2StreamProfileLevelInfo::output(
@@ -137,7 +140,7 @@
C2P<C2StreamBitrateInfo::output>& me) {
(void)mayBlock;
C2R res = C2R::Ok();
- if (me.v.value <= 4096) {
+ if (me.v.value < 4096) {
me.set().value = 4096;
}
return res;
@@ -278,7 +281,7 @@
return (uint32_t)c2_max(c2_min(period + 0.5, double(UINT32_MAX)), 1.);
}
- std::shared_ptr<C2StreamPictureSizeInfo::input> getSize_l() const {
+ std::shared_ptr<C2StreamPictureSizeInfo::input> getSize_l() const {
return mSize;
}
std::shared_ptr<C2StreamFrameRateInfo::output> getFrameRate_l() const {
@@ -304,18 +307,21 @@
std::shared_ptr<C2StreamProfileLevelInfo::output> mProfileLevel;
std::shared_ptr<C2StreamSyncFrameIntervalTuning::output> mSyncFramePeriod;
};
+
constexpr char COMPONENT_NAME[] = "c2.android.hevc.encoder";
static size_t GetCPUCoreCount() {
- long cpuCoreCount = 1;
+ long cpuCoreCount = 0;
+
#if defined(_SC_NPROCESSORS_ONLN)
cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
#else
// _SC_NPROC_ONLN must be defined...
cpuCoreCount = sysconf(_SC_NPROC_ONLN);
#endif
- CHECK(cpuCoreCount >= 1);
- ALOGV("Number of CPU cores: %ld", cpuCoreCount);
+
+ if (cpuCoreCount < 1)
+ cpuCoreCount = 1;
return (size_t)cpuCoreCount;
}
@@ -383,7 +389,7 @@
c2_status_t C2SoftHevcEnc::initEncParams() {
mCodecCtx = nullptr;
- mNumCores = MIN(GetCPUCoreCount(), CODEC_MAX_CORES);
+ mNumCores = std::min(GetCPUCoreCount(), (size_t) CODEC_MAX_CORES);
memset(&mEncParams, 0, sizeof(ihevce_static_cfg_params_t));
// default configuration
@@ -397,7 +403,8 @@
mEncParams.s_src_prms.i4_width = mSize->width;
mEncParams.s_src_prms.i4_height = mSize->height;
mEncParams.s_src_prms.i4_frm_rate_denom = 1000;
- mEncParams.s_src_prms.i4_frm_rate_num = mFrameRate->value * mEncParams.s_src_prms.i4_frm_rate_denom;
+ mEncParams.s_src_prms.i4_frm_rate_num =
+ mFrameRate->value * mEncParams.s_src_prms.i4_frm_rate_denom;
mEncParams.s_tgt_lyr_prms.as_tgt_params[0].i4_quality_preset = IHEVCE_QUALITY_P5;
mEncParams.s_tgt_lyr_prms.as_tgt_params[0].ai4_tgt_bitrate[0] =
mBitrate->value;
@@ -470,7 +477,7 @@
const C2GraphicView* const input,
uint64_t timestamp) {
ihevce_static_cfg_params_t* params = &mEncParams;
- memset(ps_encode_ip, 0, sizeof(ihevce_inp_buf_t));
+ memset(ps_encode_ip, 0, sizeof(*ps_encode_ip));
if (!input) {
return C2_OK;
@@ -495,13 +502,14 @@
int32_t uStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
int32_t vStride = layout.planes[C2PlanarLayout::PLANE_V].rowInc;
- uint32_t width = mSize->width;
- uint32_t height = mSize->height;
+ const uint32_t width = mSize->width;
+ const uint32_t height = mSize->height;
- // width and height are always even
- // width and height are always even (as block size is 16x16)
- CHECK_EQ((width & 1u), 0u);
- CHECK_EQ((height & 1u), 0u);
+ // width and height must be even
+ if (width & 1u || height & 1u) {
+ ALOGW("height(%u) and width(%u) must both be even", height, width);
+ return C2_BAD_VALUE;
+ }
size_t yPlaneSize = width * height;
@@ -650,6 +658,7 @@
if (view->error() != C2_OK) {
ALOGE("graphic view map err = %d", view->error());
mSignalledError = true;
+ work->result = C2_CORRUPTED;
return;
}
}
@@ -687,8 +696,8 @@
status = setEncodeArgs(&s_encode_ip, view.get(), timestamp);
if (C2_OK != status) {
- mSignalledError = true;
ALOGE("setEncodeArgs failed : 0x%x", status);
+ mSignalledError = true;
work->result = status;
return;
}
@@ -761,8 +770,9 @@
: mHelper(std::static_pointer_cast<C2ReflectorHelper>(
GetCodec2PlatformComponentStore()->getParamReflector())) {}
- virtual c2_status_t createComponent(
- c2_node_id_t id, std::shared_ptr<C2Component>* const component,
+ c2_status_t createComponent(
+ c2_node_id_t id,
+ std::shared_ptr<C2Component>* const component,
std::function<void(C2Component*)> deleter) override {
*component = std::shared_ptr<C2Component>(
new C2SoftHevcEnc(
@@ -772,8 +782,9 @@
return C2_OK;
}
- virtual c2_status_t createInterface(
- c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
+ c2_status_t createInterface(
+ c2_node_id_t id,
+ std::shared_ptr<C2ComponentInterface>* const interface,
std::function<void(C2ComponentInterface*)> deleter) override {
*interface = std::shared_ptr<C2ComponentInterface>(
new SimpleInterface<C2SoftHevcEnc::IntfImpl>(
@@ -783,7 +794,7 @@
return C2_OK;
}
- virtual ~C2SoftHevcEncFactory() override = default;
+ ~C2SoftHevcEncFactory() override = default;
private:
std::shared_ptr<C2ReflectorHelper> mHelper;
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.h b/media/codec2/components/hevc/C2SoftHevcEnc.h
index c22fea2..9d90b95 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.h
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 The Android Open Source Project
+ * Copyright 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,18 +17,18 @@
#ifndef ANDROID_C2_SOFT_HEVC_ENC_H_
#define ANDROID_C2_SOFT_HEVC_ENC_H_
-#include <map>
-#include <utils/Vector.h>
-#include <media/stagefright/foundation/ColorUtils.h>
#include <SimpleC2Component.h>
+#include <algorithm>
+#include <map>
+#include <media/stagefright/foundation/ColorUtils.h>
+#include <utils/Vector.h>
#include "ihevc_typedefs.h"
namespace android {
-#define MIN(a, b) ((a) < (b)) ? (a) : (b)
/** Get time */
-#define GETTIME(a, b) gettimeofday(a, b);
+#define GETTIME(a, b) gettimeofday(a, b)
/** Compute difference between start and end */
#define TIME_DIFF(start, end, diff) \
@@ -55,7 +55,7 @@
const std::shared_ptr<C2BlockPool>& pool) override;
protected:
- virtual ~C2SoftHevcEnc();
+ ~C2SoftHevcEnc() override;
private:
std::shared_ptr<IntfImpl> mIntf;
diff --git a/media/codec2/components/opus/C2SoftOpusDec.cpp b/media/codec2/components/opus/C2SoftOpusDec.cpp
index 680712e..7dcd53d 100644
--- a/media/codec2/components/opus/C2SoftOpusDec.cpp
+++ b/media/codec2/components/opus/C2SoftOpusDec.cpp
@@ -252,20 +252,25 @@
const uint8_t *data = rView.data() + inOffset;
if (mInputBufferCount < 3) {
if (mInputBufferCount == 0) {
- size_t opusHeadSize = inSize;
+ size_t opusHeadSize = 0;
size_t codecDelayBufSize = 0;
size_t seekPreRollBufSize = 0;
- void *opusHeadBuf = (void *)data;
+ void *opusHeadBuf = NULL;
void *codecDelayBuf = NULL;
void *seekPreRollBuf = NULL;
- GetOpusHeaderBuffers(data, inSize, &opusHeadBuf,
- &opusHeadSize, &codecDelayBuf,
- &codecDelayBufSize, &seekPreRollBuf,
- &seekPreRollBufSize);
+ if (!GetOpusHeaderBuffers(data, inSize, &opusHeadBuf,
+ &opusHeadSize, &codecDelayBuf,
+ &codecDelayBufSize, &seekPreRollBuf,
+ &seekPreRollBufSize)) {
+ ALOGE("%s encountered error in GetOpusHeaderBuffers", __func__);
+ mSignalledError = true;
+ work->result = C2_CORRUPTED;
+ return;
+ }
if (!ParseOpusHeader((uint8_t *)opusHeadBuf, opusHeadSize, &mHeader)) {
- ALOGE("Encountered error while Parsing Opus Header.");
+ ALOGE("%s Encountered error while Parsing Opus Header.", __func__);
mSignalledError = true;
work->result = C2_CORRUPTED;
return;
@@ -304,16 +309,16 @@
return;
}
- if (codecDelayBuf && codecDelayBufSize == 8) {
+ if (codecDelayBuf && codecDelayBufSize == sizeof(uint64_t)) {
uint64_t value;
memcpy(&value, codecDelayBuf, sizeof(uint64_t));
mCodecDelay = ns_to_samples(value, kRate);
mSamplesToDiscard = mCodecDelay;
++mInputBufferCount;
}
- if (seekPreRollBuf && seekPreRollBufSize == 8) {
+ if (seekPreRollBuf && seekPreRollBufSize == sizeof(uint64_t)) {
uint64_t value;
- memcpy(&value, codecDelayBuf, sizeof(uint64_t));
+ memcpy(&value, seekPreRollBuf, sizeof(uint64_t));
mSeekPreRoll = ns_to_samples(value, kRate);
++mInputBufferCount;
}
diff --git a/media/codec2/core/Android.bp b/media/codec2/core/Android.bp
index b723755..a7e8997 100644
--- a/media/codec2/core/Android.bp
+++ b/media/codec2/core/Android.bp
@@ -7,6 +7,9 @@
cc_library_shared {
name: "libcodec2",
vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
srcs: ["C2.cpp"],
diff --git a/media/codec2/hidl/1.0/utils/Android.bp b/media/codec2/hidl/1.0/utils/Android.bp
index d0296a5..f5aa65b 100644
--- a/media/codec2/hidl/1.0/utils/Android.bp
+++ b/media/codec2/hidl/1.0/utils/Android.bp
@@ -3,6 +3,9 @@
cc_library {
name: "libcodec2_hidl@1.0",
vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
defaults: ["hidl_defaults"],
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index e0b1355..ab6a105 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -14,6 +14,9 @@
cc_library_shared {
name: "libcodec2_vndk",
vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
srcs: [
"C2AllocatorIon.cpp",
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index 7239302..a399940 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -119,6 +119,9 @@
const mkvparser::BlockEntry *mBlockEntry;
long mBlockEntryIndex;
+ unsigned long mTrackType;
+ void seekwithoutcue_l(int64_t seekTimeUs, int64_t *actualFrameTimeUs);
+
void advance_l();
BlockIterator(const BlockIterator &);
@@ -290,6 +293,7 @@
mCluster(NULL),
mBlockEntry(NULL),
mBlockEntryIndex(0) {
+ mTrackType = mExtractor->mSegment->GetTracks()->GetTrackByNumber(trackNum)->GetType();
reset();
}
@@ -442,12 +446,14 @@
}
if (!pCues) {
- ALOGE("No Cues in file");
+ ALOGV("No Cues in file,seek without cue data");
+ seekwithoutcue_l(seekTimeUs, actualFrameTimeUs);
return;
}
}
else if (!pSH) {
- ALOGE("No SeekHead");
+ ALOGV("No SeekHead, seek without cue data");
+ seekwithoutcue_l(seekTimeUs, actualFrameTimeUs);
return;
}
@@ -456,7 +462,9 @@
while (!pCues->DoneParsing()) {
pCues->LoadCuePoint();
pCP = pCues->GetLast();
- CHECK(pCP);
+ ALOGV("pCP = %s", pCP == NULL ? "NULL" : "not NULL");
+ if (pCP == NULL)
+ continue;
size_t trackCount = mExtractor->mTracks.size();
for (size_t index = 0; index < trackCount; ++index) {
@@ -494,6 +502,7 @@
// Always *search* based on the video track, but finalize based on mTrackNum
if (!pTP) {
ALOGE("Did not locate the video track for seeking");
+ seekwithoutcue_l(seekTimeUs, actualFrameTimeUs);
return;
}
@@ -537,6 +546,31 @@
return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll;
}
+void BlockIterator::seekwithoutcue_l(int64_t seekTimeUs, int64_t *actualFrameTimeUs) {
+ mCluster = mExtractor->mSegment->FindCluster(seekTimeUs * 1000ll);
+ const long status = mCluster->GetFirst(mBlockEntry);
+ if (status < 0) { // error
+ ALOGE("get last blockenry failed!");
+ mCluster = NULL;
+ return;
+ }
+ mBlockEntryIndex = 0;
+ while (!eos() && ((block()->GetTrackNumber() != mTrackNum) || (blockTimeUs() < seekTimeUs))) {
+ advance_l();
+ }
+
+ // video track will seek to the next key frame.
+ if (mTrackType == 1) {
+ while (!eos() && ((block()->GetTrackNumber() != mTrackNum) ||
+ !mBlockEntry->GetBlock()->IsKey())) {
+ advance_l();
+ }
+ }
+ *actualFrameTimeUs = blockTimeUs();
+ ALOGV("seekTimeUs:%lld, actualFrameTimeUs:%lld, tracknum:%lld",
+ (long long)seekTimeUs, (long long)*actualFrameTimeUs, (long long)mTrackNum);
+}
+
////////////////////////////////////////////////////////////////////////////////
static unsigned U24_AT(const uint8_t *ptr) {
@@ -956,17 +990,56 @@
return;
}
- // from mkvparser::Segment::Load(), but stop at first cluster
- ret = mSegment->ParseHeaders();
- if (ret == 0) {
- long len;
- ret = mSegment->LoadCluster(pos, len);
- if (ret >= 1) {
- // no more clusters
- ret = 0;
+ if (mIsLiveStreaming) {
+ // from mkvparser::Segment::Load(), but stop at first cluster
+ ret = mSegment->ParseHeaders();
+ if (ret == 0) {
+ long len;
+ ret = mSegment->LoadCluster(pos, len);
+ if (ret >= 1) {
+ // no more clusters
+ ret = 0;
+ }
+ } else if (ret > 0) {
+ ret = mkvparser::E_BUFFER_NOT_FULL;
}
- } else if (ret > 0) {
- ret = mkvparser::E_BUFFER_NOT_FULL;
+ } else {
+ ret = mSegment->ParseHeaders();
+ if (ret < 0) {
+ ALOGE("Segment parse header return fail %lld", ret);
+ delete mSegment;
+ mSegment = NULL;
+ return;
+ } else if (ret == 0) {
+ const mkvparser::Cues* mCues = mSegment->GetCues();
+ const mkvparser::SeekHead* mSH = mSegment->GetSeekHead();
+ if ((mCues == NULL) && (mSH != NULL)) {
+ size_t count = mSH->GetCount();
+ const mkvparser::SeekHead::Entry* mEntry;
+ for (size_t index = 0; index < count; index++) {
+ mEntry = mSH->GetEntry(index);
+ if (mEntry->id == 0x0C53BB6B) { // Cues ID
+ long len;
+ long long pos;
+ mSegment->ParseCues(mEntry->pos, pos, len);
+ mCues = mSegment->GetCues();
+ ALOGV("find cue data by seekhead");
+ break;
+ }
+ }
+ }
+
+ if (mCues) {
+ long len;
+ ret = mSegment->LoadCluster(pos, len);
+ ALOGV("has Cue data, Cluster num=%ld", mSegment->GetCount());
+ } else {
+ long status_Load = mSegment->Load();
+ ALOGW("no Cue data,Segment Load status:%ld",status_Load);
+ }
+ } else if (ret > 0) {
+ ret = mkvparser::E_BUFFER_NOT_FULL;
+ }
}
if (ret < 0) {
diff --git a/media/extractors/mp4/AC4Parser.cpp b/media/extractors/mp4/AC4Parser.cpp
index 59a2e9b..13d60c8 100644
--- a/media/extractors/mp4/AC4Parser.cpp
+++ b/media/extractors/mp4/AC4Parser.cpp
@@ -260,7 +260,7 @@
int32_t short_program_id = -1;
if (bitstream_version > 1) {
- if (ac4_dsi_version == 0){
+ if (ac4_dsi_version == 0) {
ALOGE("invalid ac4 dsi");
return false;
}
@@ -295,6 +295,7 @@
bool b_single_substream_group = false;
uint32_t presentation_config = 0, presentation_version = 0;
uint32_t pres_bytes = 0;
+ uint64_t start = 0;
if (ac4_dsi_version == 0) {
CHECK_BITS_LEFT(1 + 5 + 5);
@@ -315,6 +316,8 @@
mBitReader.skipBits(pres_bytes * 8);
continue;
}
+ /* record a marker, less the size of the presentation_config */
+ start = (mDSISize - mBitReader.numBitsLeft()) / 8;
// ac4_presentation_v0_dsi(), ac4_presentation_v1_dsi() and ac4_presentation_v2_dsi()
// all start with a presentation_config of 5 bits
CHECK_BITS_LEFT(5);
@@ -338,9 +341,6 @@
(presentation_config >= NELEM(PresentationConfig) ?
"reserved" : PresentationConfig[presentation_config]));
- /* record a marker, less the size of the presentation_config */
- uint64_t start = (mDSISize - mBitReader.numBitsLeft()) / 8;
-
bool b_add_emdf_substreams = false;
if (!b_single_substream_group && presentation_config == 6) {
b_add_emdf_substreams = true;
@@ -535,14 +535,14 @@
}
break;
}
- CHECK_BITS_LEFT(1 + 1);
- bool b_pre_virtualized = (mBitReader.getBits(1) == 1);
- mPresentations[presentation].mPreVirtualized = b_pre_virtualized;
- b_add_emdf_substreams = (mBitReader.getBits(1) == 1);
- ALOGV("%u: b_pre_virtualized = %s\n", presentation, BOOLSTR(b_pre_virtualized));
- ALOGV("%u: b_add_emdf_substreams = %s\n", presentation,
- BOOLSTR(b_add_emdf_substreams));
}
+ CHECK_BITS_LEFT(1 + 1);
+ bool b_pre_virtualized = (mBitReader.getBits(1) == 1);
+ mPresentations[presentation].mPreVirtualized = b_pre_virtualized;
+ b_add_emdf_substreams = (mBitReader.getBits(1) == 1);
+ ALOGV("%u: b_pre_virtualized = %s\n", presentation, BOOLSTR(b_pre_virtualized));
+ ALOGV("%u: b_add_emdf_substreams = %s\n", presentation,
+ BOOLSTR(b_add_emdf_substreams));
}
if (b_add_emdf_substreams) {
CHECK_BITS_LEFT(7);
@@ -599,10 +599,6 @@
if (ac4_dsi_version == 1) {
uint64_t end = (mDSISize - mBitReader.numBitsLeft()) / 8;
- if (mBitReader.numBitsLeft() % 8 != 0) {
- end += 1;
- }
-
uint64_t presentation_bytes = end - start;
uint64_t skip_bytes = pres_bytes - presentation_bytes;
ALOGV("skipping = %" PRIu64 " bytes", skip_bytes);
@@ -612,7 +608,7 @@
// we should know this or something is probably wrong
// with the bitstream (or we don't support it)
- if (mPresentations[presentation].mChannelMode == -1){
+ if (mPresentations[presentation].mChannelMode == -1) {
ALOGE("could not determing channel mode of presentation %d", presentation);
return false;
}
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index c776c51..4298b57 100755
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -142,6 +142,7 @@
uint8_t *mSrcBuffer;
bool mIsHeif;
+ bool mIsAudio;
sp<ItemTable> mItemTable;
// Start offset from composition time to presentation time.
@@ -4530,6 +4531,7 @@
}
mIsPcm = !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW);
+ mIsAudio = !strncasecmp(mime, "audio/", 6);
if (mIsPcm) {
int32_t numChannels = 0;
@@ -5416,8 +5418,11 @@
findFlags = SampleTable::kFlagBefore;
}
- uint32_t syncSampleIndex;
- if (err == OK) {
+ uint32_t syncSampleIndex = sampleIndex;
+ // assume every audio sample is a sync sample. This works around
+ // seek issues with files that were incorrectly written with an
+ // empty or single-sample stss block for the audio track
+ if (err == OK && !mIsAudio) {
err = mSampleTable->findSyncSampleNear(
sampleIndex, &syncSampleIndex, findFlags);
}
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index cb1517e..8df1921 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -70,70 +70,34 @@
// ---------------------------------------------------------------------------
-static std::string audioFormatTypeString(audio_format_t value) {
- std::string formatType;
- if (FormatConverter::toString(value, formatType)) {
- return formatType;
- }
- char rawbuffer[16]; // room for "%d"
- snprintf(rawbuffer, sizeof(rawbuffer), "%d", value);
- return rawbuffer;
-}
-
-static std::string audioSourceString(audio_source_t value) {
- std::string source;
- if (SourceTypeConverter::toString(value, source)) {
- return source;
- }
- char rawbuffer[16]; // room for "%d"
- snprintf(rawbuffer, sizeof(rawbuffer), "%d", value);
- return rawbuffer;
-}
-
void AudioRecord::MediaMetrics::gather(const AudioRecord *record)
{
- // key for media statistics is defined in the header
- // attrs for media statistics
- // NB: these are matched with public Java API constants defined
- // in frameworks/base/media/java/android/media/AudioRecord.java
- // These must be kept synchronized with the constants there.
- static constexpr char kAudioRecordEncoding[] = "android.media.audiorecord.encoding";
- static constexpr char kAudioRecordSource[] = "android.media.audiorecord.source";
- static constexpr char kAudioRecordLatency[] = "android.media.audiorecord.latency";
- static constexpr char kAudioRecordSampleRate[] = "android.media.audiorecord.samplerate";
- static constexpr char kAudioRecordChannelCount[] = "android.media.audiorecord.channels";
- static constexpr char kAudioRecordCreated[] = "android.media.audiorecord.createdMs";
- static constexpr char kAudioRecordDuration[] = "android.media.audiorecord.durationMs";
- static constexpr char kAudioRecordCount[] = "android.media.audiorecord.n";
- static constexpr char kAudioRecordError[] = "android.media.audiorecord.errcode";
- static constexpr char kAudioRecordErrorFunction[] = "android.media.audiorecord.errfunc";
+#define MM_PREFIX "android.media.audiorecord." // avoid cut-n-paste errors.
- // constructor guarantees mAnalyticsItem is valid
+ // Java API 28 entries, do not change.
+ mAnalyticsItem->setCString(MM_PREFIX "encoding", toString(record->mFormat).c_str());
+ mAnalyticsItem->setCString(MM_PREFIX "source", toString(record->mAttributes.source).c_str());
+ mAnalyticsItem->setInt32(MM_PREFIX "latency", (int32_t)record->mLatency); // bad estimate.
+ mAnalyticsItem->setInt32(MM_PREFIX "samplerate", (int32_t)record->mSampleRate);
+ mAnalyticsItem->setInt32(MM_PREFIX "channels", (int32_t)record->mChannelCount);
- mAnalyticsItem->setInt32(kAudioRecordLatency, record->mLatency);
- mAnalyticsItem->setInt32(kAudioRecordSampleRate, record->mSampleRate);
- mAnalyticsItem->setInt32(kAudioRecordChannelCount, record->mChannelCount);
- mAnalyticsItem->setCString(kAudioRecordEncoding,
- audioFormatTypeString(record->mFormat).c_str());
- mAnalyticsItem->setCString(kAudioRecordSource,
- audioSourceString(record->mAttributes.source).c_str());
+ // Non-API entries, these can change.
+ mAnalyticsItem->setInt32(MM_PREFIX "portId", (int32_t)record->mPortId);
+ mAnalyticsItem->setInt32(MM_PREFIX "frameCount", (int32_t)record->mFrameCount);
+ mAnalyticsItem->setCString(MM_PREFIX "attributes", toString(record->mAttributes).c_str());
+ mAnalyticsItem->setInt64(MM_PREFIX "channelMask", (int64_t)record->mChannelMask);
- // log total duration recording, including anything currently running [and count].
- nsecs_t active = 0;
+ // log total duration recording, including anything currently running.
+ int64_t activeNs = 0;
if (mStartedNs != 0) {
- active = systemTime() - mStartedNs;
+ activeNs = systemTime() - mStartedNs;
}
- mAnalyticsItem->setInt64(kAudioRecordDuration, (mDurationNs + active) / (1000 * 1000));
- mAnalyticsItem->setInt32(kAudioRecordCount, mCount);
-
- // XXX I don't know that this adds a lot of value, long term
- if (mCreatedNs != 0) {
- mAnalyticsItem->setInt64(kAudioRecordCreated, mCreatedNs / (1000 * 1000));
- }
+ mAnalyticsItem->setDouble(MM_PREFIX "durationMs", (mDurationNs + activeNs) * 1e-6);
+ mAnalyticsItem->setInt64(MM_PREFIX "startCount", (int64_t)mCount);
if (mLastError != NO_ERROR) {
- mAnalyticsItem->setInt32(kAudioRecordError, mLastError);
- mAnalyticsItem->setCString(kAudioRecordErrorFunction, mLastErrorFunc.c_str());
+ mAnalyticsItem->setInt32(MM_PREFIX "lastError.code", (int32_t)mLastError);
+ mAnalyticsItem->setCString(MM_PREFIX "lastError.at", mLastErrorFunc.c_str());
}
}
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 60e841c..e59f7e0 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -170,44 +170,8 @@
// ---------------------------------------------------------------------------
-static std::string audioContentTypeString(audio_content_type_t value) {
- std::string contentType;
- if (AudioContentTypeConverter::toString(value, contentType)) {
- return contentType;
- }
- char rawbuffer[16]; // room for "%d"
- snprintf(rawbuffer, sizeof(rawbuffer), "%d", value);
- return rawbuffer;
-}
-
-static std::string audioUsageString(audio_usage_t value) {
- std::string usage;
- if (UsageTypeConverter::toString(value, usage)) {
- return usage;
- }
- char rawbuffer[16]; // room for "%d"
- snprintf(rawbuffer, sizeof(rawbuffer), "%d", value);
- return rawbuffer;
-}
-
void AudioTrack::MediaMetrics::gather(const AudioTrack *track)
{
-
- // key for media statistics is defined in the header
- // attrs for media statistics
- // NB: these are matched with public Java API constants defined
- // in frameworks/base/media/java/android/media/AudioTrack.java
- // These must be kept synchronized with the constants there.
- static constexpr char kAudioTrackStreamType[] = "android.media.audiotrack.streamtype";
- static constexpr char kAudioTrackContentType[] = "android.media.audiotrack.type";
- static constexpr char kAudioTrackUsage[] = "android.media.audiotrack.usage";
- static constexpr char kAudioTrackSampleRate[] = "android.media.audiotrack.samplerate";
- static constexpr char kAudioTrackChannelMask[] = "android.media.audiotrack.channelmask";
-
- // NB: These are not yet exposed as public Java API constants.
- static constexpr char kAudioTrackUnderrunFrames[] = "android.media.audiotrack.underrunframes";
- static constexpr char kAudioTrackStartupGlitch[] = "android.media.audiotrack.glitch.startup";
-
// only if we're in a good state...
// XXX: shall we gather alternative info if failing?
const status_t lstatus = track->initCheck();
@@ -216,28 +180,22 @@
return;
}
- // constructor guarantees mAnalyticsItem is valid
+#define MM_PREFIX "android.media.audiotrack." // avoid cut-n-paste errors.
- const int32_t underrunFrames = track->getUnderrunFrames();
- if (underrunFrames != 0) {
- mAnalyticsItem->setInt32(kAudioTrackUnderrunFrames, underrunFrames);
- }
+ // Java API 28 entries, do not change.
+ mAnalyticsItem->setCString(MM_PREFIX "streamtype", toString(track->streamType()).c_str());
+ mAnalyticsItem->setCString(MM_PREFIX "type",
+ toString(track->mAttributes.content_type).c_str());
+ mAnalyticsItem->setCString(MM_PREFIX "usage", toString(track->mAttributes.usage).c_str());
- if (track->mTimestampStartupGlitchReported) {
- mAnalyticsItem->setInt32(kAudioTrackStartupGlitch, 1);
- }
-
- if (track->mStreamType != -1) {
- // deprecated, but this will tell us who still uses it.
- mAnalyticsItem->setInt32(kAudioTrackStreamType, track->mStreamType);
- }
- // XXX: consider including from mAttributes: source type
- mAnalyticsItem->setCString(kAudioTrackContentType,
- audioContentTypeString(track->mAttributes.content_type).c_str());
- mAnalyticsItem->setCString(kAudioTrackUsage,
- audioUsageString(track->mAttributes.usage).c_str());
- mAnalyticsItem->setInt32(kAudioTrackSampleRate, track->mSampleRate);
- mAnalyticsItem->setInt64(kAudioTrackChannelMask, track->mChannelMask);
+ // Non-API entries, these can change due to a Java string mistake.
+ mAnalyticsItem->setInt32(MM_PREFIX "sampleRate", (int32_t)track->mSampleRate);
+ mAnalyticsItem->setInt64(MM_PREFIX "channelMask", (int64_t)track->mChannelMask);
+ // Non-API entries, these can change.
+ mAnalyticsItem->setInt32(MM_PREFIX "portId", (int32_t)track->mPortId);
+ mAnalyticsItem->setCString(MM_PREFIX "encoding", toString(track->mFormat).c_str());
+ mAnalyticsItem->setInt32(MM_PREFIX "frameCount", (int32_t)track->mFrameCount);
+ mAnalyticsItem->setCString(MM_PREFIX "attributes", toString(track->mAttributes).c_str());
}
// hand the user a snapshot of the metrics.
diff --git a/media/libaudioclient/include/media/AudioMixer.h b/media/libaudioclient/include/media/AudioMixer.h
index 41b425f..783eef3 100644
--- a/media/libaudioclient/include/media/AudioMixer.h
+++ b/media/libaudioclient/include/media/AudioMixer.h
@@ -273,7 +273,7 @@
mPostDownmixReformatBufferProvider.reset(nullptr);
mDownmixerBufferProvider.reset(nullptr);
mReformatBufferProvider.reset(nullptr);
- mAdjustChannelsNonDestructiveBufferProvider.reset(nullptr);
+ mContractChannelsNonDestructiveBufferProvider.reset(nullptr);
mAdjustChannelsBufferProvider.reset(nullptr);
}
@@ -347,8 +347,12 @@
* all pre-mixer track buffer conversions outside the AudioMixer class.
*
* 1) mInputBufferProvider: The AudioTrack buffer provider.
- * 2) mAdjustChannelsBufferProvider: Expend or contracts data
- * 3) mAdjustChannelsNonDestructiveBufferProvider: Non-destructively adjust sample data
+ * 2) mAdjustChannelsBufferProvider: Expands or contracts sample data from one interleaved
+ * channel format to another. Expanded channels are filled with zeros and put at the end
+ * of each audio frame. Contracted channels are copied to the end of the buffer.
+ * 3) mContractChannelsNonDestructiveBufferProvider: Non-destructively contract sample data.
+ * This is currently using at audio-haptic coupled playback to separate audio and haptic
+ * data. Contracted channels could be written to given buffer.
* 4) mReformatBufferProvider: If not NULL, performs the audio reformat to
* match either mMixerInFormat or mDownmixRequiresFormat, if the downmixer
* requires reformat. For example, it may convert floating point input to
@@ -360,9 +364,10 @@
* 7) mTimestretchBufferProvider: Adds timestretching for playback rate
*/
AudioBufferProvider* mInputBufferProvider; // externally provided buffer provider.
- // TODO: combine AdjustChannelsBufferProvider and AdjustChannelsNonDestructiveBufferProvider
+ // TODO: combine mAdjustChannelsBufferProvider and
+ // mContractChannelsNonDestructiveBufferProvider
std::unique_ptr<PassthruBufferProvider> mAdjustChannelsBufferProvider;
- std::unique_ptr<PassthruBufferProvider> mAdjustChannelsNonDestructiveBufferProvider;
+ std::unique_ptr<PassthruBufferProvider> mContractChannelsNonDestructiveBufferProvider;
std::unique_ptr<PassthruBufferProvider> mReformatBufferProvider;
std::unique_ptr<PassthruBufferProvider> mDownmixerBufferProvider;
std::unique_ptr<PassthruBufferProvider> mPostDownmixReformatBufferProvider;
diff --git a/media/libaudioprocessing/AudioMixer.cpp b/media/libaudioprocessing/AudioMixer.cpp
index 2c57db7..f7cc096 100644
--- a/media/libaudioprocessing/AudioMixer.cpp
+++ b/media/libaudioprocessing/AudioMixer.cpp
@@ -408,8 +408,8 @@
void AudioMixer::Track::unprepareForAdjustChannelsNonDestructive()
{
ALOGV("AUDIOMIXER::unprepareForAdjustChannelsNonDestructive");
- if (mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) {
- mAdjustChannelsNonDestructiveBufferProvider.reset(nullptr);
+ if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
+ mContractChannelsNonDestructiveBufferProvider.reset(nullptr);
reconfigureBufferProviders();
}
}
@@ -426,13 +426,13 @@
? (uint8_t*)mainBuffer + frames * audio_bytes_per_frame(
mMixerChannelCount, mMixerFormat)
: NULL;
- mAdjustChannelsNonDestructiveBufferProvider.reset(
- new AdjustChannelsNonDestructiveBufferProvider(
+ mContractChannelsNonDestructiveBufferProvider.reset(
+ new AdjustChannelsBufferProvider(
mFormat,
mAdjustNonDestructiveInChannelCount,
mAdjustNonDestructiveOutChannelCount,
- mKeepContractedChannels ? mMixerFormat : AUDIO_FORMAT_INVALID,
frames,
+ mKeepContractedChannels ? mMixerFormat : AUDIO_FORMAT_INVALID,
buffer));
reconfigureBufferProviders();
}
@@ -441,9 +441,9 @@
void AudioMixer::Track::clearContractedBuffer()
{
- if (mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) {
- static_cast<AdjustChannelsNonDestructiveBufferProvider*>(
- mAdjustChannelsNonDestructiveBufferProvider.get())->clearContractedFrames();
+ if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
+ static_cast<AdjustChannelsBufferProvider*>(
+ mContractChannelsNonDestructiveBufferProvider.get())->clearContractedFrames();
}
}
@@ -455,9 +455,9 @@
mAdjustChannelsBufferProvider->setBufferProvider(bufferProvider);
bufferProvider = mAdjustChannelsBufferProvider.get();
}
- if (mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) {
- mAdjustChannelsNonDestructiveBufferProvider->setBufferProvider(bufferProvider);
- bufferProvider = mAdjustChannelsNonDestructiveBufferProvider.get();
+ if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
+ mContractChannelsNonDestructiveBufferProvider->setBufferProvider(bufferProvider);
+ bufferProvider = mContractChannelsNonDestructiveBufferProvider.get();
}
if (mReformatBufferProvider.get() != nullptr) {
mReformatBufferProvider->setBufferProvider(bufferProvider);
@@ -966,8 +966,8 @@
track->mDownmixerBufferProvider->reset();
} else if (track->mReformatBufferProvider.get() != nullptr) {
track->mReformatBufferProvider->reset();
- } else if (track->mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) {
- track->mAdjustChannelsNonDestructiveBufferProvider->reset();
+ } else if (track->mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
+ track->mContractChannelsNonDestructiveBufferProvider->reset();
} else if (track->mAdjustChannelsBufferProvider.get() != nullptr) {
track->mAdjustChannelsBufferProvider->reset();
}
diff --git a/media/libaudioprocessing/BufferProviders.cpp b/media/libaudioprocessing/BufferProviders.cpp
index b764ccb..21d25e1 100644
--- a/media/libaudioprocessing/BufferProviders.cpp
+++ b/media/libaudioprocessing/BufferProviders.cpp
@@ -627,79 +627,68 @@
}
}
-AdjustChannelsBufferProvider::AdjustChannelsBufferProvider(audio_format_t format,
- size_t inChannelCount, size_t outChannelCount, size_t frameCount) :
+AdjustChannelsBufferProvider::AdjustChannelsBufferProvider(
+ audio_format_t format, size_t inChannelCount, size_t outChannelCount,
+ size_t frameCount, audio_format_t contractedFormat, void* contractedBuffer) :
CopyBufferProvider(
audio_bytes_per_frame(inChannelCount, format),
- audio_bytes_per_frame(outChannelCount, format),
+ audio_bytes_per_frame(std::max(inChannelCount, outChannelCount), format),
frameCount),
mFormat(format),
mInChannelCount(inChannelCount),
mOutChannelCount(outChannelCount),
- mSampleSizeInBytes(audio_bytes_per_sample(format))
-{
- ALOGV("AdjustBufferProvider(%p)(%#x, %zu, %zu, %zu)",
- this, format, inChannelCount, outChannelCount, frameCount);
-}
-
-void AdjustChannelsBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
-{
- adjust_channels(src, mInChannelCount, dst, mOutChannelCount, mSampleSizeInBytes,
- frames * mInChannelCount * mSampleSizeInBytes);
-}
-
-AdjustChannelsNonDestructiveBufferProvider::AdjustChannelsNonDestructiveBufferProvider(
- audio_format_t format, size_t inChannelCount, size_t outChannelCount,
- audio_format_t contractedFormat, size_t contractedFrameCount, void* contractedBuffer) :
- CopyBufferProvider(
- audio_bytes_per_frame(std::max(inChannelCount, outChannelCount), format),
- audio_bytes_per_frame(std::max(inChannelCount, outChannelCount), format),
- contractedFrameCount),
- mFormat(format),
- mInChannelCount(inChannelCount),
- mOutChannelCount(outChannelCount),
mSampleSizeInBytes(audio_bytes_per_sample(format)),
+ mFrameCount(frameCount),
mContractedChannelCount(inChannelCount - outChannelCount),
mContractedFormat(contractedFormat),
- mContractedFrameCount(contractedFrameCount),
mContractedBuffer(contractedBuffer),
mContractedWrittenFrames(0)
{
- ALOGV("AdjustChannelsNonDestructiveBufferProvider(%p)(%#x, %zu, %zu, %#x, %p)",
- this, format, inChannelCount, outChannelCount, contractedFormat, contractedBuffer);
+ ALOGV("AdjustChannelsBufferProvider(%p)(%#x, %zu, %zu, %zu, %#x, %p)", this, format,
+ inChannelCount, outChannelCount, frameCount, contractedFormat, contractedBuffer);
if (mContractedFormat != AUDIO_FORMAT_INVALID && mInChannelCount > mOutChannelCount) {
mContractedFrameSize = audio_bytes_per_frame(mContractedChannelCount, mContractedFormat);
}
}
-status_t AdjustChannelsNonDestructiveBufferProvider::getNextBuffer(
- AudioBufferProvider::Buffer* pBuffer)
+status_t AdjustChannelsBufferProvider::getNextBuffer(AudioBufferProvider::Buffer* pBuffer)
{
- const size_t outFramesLeft = mContractedFrameCount - mContractedWrittenFrames;
- if (outFramesLeft < pBuffer->frameCount) {
- // Restrict the frame count so that we don't write over the size of the output buffer.
- pBuffer->frameCount = outFramesLeft;
+ if (mContractedBuffer != nullptr) {
+ // Restrict frame count only when it is needed to save contracted frames.
+ const size_t outFramesLeft = mFrameCount - mContractedWrittenFrames;
+ if (outFramesLeft < pBuffer->frameCount) {
+ // Restrict the frame count so that we don't write over the size of the output buffer.
+ pBuffer->frameCount = outFramesLeft;
+ }
}
return CopyBufferProvider::getNextBuffer(pBuffer);
}
-void AdjustChannelsNonDestructiveBufferProvider::copyFrames(
- void *dst, const void *src, size_t frames)
+void AdjustChannelsBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
{
- adjust_channels_non_destructive(src, mInChannelCount, dst, mOutChannelCount, mSampleSizeInBytes,
- frames * mInChannelCount * mSampleSizeInBytes);
- if (mContractedFormat != AUDIO_FORMAT_INVALID && mContractedBuffer != NULL
- && mInChannelCount > mOutChannelCount) {
- const size_t contractedIdx = frames * mOutChannelCount * mSampleSizeInBytes;
- memcpy_by_audio_format(
- (uint8_t*)mContractedBuffer + mContractedWrittenFrames * mContractedFrameSize,
- mContractedFormat, (uint8_t*)dst + contractedIdx, mFormat,
- mContractedChannelCount * frames);
- mContractedWrittenFrames += frames;
+ if (mInChannelCount > mOutChannelCount) {
+ // For case multi to mono, adjust_channels has special logic that will mix first two input
+ // channels into a single output channel. In that case, use adjust_channels_non_destructive
+ // to keep only one channel data even when contracting to mono.
+ adjust_channels_non_destructive(src, mInChannelCount, dst, mOutChannelCount,
+ mSampleSizeInBytes, frames * mInChannelCount * mSampleSizeInBytes);
+ if (mContractedFormat != AUDIO_FORMAT_INVALID
+ && mContractedBuffer != nullptr) {
+ const size_t contractedIdx = frames * mOutChannelCount * mSampleSizeInBytes;
+ memcpy_by_audio_format(
+ (uint8_t*) mContractedBuffer + mContractedWrittenFrames * mContractedFrameSize,
+ mContractedFormat, (uint8_t*) dst + contractedIdx, mFormat,
+ mContractedChannelCount * frames);
+ mContractedWrittenFrames += frames;
+ }
+ } else {
+ // Prefer expanding data from the end of each audio frame.
+ adjust_channels(src, mInChannelCount, dst, mOutChannelCount,
+ mSampleSizeInBytes, frames * mInChannelCount * mSampleSizeInBytes);
}
}
-void AdjustChannelsNonDestructiveBufferProvider::reset()
+void AdjustChannelsBufferProvider::reset()
{
mContractedWrittenFrames = 0;
CopyBufferProvider::reset();
diff --git a/media/libeffects/downmix/tests/Android.bp b/media/libeffects/downmix/tests/Android.bp
index e2e7dbd..63afc54 100644
--- a/media/libeffects/downmix/tests/Android.bp
+++ b/media/libeffects/downmix/tests/Android.bp
@@ -24,7 +24,6 @@
],
cflags: [
- "-v",
"-Werror",
"-Wextra",
],
diff --git a/media/libmedia/include/media/BufferProviders.h b/media/libmedia/include/media/BufferProviders.h
index ea41527..b038854 100644
--- a/media/libmedia/include/media/BufferProviders.h
+++ b/media/libmedia/include/media/BufferProviders.h
@@ -218,33 +218,21 @@
bool mAudioPlaybackRateValid; // flag for current parameters validity
};
-// AdjustBufferProvider derives from CopyBufferProvider to adjust sample data.
+// AdjustChannelsBufferProvider derives from CopyBufferProvider to adjust sample data.
// Expands or contracts sample data from one interleaved channel format to another.
-// Expanded channels are filled with zeros and put at the end of each audio frame.
-// Contracted channels are omitted from the end of each audio frame.
+// Extra expanded channels are filled with zeros and put at the end of each audio frame.
+// Contracted channels are copied to the end of the output buffer(storage should be
+// allocated appropriately).
+// Contracted channels could be written to output buffer.
class AdjustChannelsBufferProvider : public CopyBufferProvider {
public:
AdjustChannelsBufferProvider(audio_format_t format, size_t inChannelCount,
- size_t outChannelCount, size_t frameCount);
- //Overrides
- void copyFrames(void *dst, const void *src, size_t frames) override;
-
-protected:
- const audio_format_t mFormat;
- const size_t mInChannelCount;
- const size_t mOutChannelCount;
- const size_t mSampleSizeInBytes;
-};
-
-// AdjustChannelsNonDestructiveBufferProvider derives from CopyBufferProvider to adjust sample data.
-// Expands or contracts sample data from one interleaved channel format to another.
-// Extra expanded channels are interleaved in from the end of the input buffer.
-// Contracted channels are copied to the end of the output buffer.
-// Contracted channels could be written to output buffer.
-class AdjustChannelsNonDestructiveBufferProvider : public CopyBufferProvider {
-public:
- AdjustChannelsNonDestructiveBufferProvider(audio_format_t format, size_t inChannelCount,
- size_t outChannelCount, audio_format_t contractedFormat, size_t contractedFrameCount,
+ size_t outChannelCount, size_t frameCount) : AdjustChannelsBufferProvider(
+ format, inChannelCount, outChannelCount,
+ frameCount, AUDIO_FORMAT_INVALID, nullptr) { }
+ // Contracted data is converted to contractedFormat and put into contractedBuffer.
+ AdjustChannelsBufferProvider(audio_format_t format, size_t inChannelCount,
+ size_t outChannelCount, size_t frameCount, audio_format_t contractedFormat,
void* contractedBuffer);
//Overrides
status_t getNextBuffer(Buffer* pBuffer) override;
@@ -258,9 +246,9 @@
const size_t mInChannelCount;
const size_t mOutChannelCount;
const size_t mSampleSizeInBytes;
+ const size_t mFrameCount;
const size_t mContractedChannelCount;
const audio_format_t mContractedFormat;
- const size_t mContractedFrameCount;
void *mContractedBuffer;
size_t mContractedWrittenFrames;
size_t mContractedFrameSize;
diff --git a/media/libstagefright/AACWriter.cpp b/media/libstagefright/AACWriter.cpp
index 2ea5fcd..9eba7e9 100644
--- a/media/libstagefright/AACWriter.cpp
+++ b/media/libstagefright/AACWriter.cpp
@@ -85,7 +85,7 @@
CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC));
CHECK(meta->findInt32(kKeyChannelCount, &mChannelCount));
CHECK(meta->findInt32(kKeySampleRate, &mSampleRate));
- CHECK(mChannelCount >= 1 && mChannelCount <= 2);
+ CHECK(mChannelCount >= 1 && mChannelCount <= 7);
// Optionally, we want to check whether AACProfile is also set.
if (meta->findInt32(kKeyAACProfile, &mAACProfile)) {
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 2bd7288..d8b825d 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -199,7 +199,6 @@
"libhidlallocatorutils",
"libhidlbase",
"libhidlmemory",
- "libziparchive",
"android.hidl.allocator@1.0",
"android.hardware.cas.native@1.0",
"android.hardware.media.omx@1.0",
diff --git a/media/libstagefright/HevcUtils.cpp b/media/libstagefright/HevcUtils.cpp
index f152a38..0c38f2e 100644
--- a/media/libstagefright/HevcUtils.cpp
+++ b/media/libstagefright/HevcUtils.cpp
@@ -457,8 +457,8 @@
if (numNalus == 0) {
continue;
}
- // array_completeness set to 0.
- header[0] = type;
+ // array_completeness set to 1.
+ header[0] = type | 0x80;
header[1] = (numNalus >> 8) & 0xff;
header[2] = numNalus & 0xff;
header += 3;
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 6259b15..f6ed0f1 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -3128,8 +3128,8 @@
if (!mIsHeic) {
if (mStszTableEntries->count() == 0) {
mFirstSampleTimeRealUs = systemTime() / 1000;
+ mOwner->setStartTimestampUs(timestampUs);
mStartTimestampUs = timestampUs;
- mOwner->setStartTimestampUs(mStartTimestampUs);
previousPausedDurationUs = mStartTimestampUs;
}
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 9c58e05..d4e4000 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -1973,10 +1973,11 @@
case kWhatComponentConfigured:
{
- if (mState == UNINITIALIZED || mState == INITIALIZED) {
- // In case a kWhatError message came in and replied with error,
+ if (mState == RELEASING || mState == UNINITIALIZED || mState == INITIALIZED) {
+ // In case a kWhatError or kWhatRelease message came in and replied,
// we log a warning and ignore.
- ALOGW("configure interrupted by error, current state %d", mState);
+ ALOGW("configure interrupted by error or release, current state %d",
+ mState);
break;
}
CHECK_EQ(mState, CONFIGURING);
@@ -2067,6 +2068,13 @@
case kWhatStartCompleted:
{
+ if (mState == RELEASING || mState == UNINITIALIZED) {
+ // In case a kWhatRelease message came in and replied,
+ // we log a warning and ignore.
+ ALOGW("start interrupted by release, current state %d", mState);
+ break;
+ }
+
CHECK_EQ(mState, STARTING);
if (mIsVideo) {
addResource(
@@ -2632,11 +2640,12 @@
break;
}
- // If we're flushing, or we're stopping but received a release
- // request, post the reply for the pending call first, and consider
- // it done. The reply token will be replaced after this, and we'll
- // no longer be able to reply.
- if (mState == FLUSHING || mState == STOPPING) {
+ // If we're flushing, stopping, configuring or starting but
+ // received a release request, post the reply for the pending call
+ // first, and consider it done. The reply token will be replaced
+ // after this, and we'll no longer be able to reply.
+ if (mState == FLUSHING || mState == STOPPING
+ || mState == CONFIGURING || mState == STARTING) {
(new AMessage)->postReply(mReplyID);
}
diff --git a/media/libstagefright/OggWriter.cpp b/media/libstagefright/OggWriter.cpp
index 5c13983..cb87b55 100644
--- a/media/libstagefright/OggWriter.cpp
+++ b/media/libstagefright/OggWriter.cpp
@@ -295,6 +295,18 @@
mEstimatedSizeBytes, mMaxFileSizeLimitBytes);
break;
}
+
+ int32_t isCodecSpecific;
+ if ((buffer->meta_data().findInt32(kKeyIsCodecConfig, &isCodecSpecific)
+ && isCodecSpecific)
+ || IsOpusHeader((uint8_t*)buffer->data() + buffer->range_offset(),
+ buffer->range_length())) {
+ ALOGV("Drop codec specific info buffer");
+ buffer->release();
+ buffer = nullptr;
+ continue;
+ }
+
int64_t timestampUs;
CHECK(buffer->meta_data().findInt64(kKeyTime, ×tampUs));
if (timestampUs > mEstimatedDurationUs) {
diff --git a/media/libstagefright/foundation/OpusHeader.cpp b/media/libstagefright/foundation/OpusHeader.cpp
index 9faede1..acb9ccf 100644
--- a/media/libstagefright/foundation/OpusHeader.cpp
+++ b/media/libstagefright/foundation/OpusHeader.cpp
@@ -15,9 +15,9 @@
*/
//#define LOG_NDEBUG 0
-#define LOG_TAG "SoftOpus"
-#include <algorithm>
+#define LOG_TAG "OpusHeader"
#include <cstring>
+#include <inttypes.h>
#include <stdint.h>
#include <log/log.h>
@@ -91,6 +91,9 @@
// Parses Opus Header. Header spec: http://wiki.xiph.org/OggOpus#ID_Header
bool ParseOpusHeader(const uint8_t* data, size_t data_size, OpusHeader* header) {
+ if (data == NULL) {
+ return false;
+ }
if (data_size < kOpusHeaderSize) {
ALOGV("Header size is too small.");
return false;
@@ -183,53 +186,88 @@
ALOGD("Buffer not large enough to hold unified OPUS CSD");
return -1;
}
+ int headerLen = 0;
- int headerLen = WriteOpusHeader(header, inputSampleRate, output,
+ // Add opus header
+ /*
+ Following is the CSD syntax for signalling OpusHeader
+ (http://wiki.xiph.org/OggOpus#ID_Header)
+
+ Marker (8 bytes) | Length (8 bytes) | OpusHeader
+
+ Markers supported:
+ AOPUS_CSD_OPUS_HEADER_MARKER - Signals Opus Header
+
+ Length should be a value within AOPUS_OPUSHEAD_MINSIZE and AOPUS_OPUSHEAD_MAXSIZE.
+ */
+
+ memcpy(output + headerLen, AOPUS_CSD_OPUS_HEADER_MARKER, AOPUS_MARKER_SIZE);
+ headerLen += AOPUS_MARKER_SIZE;
+
+ // Place holder for opusHeader Size
+ headerLen += AOPUS_LENGTH_SIZE;
+
+ int headerSize = WriteOpusHeader(header, inputSampleRate, output + headerLen,
outputSize);
- if (headerLen < 0) {
- ALOGD("WriteOpusHeader failed");
+ if (headerSize < 0) {
+ ALOGD("%s: WriteOpusHeader failed", __func__);
return -1;
}
- if (headerLen >= (outputSize - 2 * AOPUS_TOTAL_CSD_SIZE)) {
- ALOGD("Buffer not large enough to hold codec delay and seek pre roll");
- return -1;
- }
+ headerLen += headerSize;
- uint64_t length = AOPUS_LENGTH;
+ // Update opus headerSize after AOPUS_CSD_OPUS_HEADER_MARKER
+ uint64_t length = headerSize;
+ memcpy(output + AOPUS_MARKER_SIZE, &length, AOPUS_LENGTH_SIZE);
/*
Following is the CSD syntax for signalling codec delay and
seek pre-roll which is to be appended after OpusHeader
- Marker (8 bytes) | Length (8 bytes) | Samples (8 bytes)
+ Marker (8 bytes) | Length (8 bytes) | Samples in ns (8 bytes)
Markers supported:
- AOPUSDLY - Signals Codec Delay
- AOPUSPRL - Signals seek pre roll
+ AOPUS_CSD_CODEC_DELAY_MARKER - codec delay as samples in ns, represented in 8 bytes
+ AOPUS_CSD_SEEK_PREROLL_MARKER - preroll adjustment as samples in ns, represented in 8 bytes
- Length should be 8.
*/
-
+ length = sizeof(codecDelay);
+ if (headerLen > (outputSize - AOPUS_MARKER_SIZE - AOPUS_LENGTH_SIZE - length)) {
+ ALOGD("Buffer not large enough to hold codec delay");
+ return -1;
+ }
// Add codec delay
memcpy(output + headerLen, AOPUS_CSD_CODEC_DELAY_MARKER, AOPUS_MARKER_SIZE);
headerLen += AOPUS_MARKER_SIZE;
memcpy(output + headerLen, &length, AOPUS_LENGTH_SIZE);
headerLen += AOPUS_LENGTH_SIZE;
- memcpy(output + headerLen, &codecDelay, AOPUS_CSD_SIZE);
- headerLen += AOPUS_CSD_SIZE;
+ memcpy(output + headerLen, &codecDelay, length);
+ headerLen += length;
+ length = sizeof(seekPreRoll);
+ if (headerLen > (outputSize - AOPUS_MARKER_SIZE - AOPUS_LENGTH_SIZE - length)) {
+ ALOGD("Buffer not large enough to hold seek pre roll");
+ return -1;
+ }
// Add skip pre roll
memcpy(output + headerLen, AOPUS_CSD_SEEK_PREROLL_MARKER, AOPUS_MARKER_SIZE);
headerLen += AOPUS_MARKER_SIZE;
memcpy(output + headerLen, &length, AOPUS_LENGTH_SIZE);
headerLen += AOPUS_LENGTH_SIZE;
- memcpy(output + headerLen, &seekPreRoll, AOPUS_CSD_SIZE);
- headerLen += AOPUS_CSD_SIZE;
+ memcpy(output + headerLen, &seekPreRoll, length);
+ headerLen += length;
return headerLen;
}
-void GetOpusHeaderBuffers(const uint8_t *data, size_t data_size,
+bool IsOpusHeader(const uint8_t *data, size_t data_size) {
+ if (data_size < AOPUS_MARKER_SIZE) {
+ return false;
+ }
+
+ return !memcmp(data, AOPUS_CSD_OPUS_HEADER_MARKER, AOPUS_MARKER_SIZE);
+}
+
+bool GetOpusHeaderBuffers(const uint8_t *data, size_t data_size,
void **opusHeadBuf, size_t *opusHeadSize,
void **codecDelayBuf, size_t *codecDelaySize,
void **seekPreRollBuf, size_t *seekPreRollSize) {
@@ -237,26 +275,77 @@
*codecDelaySize = 0;
*seekPreRollBuf = NULL;
*seekPreRollSize = 0;
- *opusHeadBuf = (void *)data;
- *opusHeadSize = data_size;
- if (data_size >= AOPUS_UNIFIED_CSD_MINSIZE) {
+ *opusHeadBuf = NULL;
+ *opusHeadSize = 0;
+
+ // AOPUS_MARKER_SIZE is 8 "OpusHead" is of size 8
+ if (data_size < 8)
+ return false;
+
+ // Check if the CSD is in legacy format
+ if (!memcmp("OpusHead", data, 8)) {
+ if (data_size < AOPUS_OPUSHEAD_MINSIZE || data_size > AOPUS_OPUSHEAD_MAXSIZE) {
+ ALOGD("Unexpected size for opusHeadSize %zu", data_size);
+ return false;
+ }
+ *opusHeadBuf = (void *)data;
+ *opusHeadSize = data_size;
+ return true;
+ } else if (memcmp(AOPUS_CSD_MARKER_PREFIX, data, AOPUS_CSD_MARKER_PREFIX_SIZE) == 0) {
size_t i = 0;
- while (i < data_size - AOPUS_TOTAL_CSD_SIZE) {
+ bool found = false;
+ while (i <= data_size - AOPUS_MARKER_SIZE - AOPUS_LENGTH_SIZE) {
uint8_t *csdBuf = (uint8_t *)data + i;
- if (!memcmp(csdBuf, AOPUS_CSD_CODEC_DELAY_MARKER, AOPUS_MARKER_SIZE)) {
- *opusHeadSize = std::min(*opusHeadSize, i);
+ if (!memcmp(csdBuf, AOPUS_CSD_OPUS_HEADER_MARKER, AOPUS_MARKER_SIZE)) {
+ uint64_t value;
+ memcpy(&value, csdBuf + AOPUS_MARKER_SIZE, sizeof(value));
+ if (value < AOPUS_OPUSHEAD_MINSIZE || value > AOPUS_OPUSHEAD_MAXSIZE) {
+ ALOGD("Unexpected size for opusHeadSize %" PRIu64, value);
+ return false;
+ }
+ i += AOPUS_MARKER_SIZE + AOPUS_LENGTH_SIZE + value;
+ if (i > data_size) {
+ ALOGD("Marker signals a header that is larger than input");
+ return false;
+ }
+ *opusHeadBuf = csdBuf + AOPUS_MARKER_SIZE + AOPUS_LENGTH_SIZE;
+ *opusHeadSize = value;
+ found = true;
+ } else if (!memcmp(csdBuf, AOPUS_CSD_CODEC_DELAY_MARKER, AOPUS_MARKER_SIZE)) {
+ uint64_t value;
+ memcpy(&value, csdBuf + AOPUS_MARKER_SIZE, sizeof(value));
+ if (value != sizeof(uint64_t)) {
+ ALOGD("Unexpected size for codecDelay %" PRIu64, value);
+ return false;
+ }
+ i += AOPUS_MARKER_SIZE + AOPUS_LENGTH_SIZE + value;
+ if (i > data_size) {
+ ALOGD("Marker signals a header that is larger than input");
+ return false;
+ }
*codecDelayBuf = csdBuf + AOPUS_MARKER_SIZE + AOPUS_LENGTH_SIZE;
- *codecDelaySize = AOPUS_CSD_SIZE;
- i += AOPUS_TOTAL_CSD_SIZE;
+ *codecDelaySize = value;
} else if (!memcmp(csdBuf, AOPUS_CSD_SEEK_PREROLL_MARKER, AOPUS_MARKER_SIZE)) {
- *opusHeadSize = std::min(*opusHeadSize, i);
+ uint64_t value;
+ memcpy(&value, csdBuf + AOPUS_MARKER_SIZE, sizeof(value));
+ if (value != sizeof(uint64_t)) {
+ ALOGD("Unexpected size for seekPreRollSize %" PRIu64, value);
+ return false;
+ }
+ i += AOPUS_MARKER_SIZE + AOPUS_LENGTH_SIZE + value;
+ if (i > data_size) {
+ ALOGD("Marker signals a header that is larger than input");
+ return false;
+ }
*seekPreRollBuf = csdBuf + AOPUS_MARKER_SIZE + AOPUS_LENGTH_SIZE;
- *seekPreRollSize = AOPUS_CSD_SIZE;
- i += AOPUS_TOTAL_CSD_SIZE;
+ *seekPreRollSize = value;
} else {
i++;
}
}
+ return found;
+ } else {
+ return false; // it isn't in either format
}
}
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/OpusHeader.h b/media/libstagefright/foundation/include/media/stagefright/foundation/OpusHeader.h
index 9bffccb..29037af 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/OpusHeader.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/OpusHeader.h
@@ -25,22 +25,37 @@
namespace android {
/* Constants used for delimiting Opus CSD */
-#define AOPUS_CSD_CODEC_DELAY_MARKER "AOPUSDLY"
-#define AOPUS_CSD_SEEK_PREROLL_MARKER "AOPUSPRL"
-#define AOPUS_CSD_SIZE 8
-#define AOPUS_LENGTH 8
+#define AOPUS_CSD_MARKER_PREFIX "AOPUS"
+#define AOPUS_CSD_MARKER_PREFIX_SIZE (sizeof(AOPUS_CSD_MARKER_PREFIX) - 1)
+#define AOPUS_CSD_OPUS_HEADER_MARKER AOPUS_CSD_MARKER_PREFIX "HDR"
+#define AOPUS_CSD_CODEC_DELAY_MARKER AOPUS_CSD_MARKER_PREFIX "DLY"
+#define AOPUS_CSD_SEEK_PREROLL_MARKER AOPUS_CSD_MARKER_PREFIX "PRL"
#define AOPUS_MARKER_SIZE 8
-#define AOPUS_LENGTH_SIZE 8
-#define AOPUS_TOTAL_CSD_SIZE \
- ((AOPUS_MARKER_SIZE) + (AOPUS_LENGTH_SIZE) + (AOPUS_CSD_SIZE))
-#define AOPUS_CSD0_MINSIZE 19
-#define AOPUS_UNIFIED_CSD_MINSIZE \
- ((AOPUS_CSD0_MINSIZE) + 2 * (AOPUS_TOTAL_CSD_SIZE))
+#define AOPUS_LENGTH_SIZE sizeof(uint64_t)
+#define AOPUS_CSD_CODEC_DELAY_SIZE \
+ (AOPUS_MARKER_SIZE) + (AOPUS_LENGTH_SIZE) + sizeof(uint64_t)
+#define AOPUS_CSD_SEEK_PREROLL_SIZE \
+ (AOPUS_MARKER_SIZE) + (AOPUS_LENGTH_SIZE) + sizeof(uint64_t)
-/* CSD0 at max can be 22 bytes + max number of channels (255) */
-#define AOPUS_CSD0_MAXSIZE 277
+/* OpusHead csd minimum size is 19 */
+#define AOPUS_OPUSHEAD_MINSIZE 19
+#define AOPUS_CSD_OPUSHEAD_MINSIZE \
+ (AOPUS_MARKER_SIZE) + (AOPUS_LENGTH_SIZE) + (AOPUS_OPUSHEAD_MINSIZE)
+
+#define AOPUS_UNIFIED_CSD_MINSIZE \
+ ((AOPUS_CSD_OPUSHEAD_MINSIZE) + \
+ (AOPUS_CSD_CODEC_DELAY_SIZE) + \
+ (AOPUS_CSD_SEEK_PREROLL_SIZE))
+
+/* OpusHead csd at max can be AOPUS_CSD_OPUSHEAD_MINSIZE + 2 + max number of channels (255) */
+#define AOPUS_OPUSHEAD_MAXSIZE ((AOPUS_OPUSHEAD_MINSIZE) + 2 + 255)
+#define AOPUS_CSD_OPUSHEAD_MAXSIZE \
+ (AOPUS_MARKER_SIZE) + (AOPUS_LENGTH_SIZE) + (AOPUS_OPUSHEAD_MAXSIZE)
+
#define AOPUS_UNIFIED_CSD_MAXSIZE \
- ((AOPUS_CSD0_MAXSIZE) + 2 * (AOPUS_TOTAL_CSD_SIZE))
+ ((AOPUS_CSD_OPUSHEAD_MAXSIZE) + \
+ (AOPUS_CSD_CODEC_DELAY_SIZE) + \
+ (AOPUS_CSD_SEEK_PREROLL_SIZE))
struct OpusHeader {
int channels;
@@ -54,13 +69,14 @@
bool ParseOpusHeader(const uint8_t* data, size_t data_size, OpusHeader* header);
int WriteOpusHeader(const OpusHeader &header, int input_sample_rate, uint8_t* output, size_t output_size);
-void GetOpusHeaderBuffers(const uint8_t *data, size_t data_size,
+bool GetOpusHeaderBuffers(const uint8_t *data, size_t data_size,
void **opusHeadBuf, size_t *opusHeadSize,
void **codecDelayBuf, size_t *codecDelaySize,
void **seekPreRollBuf, size_t *seekPreRollSize);
int WriteOpusHeaders(const OpusHeader &header, int inputSampleRate,
uint8_t* output, size_t outputSize, uint64_t codecDelay,
uint64_t seekPreRoll);
+bool IsOpusHeader(const uint8_t *data, size_t data_size);
} // namespace android
#endif // OPUS_HEADER_H_
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 91b7587..40980a6 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -32,6 +32,7 @@
libbinder \
libaudioclient \
libmedialogservice \
+ libmediametrics \
libmediautils \
libnbaio \
libnblog \
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 8f181a4..468676a 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -488,6 +488,8 @@
sp<IBinder> binder = IInterface::asBinder(mPowerManager);
binder->unlinkToDeath(mDeathRecipient);
}
+
+ sendStatistics(true /* force */);
}
status_t AudioFlinger::ThreadBase::readyToRun()
@@ -571,6 +573,15 @@
// sendIoConfigEvent_l() must be called with ThreadBase::mLock held
void AudioFlinger::ThreadBase::sendIoConfigEvent_l(audio_io_config_event event, pid_t pid)
{
+ // The audio statistics history is exponentially weighted to forget events
+ // about five or more seconds in the past. In order to have
+ // crisper statistics for mediametrics, we reset the statistics on
+ // an IoConfigEvent, to reflect different properties for a new device.
+ mIoJitterMs.reset();
+ mLatencyMs.reset();
+ mProcessTimeMs.reset();
+ mTimestampVerifier.discontinuity();
+
sp<ConfigEvent> configEvent = (ConfigEvent *)new IoConfigEvent(event, pid);
sendConfigEvent_l(configEvent);
}
@@ -1651,6 +1662,65 @@
mWaitWorkCV.broadcast();
}
+// Call only from threadLoop() or when it is idle.
+// Do not call from high performance code as this may do binder rpc to the MediaMetrics service.
+void AudioFlinger::ThreadBase::sendStatistics(bool force)
+{
+ // Do not log if we have no stats.
+ // We choose the timestamp verifier because it is the most likely item to be present.
+ const int64_t nstats = mTimestampVerifier.getN() - mLastRecordedTimestampVerifierN;
+ if (nstats == 0) {
+ return;
+ }
+
+ // Don't log more frequently than once per 12 hours.
+ // We use BOOTTIME to include suspend time.
+ const int64_t timeNs = systemTime(SYSTEM_TIME_BOOTTIME);
+ const int64_t sinceNs = timeNs - mLastRecordedTimeNs; // ok if mLastRecordedTimeNs = 0
+ if (!force && sinceNs <= 12 * NANOS_PER_HOUR) {
+ return;
+ }
+
+ mLastRecordedTimestampVerifierN = mTimestampVerifier.getN();
+ mLastRecordedTimeNs = timeNs;
+
+ std::unique_ptr<MediaAnalyticsItem> item(MediaAnalyticsItem::create("audiothread"));
+
+#define MM_PREFIX "android.media.audiothread." // avoid cut-n-paste errors.
+
+ // thread configuration
+ item->setInt32(MM_PREFIX "id", (int32_t)mId); // IO handle
+ // item->setInt32(MM_PREFIX "portId", (int32_t)mPortId);
+ item->setCString(MM_PREFIX "type", threadTypeToString(mType));
+ item->setInt32(MM_PREFIX "sampleRate", (int32_t)mSampleRate);
+ item->setInt64(MM_PREFIX "channelMask", (int64_t)mChannelMask);
+ item->setCString(MM_PREFIX "encoding", toString(mFormat).c_str());
+ item->setInt32(MM_PREFIX "frameCount", (int32_t)mFrameCount);
+ item->setCString(MM_PREFIX "outDevice", toString(mOutDevice).c_str());
+ item->setCString(MM_PREFIX "inDevice", toString(mInDevice).c_str());
+
+ // thread statistics
+ if (mIoJitterMs.getN() > 0) {
+ item->setDouble(MM_PREFIX "ioJitterMs.mean", mIoJitterMs.getMean());
+ item->setDouble(MM_PREFIX "ioJitterMs.std", mIoJitterMs.getStdDev());
+ }
+ if (mProcessTimeMs.getN() > 0) {
+ item->setDouble(MM_PREFIX "processTimeMs.mean", mProcessTimeMs.getMean());
+ item->setDouble(MM_PREFIX "processTimeMs.std", mProcessTimeMs.getStdDev());
+ }
+ const auto tsjitter = mTimestampVerifier.getJitterMs();
+ if (tsjitter.getN() > 0) {
+ item->setDouble(MM_PREFIX "timestampJitterMs.mean", tsjitter.getMean());
+ item->setDouble(MM_PREFIX "timestampJitterMs.std", tsjitter.getStdDev());
+ }
+ if (mLatencyMs.getN() > 0) {
+ item->setDouble(MM_PREFIX "latencyMs.mean", mLatencyMs.getMean());
+ item->setDouble(MM_PREFIX "latencyMs.std", mLatencyMs.getStdDev());
+ }
+
+ item->selfrecord();
+}
+
// ----------------------------------------------------------------------------
// Playback
// ----------------------------------------------------------------------------
@@ -3447,6 +3517,7 @@
LOG_AUDIO_STATE();
}
mStandby = true;
+ sendStatistics(false /* force */);
}
if (mActiveTracks.isEmpty() && mConfigEvents.isEmpty()) {
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 1afea08..97aa9f0 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -399,6 +399,9 @@
virtual void dump(int fd, const Vector<String16>& args) = 0;
+ // deliver stats to mediametrics.
+ void sendStatistics(bool force);
+
mutable Mutex mLock;
protected:
@@ -522,6 +525,10 @@
audio_utils::Statistics<double> mProcessTimeMs{0.995 /* alpha */};
audio_utils::Statistics<double> mLatencyMs{0.995 /* alpha */};
+ // Save the last count when we delivered statistics to mediametrics.
+ int64_t mLastRecordedTimestampVerifierN = 0;
+ int64_t mLastRecordedTimeNs = 0; // BOOTTIME to include suspend.
+
bool mIsMsdDevice = false;
// A condition that must be evaluated by the thread loop has changed and
// we must not wait for async write callback in the thread loop before evaluating it
diff --git a/services/audiopolicy/engine/common/Android.bp b/services/audiopolicy/engine/common/Android.bp
index e6ede07..d0775ad 100644
--- a/services/audiopolicy/engine/common/Android.bp
+++ b/services/audiopolicy/engine/common/Android.bp
@@ -17,3 +17,31 @@
host_supported: true,
export_include_dirs: ["include"],
}
+
+cc_library_static {
+ name: "libaudiopolicyengine_common",
+ srcs: [
+ "src/EngineBase.cpp",
+ "src/ProductStrategy.cpp",
+ "src/VolumeCurve.cpp",
+ "src/VolumeGroup.cpp",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+ header_libs: [
+ "libbase_headers",
+ "libaudiopolicycommon",
+ "libaudiopolicyengine_common_headers",
+ "libaudiopolicyengine_interface_headers",
+ ],
+ export_header_lib_headers: [
+ "libaudiopolicyengine_common_headers",
+ ],
+ static_libs: [
+ "libaudiopolicycomponents",
+ "libaudiopolicyengine_config",
+ ],
+}
diff --git a/services/audiopolicy/engine/config/Android.bp b/services/audiopolicy/engine/config/Android.bp
new file mode 100644
index 0000000..6e72f2a
--- /dev/null
+++ b/services/audiopolicy/engine/config/Android.bp
@@ -0,0 +1,31 @@
+cc_library_static {
+ name: "libaudiopolicyengine_config",
+ export_include_dirs: ["include"],
+ include_dirs: [
+ "external/libxml2/include",
+ "external/icu/icu4c/source/common",
+ ],
+ srcs: [
+ "src/EngineConfig.cpp",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+ shared_libs: [
+ "libmedia_helper",
+ "libandroidicu",
+ "libxml2",
+ "libutils",
+ "liblog",
+ "libcutils",
+ ],
+ static_libs: [
+ "libaudiopolicycomponents",
+ ],
+ header_libs: [
+ "libaudio_system_headers",
+ "libaudiopolicycommon",
+ ],
+}
diff --git a/services/audiopolicy/engine/config/Android.mk b/services/audiopolicy/engine/config/Android.mk
deleted file mode 100644
index 0b292a5..0000000
--- a/services/audiopolicy/engine/config/Android.mk
+++ /dev/null
@@ -1,42 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-##################################################################
-# Component build
-##################################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-
-LOCAL_C_INCLUDES := \
- $(LOCAL_EXPORT_C_INCLUDE_DIRS) \
- external/libxml2/include \
- external/icu/icu4c/source/common
-
-LOCAL_SRC_FILES := \
- src/EngineConfig.cpp
-
-LOCAL_CFLAGS += -Wall -Werror -Wextra
-
-LOCAL_SHARED_LIBRARIES := \
- libmedia_helper \
- libandroidicu \
- libxml2 \
- libutils \
- liblog \
- libcutils
-
-LOCAL_STATIC_LIBRARIES := \
- libaudiopolicycomponents
-
-LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-
-LOCAL_MODULE := libaudiopolicyengineconfig
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_HEADER_LIBRARIES := \
- libaudio_system_headers \
- libaudiopolicycommon
-
-include $(BUILD_SHARED_LIBRARY)
-
diff --git a/services/audiopolicy/engineconfigurable/Android.mk b/services/audiopolicy/engineconfigurable/Android.mk
index 4eff6e6..84a4422 100644
--- a/services/audiopolicy/engineconfigurable/Android.mk
+++ b/services/audiopolicy/engineconfigurable/Android.mk
@@ -12,10 +12,6 @@
src/EngineInstance.cpp \
src/Stream.cpp \
src/InputSource.cpp \
- ../engine/common/src/VolumeCurve.cpp \
- ../engine/common/src/VolumeGroup.cpp \
- ../engine/common/src/ProductStrategy.cpp \
- ../engine/common/src/EngineBase.cpp
audio_policy_engine_includes_common := \
frameworks/av/services/audiopolicy/engineconfigurable/include \
@@ -37,7 +33,6 @@
LOCAL_HEADER_LIBRARIES := \
libaudiopolicycommon \
- libaudiopolicyengine_common_headers \
libaudiopolicyengine_interface_headers
LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
@@ -47,13 +42,15 @@
LOCAL_STATIC_LIBRARIES := \
libaudiopolicypfwwrapper \
- libaudiopolicycomponents
+ libaudiopolicycomponents \
+ libaudiopolicyengine_common \
+ libaudiopolicyengine_config \
LOCAL_SHARED_LIBRARIES := \
- libaudiopolicyengineconfig \
liblog \
libutils \
liblog \
+ libcutils \
libaudioutils \
libparameter \
libmedia_helper \
diff --git a/services/audiopolicy/enginedefault/Android.bp b/services/audiopolicy/enginedefault/Android.bp
new file mode 100644
index 0000000..7b42c6a
--- /dev/null
+++ b/services/audiopolicy/enginedefault/Android.bp
@@ -0,0 +1,32 @@
+cc_library_shared {
+ name: "libaudiopolicyenginedefault",
+ export_include_dirs: ["include"],
+ srcs: [
+ "src/Engine.cpp",
+ "src/EngineInstance.cpp",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+ local_include_dirs: ["include"],
+ header_libs: [
+ "libbase_headers",
+ "libaudiopolicycommon",
+ "libaudiopolicyengine_interface_headers",
+ ],
+ static_libs: [
+ "libaudiopolicycomponents",
+ "libaudiopolicyengine_common",
+ "libaudiopolicyengine_config",
+ ],
+ shared_libs: [
+ "liblog",
+ "libcutils",
+ "libutils",
+ "libmedia_helper",
+ "libaudiopolicy",
+ "libxml2",
+ ],
+}
diff --git a/services/audiopolicy/enginedefault/Android.mk b/services/audiopolicy/enginedefault/Android.mk
deleted file mode 100644
index ebf383b..0000000
--- a/services/audiopolicy/enginedefault/Android.mk
+++ /dev/null
@@ -1,57 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-# Component build
-#######################################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- src/Engine.cpp \
- src/EngineInstance.cpp \
- ../engine/common/src/VolumeCurve.cpp \
- ../engine/common/src/ProductStrategy.cpp \
- ../engine/common/src/EngineBase.cpp \
- ../engine/common/src/VolumeGroup.cpp
-
-audio_policy_engine_includes_common := \
- $(LOCAL_PATH)/include
-
-LOCAL_CFLAGS += \
- -Wall \
- -Werror \
- -Wextra \
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
- $(audio_policy_engine_includes_common)
-
-LOCAL_C_INCLUDES := \
- $(audio_policy_engine_includes_common) \
- $(TARGET_OUT_HEADERS)/hw \
- $(call include-path-for, frameworks-av) \
- $(call include-path-for, audio-utils) \
- $(call include-path-for, bionic)
-
-LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-
-LOCAL_MODULE := libaudiopolicyenginedefault
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_HEADER_LIBRARIES := libbase_headers
-
-LOCAL_STATIC_LIBRARIES := \
- libaudiopolicycomponents
-
-LOCAL_SHARED_LIBRARIES := \
- liblog \
- libcutils \
- libutils \
- libmedia_helper \
- libaudiopolicyengineconfig \
- libaudiopolicy
-
-LOCAL_HEADER_LIBRARIES := \
- libaudiopolicycommon \
- libaudiopolicyengine_common_headers \
- libaudiopolicyengine_interface_headers
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index c969af3..ea98253 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1022,7 +1022,8 @@
}
}
if (*output == AUDIO_IO_HANDLE_NONE) {
- *output = getOutputForDevices(outputDevices, session, *stream, config, flags);
+ *output = getOutputForDevices(outputDevices, session, *stream, config,
+ flags, attr->flags & AUDIO_FLAG_MUTE_HAPTIC);
}
if (*output == AUDIO_IO_HANDLE_NONE) {
return INVALID_OPERATION;
@@ -1100,11 +1101,16 @@
audio_session_t session,
audio_stream_type_t stream,
const audio_config_t *config,
- audio_output_flags_t *flags)
+ audio_output_flags_t *flags,
+ bool forceMutingHaptic)
{
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
status_t status;
+ // Discard haptic channel mask when forcing muting haptic channels.
+ audio_channel_mask_t channelMask = forceMutingHaptic
+ ? (config->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL) : config->channel_mask;
+
// open a direct output if required by specified parameters
//force direct flag if offload flag is set: offloading implies a direct output stream
// and all common behaviors are driven by checking only the direct flag
@@ -1141,7 +1147,7 @@
// and not explicitly requested
if (((*flags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) &&
audio_is_linear_pcm(config->format) && config->sample_rate <= SAMPLE_RATE_HZ_MAX &&
- audio_channel_count_from_out_mask(config->channel_mask) <= 2) {
+ audio_channel_count_from_out_mask(channelMask) <= 2) {
goto non_direct_output;
}
@@ -1157,7 +1163,7 @@
profile = getProfileForOutput(devices,
config->sample_rate,
config->format,
- config->channel_mask,
+ channelMask,
(audio_output_flags_t)*flags,
true /* directOnly */);
}
@@ -1171,7 +1177,7 @@
// and configured with same parameters
if ((config->sample_rate == desc->mSamplingRate) &&
(config->format == desc->mFormat) &&
- (config->channel_mask == desc->mChannelMask) &&
+ (channelMask == desc->mChannelMask) &&
(session == desc->mDirectClientSession)) {
desc->mDirectOpenCount++;
ALOGI("%s reusing direct output %d for session %d", __func__,
@@ -1213,11 +1219,11 @@
if (status != NO_ERROR ||
(config->sample_rate != 0 && config->sample_rate != outputDesc->mSamplingRate) ||
(config->format != AUDIO_FORMAT_DEFAULT && config->format != outputDesc->mFormat) ||
- (config->channel_mask != 0 && config->channel_mask != outputDesc->mChannelMask)) {
+ (channelMask != 0 && channelMask != outputDesc->mChannelMask)) {
ALOGV("%s failed opening direct output: output %d sample rate %d %d,"
"format %d %d, channel mask %04x %04x", __func__, output, config->sample_rate,
outputDesc->mSamplingRate, config->format, outputDesc->mFormat,
- config->channel_mask, outputDesc->mChannelMask);
+ channelMask, outputDesc->mChannelMask);
if (output != AUDIO_IO_HANDLE_NONE) {
outputDesc->close();
}
@@ -1258,12 +1264,11 @@
// at this stage we should ignore the DIRECT flag as no direct output could be found earlier
*flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_DIRECT);
- output = selectOutput(outputs, *flags, config->format,
- config->channel_mask, config->sample_rate);
+ output = selectOutput(outputs, *flags, config->format, channelMask, config->sample_rate);
}
ALOGW_IF((output == 0), "getOutputForDevices() could not find output for stream %d, "
"sampling rate %d, format %#x, channels %#x, flags %#x",
- stream, config->sample_rate, config->format, config->channel_mask, *flags);
+ stream, config->sample_rate, config->format, channelMask, *flags);
return output;
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 641a03a..3a31e1e 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -779,7 +779,8 @@
audio_session_t session,
audio_stream_type_t stream,
const audio_config_t *config,
- audio_output_flags_t *flags);
+ audio_output_flags_t *flags,
+ bool forceMutingHaptic = false);
/**
* @brief getInputForDevice selects an input handle for a given input device and
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 2794324..22e09e4 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -4391,8 +4391,11 @@
dst.status = BufferStatus::OK;
dst.releaseFence = nullptr;
- pushInflightBufferLocked(captureRequest->frameNumber, streamId,
- src->buffer, src->acquire_fence);
+ // Output buffers are empty when using HAL buffer manager
+ if (!mUseHalBufManager) {
+ pushInflightBufferLocked(captureRequest->frameNumber, streamId,
+ src->buffer, src->acquire_fence);
+ }
}
}
return OK;
diff --git a/services/mediaextractor/Android.mk b/services/mediaextractor/Android.mk
index 65fcf40..661a475 100644
--- a/services/mediaextractor/Android.mk
+++ b/services/mediaextractor/Android.mk
@@ -6,7 +6,7 @@
LOCAL_SRC_FILES := \
MediaExtractorService.cpp
-LOCAL_SHARED_LIBRARIES := libmedia libstagefright libbinder libutils liblog
+LOCAL_SHARED_LIBRARIES := libmedia libstagefright libbinder libutils
LOCAL_MODULE:= libmediaextractorservice
include $(BUILD_SHARED_LIBRARY)
@@ -21,7 +21,7 @@
LOCAL_SRC_FILES := main_extractorservice.cpp
LOCAL_SHARED_LIBRARIES := libmedia libmediaextractorservice libbinder libutils \
- liblog libbase libandroidicu libavservices_minijail
+ liblog libandroidicu libavservices_minijail
LOCAL_STATIC_LIBRARIES := libicuandroid_utils
LOCAL_MODULE:= mediaextractor
LOCAL_INIT_RC := mediaextractor.rc