Merge "AAC C2 decoder: add channel mask in output format change" into tm-dev
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 93b79c3..7a1728c 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1826,13 +1826,20 @@
return;
}
+ // preparation of input buffers may not succeed due to the lack of
+ // memory; returning correct error code (NO_MEMORY) as an error allows
+ // MediaCodec to try reclaim and restart codec gracefully.
+ std::map<size_t, sp<MediaCodecBuffer>> clientInputBuffers;
+ err2 = mChannel->prepareInitialInputBuffers(&clientInputBuffers);
+ if (err2 != OK) {
+ ALOGE("Initial preparation for Input Buffers failed");
+ mCallback->onError(err2, ACTION_CODE_FATAL);
+ return;
+ }
+
mCallback->onStartCompleted();
- err2 = mChannel->requestInitialInputBuffers();
- if (err2 != OK) {
- ALOGE("Initial request for Input Buffers failed");
- mCallback->onError(err2, ACTION_CODE_FATAL);
- }
+ mChannel->requestInitialInputBuffers(std::move(clientInputBuffers));
}
void CCodec::initiateShutdown(bool keepComponentAllocated) {
@@ -2126,11 +2133,14 @@
state->set(RUNNING);
}
- status_t err = mChannel->requestInitialInputBuffers();
+ std::map<size_t, sp<MediaCodecBuffer>> clientInputBuffers;
+ status_t err = mChannel->prepareInitialInputBuffers(&clientInputBuffers);
if (err != OK) {
ALOGE("Resume request for Input Buffers failed");
mCallback->onError(err, ACTION_CODE_FATAL);
+ return;
}
+ mChannel->requestInitialInputBuffers(std::move(clientInputBuffers));
}
void CCodec::signalSetParameters(const sp<AMessage> &msg) {
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index cb2ffa0..709e1a6 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -1470,54 +1470,47 @@
return OK;
}
-status_t CCodecBufferChannel::requestInitialInputBuffers() {
+status_t CCodecBufferChannel::prepareInitialInputBuffers(
+ std::map<size_t, sp<MediaCodecBuffer>> *clientInputBuffers) {
if (mInputSurface) {
return OK;
}
+ size_t numInputSlots = mInput.lock()->numSlots;
+
+ {
+ Mutexed<Input>::Locked input(mInput);
+ while (clientInputBuffers->size() < numInputSlots) {
+ size_t index;
+ sp<MediaCodecBuffer> buffer;
+ if (!input->buffers->requestNewBuffer(&index, &buffer)) {
+ break;
+ }
+ clientInputBuffers->emplace(index, buffer);
+ }
+ }
+ if (clientInputBuffers->empty()) {
+ ALOGW("[%s] start: cannot allocate memory at all", mName);
+ return NO_MEMORY;
+ } else if (clientInputBuffers->size() < numInputSlots) {
+ ALOGD("[%s] start: cannot allocate memory for all slots, "
+ "only %zu buffers allocated",
+ mName, clientInputBuffers->size());
+ } else {
+ ALOGV("[%s] %zu initial input buffers available",
+ mName, clientInputBuffers->size());
+ }
+ return OK;
+}
+
+status_t CCodecBufferChannel::requestInitialInputBuffers(
+ std::map<size_t, sp<MediaCodecBuffer>> &&clientInputBuffers) {
C2StreamBufferTypeSetting::output oStreamFormat(0u);
C2PrependHeaderModeSetting prepend(PREPEND_HEADER_TO_NONE);
c2_status_t err = mComponent->query({ &oStreamFormat, &prepend }, {}, C2_DONT_BLOCK, nullptr);
if (err != C2_OK && err != C2_BAD_INDEX) {
return UNKNOWN_ERROR;
}
- size_t numInputSlots = mInput.lock()->numSlots;
-
- struct ClientInputBuffer {
- size_t index;
- sp<MediaCodecBuffer> buffer;
- size_t capacity;
- };
- std::list<ClientInputBuffer> clientInputBuffers;
-
- {
- Mutexed<Input>::Locked input(mInput);
- while (clientInputBuffers.size() < numInputSlots) {
- ClientInputBuffer clientInputBuffer;
- if (!input->buffers->requestNewBuffer(&clientInputBuffer.index,
- &clientInputBuffer.buffer)) {
- break;
- }
- clientInputBuffer.capacity = clientInputBuffer.buffer->capacity();
- clientInputBuffers.emplace_back(std::move(clientInputBuffer));
- }
- }
- if (clientInputBuffers.empty()) {
- ALOGW("[%s] start: cannot allocate memory at all", mName);
- return NO_MEMORY;
- } else if (clientInputBuffers.size() < numInputSlots) {
- ALOGD("[%s] start: cannot allocate memory for all slots, "
- "only %zu buffers allocated",
- mName, clientInputBuffers.size());
- } else {
- ALOGV("[%s] %zu initial input buffers available",
- mName, clientInputBuffers.size());
- }
- // Sort input buffers by their capacities in increasing order.
- clientInputBuffers.sort(
- [](const ClientInputBuffer& a, const ClientInputBuffer& b) {
- return a.capacity < b.capacity;
- });
std::list<std::unique_ptr<C2Work>> flushedConfigs;
mFlushedConfigs.lock()->swap(flushedConfigs);
@@ -1539,25 +1532,31 @@
}
}
if (oStreamFormat.value == C2BufferData::LINEAR &&
- (!prepend || prepend.value == PREPEND_HEADER_TO_NONE)) {
- sp<MediaCodecBuffer> buffer = clientInputBuffers.front().buffer;
+ (!prepend || prepend.value == PREPEND_HEADER_TO_NONE) &&
+ !clientInputBuffers.empty()) {
+ size_t minIndex = clientInputBuffers.begin()->first;
+ sp<MediaCodecBuffer> minBuffer = clientInputBuffers.begin()->second;
+ for (const auto &[index, buffer] : clientInputBuffers) {
+ if (minBuffer->capacity() > buffer->capacity()) {
+ minIndex = index;
+ minBuffer = buffer;
+ }
+ }
// WORKAROUND: Some apps expect CSD available without queueing
// any input. Queue an empty buffer to get the CSD.
- buffer->setRange(0, 0);
- buffer->meta()->clear();
- buffer->meta()->setInt64("timeUs", 0);
- if (queueInputBufferInternal(buffer) != OK) {
+ minBuffer->setRange(0, 0);
+ minBuffer->meta()->clear();
+ minBuffer->meta()->setInt64("timeUs", 0);
+ if (queueInputBufferInternal(minBuffer) != OK) {
ALOGW("[%s] Error while queueing an empty buffer to get CSD",
mName);
return UNKNOWN_ERROR;
}
- clientInputBuffers.pop_front();
+ clientInputBuffers.erase(minIndex);
}
- for (const ClientInputBuffer& clientInputBuffer: clientInputBuffers) {
- mCallback->onInputBufferAvailable(
- clientInputBuffer.index,
- clientInputBuffer.buffer);
+ for (const auto &[index, buffer] : clientInputBuffers) {
+ mCallback->onInputBufferAvailable(index, buffer);
}
return OK;
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h
index b3a5f4b..f29a225 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.h
+++ b/media/codec2/sfplugin/CCodecBufferChannel.h
@@ -130,9 +130,23 @@
bool buffersBoundToCodec);
/**
- * Request initial input buffers to be filled by client.
+ * Prepare initial input buffers to be filled by client.
+ *
+ * \param clientInputBuffers[out] pointer to slot index -> buffer map.
+ * On success, it contains prepared
+ * initial input buffers.
*/
- status_t requestInitialInputBuffers();
+ status_t prepareInitialInputBuffers(
+ std::map<size_t, sp<MediaCodecBuffer>> *clientInputBuffers);
+
+ /**
+ * Request initial input buffers as prepared in clientInputBuffers.
+ *
+ * \param clientInputBuffers[in] slot index -> buffer map with prepared
+ * initial input buffers.
+ */
+ status_t requestInitialInputBuffers(
+ std::map<size_t, sp<MediaCodecBuffer>> &&clientInputBuffers);
/**
* Stop queueing buffers to the component. This object should never queue
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index 316c70d..d95e61f 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -400,10 +400,10 @@
// Rotation
// Note: SDK rotation is clock-wise, while C2 rotation is counter-clock-wise
add(ConfigMapper(KEY_ROTATION, C2_PARAMKEY_VUI_ROTATION, "value")
- .limitTo(D::VIDEO & D::CODED)
+ .limitTo((D::VIDEO | D::IMAGE) & D::CODED)
.withMappers(negate, negate));
add(ConfigMapper(KEY_ROTATION, C2_PARAMKEY_ROTATION, "value")
- .limitTo(D::VIDEO & D::RAW)
+ .limitTo((D::VIDEO | D::IMAGE) & D::RAW)
.withMappers(negate, negate));
// android 'video-scaling'
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index c6b22a6..9b4fc8f 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -2893,6 +2893,38 @@
in.writeInt32(recvTimeUs & 0xFFFFFFFF);
break;
}
+ case ARTPSource::RTCP_RR:
+ {
+ int64_t recvTimeUs;
+ int32_t senderId;
+ int32_t ssrc;
+ int32_t fraction;
+ int32_t lost;
+ int32_t lastSeq;
+ int32_t jitter;
+ int32_t lsr;
+ int32_t dlsr;
+ CHECK(msg->findInt64("recv-time-us", &recvTimeUs));
+ CHECK(msg->findInt32("rtcp-rr-ssrc", &senderId));
+ CHECK(msg->findInt32("rtcp-rrb-ssrc", &ssrc));
+ CHECK(msg->findInt32("rtcp-rrb-fraction", &fraction));
+ CHECK(msg->findInt32("rtcp-rrb-lost", &lost));
+ CHECK(msg->findInt32("rtcp-rrb-lastSeq", &lastSeq));
+ CHECK(msg->findInt32("rtcp-rrb-jitter", &jitter));
+ CHECK(msg->findInt32("rtcp-rrb-lsr", &lsr));
+ CHECK(msg->findInt32("rtcp-rrb-dlsr", &dlsr));
+ in.writeInt32(recvTimeUs >> 32);
+ in.writeInt32(recvTimeUs & 0xFFFFFFFF);
+ in.writeInt32(senderId);
+ in.writeInt32(ssrc);
+ in.writeInt32(fraction);
+ in.writeInt32(lost);
+ in.writeInt32(lastSeq);
+ in.writeInt32(jitter);
+ in.writeInt32(lsr);
+ in.writeInt32(dlsr);
+ break;
+ }
case ARTPSource::RTCP_TSFB: // RTCP TSFB
case ARTPSource::RTCP_PSFB: // RTCP PSFB
case ARTPSource::RTP_AUTODOWN:
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 4b35830..9b0b2a9 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -4222,26 +4222,29 @@
break;
}
- if (asyncNotify != nullptr) {
- if (mSurface != NULL) {
- if (!mReleaseSurface) {
- uint64_t usage = 0;
- if (mSurface->getConsumerUsage(&usage) != OK) {
- usage = 0;
- }
- mReleaseSurface.reset(new ReleaseSurface(usage));
+ bool forceSync = false;
+ if (asyncNotify != nullptr && mSurface != NULL) {
+ if (!mReleaseSurface) {
+ uint64_t usage = 0;
+ if (mSurface->getConsumerUsage(&usage) != OK) {
+ usage = 0;
}
- if (mSurface != mReleaseSurface->getSurface()) {
- status_t err = connectToSurface(mReleaseSurface->getSurface());
- ALOGW_IF(err != OK, "error connecting to release surface: err = %d", err);
- if (err == OK && !(mFlags & kFlagUsesSoftwareRenderer)) {
- err = mCodec->setSurface(mReleaseSurface->getSurface());
- ALOGW_IF(err != OK, "error setting release surface: err = %d", err);
- }
- if (err == OK) {
- (void)disconnectFromSurface();
- mSurface = mReleaseSurface->getSurface();
- }
+ mReleaseSurface.reset(new ReleaseSurface(usage));
+ }
+ if (mSurface != mReleaseSurface->getSurface()) {
+ status_t err = connectToSurface(mReleaseSurface->getSurface());
+ ALOGW_IF(err != OK, "error connecting to release surface: err = %d", err);
+ if (err == OK && !(mFlags & kFlagUsesSoftwareRenderer)) {
+ err = mCodec->setSurface(mReleaseSurface->getSurface());
+ ALOGW_IF(err != OK, "error setting release surface: err = %d", err);
+ }
+ if (err == OK) {
+ (void)disconnectFromSurface();
+ mSurface = mReleaseSurface->getSurface();
+ } else {
+ // We were not able to switch the surface, so force
+ // synchronous release.
+ forceSync = true;
}
}
}
@@ -4265,8 +4268,10 @@
}
if (asyncNotify != nullptr) {
- mResourceManagerProxy->markClientForPendingRemoval();
- postPendingRepliesAndDeferredMessages("kWhatRelease:async");
+ if (!forceSync) {
+ mResourceManagerProxy->markClientForPendingRemoval();
+ postPendingRepliesAndDeferredMessages("kWhatRelease:async");
+ }
asyncNotifyPost.clear();
mAsyncReleaseCompleteNotification = asyncNotify;
}
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index 7d72510..a61f48f 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "ARTPConnection"
#include <utils/Log.h>
+#include <media/stagefright/rtsp/ARTPAssembler.h>
#include <media/stagefright/rtsp/ARTPConnection.h>
#include <media/stagefright/rtsp/ARTPSource.h>
#include <media/stagefright/rtsp/ASessionDescription.h>
@@ -41,6 +42,10 @@
return data[0] << 8 | data[1];
}
+static uint32_t u24at(const uint8_t *data) {
+ return u16at(data) << 16 | data[2];
+}
+
static uint32_t u32at(const uint8_t *data) {
return u16at(data) << 16 | u16at(&data[2]);
}
@@ -877,11 +882,15 @@
switch (data[1]) {
case 200:
{
- parseSR(s, data, headerLength);
+ parseSenderReport(s, data, headerLength);
break;
}
case 201: // RR
+ {
+ parseReceiverReport(s, data, headerLength);
+ break;
+ }
case 202: // SDES
case 204: // APP
break;
@@ -940,18 +949,44 @@
return OK;
}
-status_t ARTPConnection::parseSR(
+status_t ARTPConnection::parseSenderReport(
StreamInfo *s, const uint8_t *data, size_t size) {
- size_t RC = data[0] & 0x1f;
-
- if (size < (7 + RC * 6) * 4) {
- // Packet too short for the minimal SR header.
+ ALOG_ASSERT(size >= 1, "parseSenderReport: invalid packet size.");
+ size_t receptionReportCount = data[0] & 0x1f;
+ if (size < (7 + (receptionReportCount * 6)) * 4) {
+ // Packet too short for the minimal sender report header.
return -1;
}
- uint32_t id = u32at(&data[4]);
+ int64_t recvTimeUs = ALooper::GetNowUs();
+ uint32_t senderId = u32at(&data[4]);
uint64_t ntpTime = u64at(&data[8]);
uint32_t rtpTime = u32at(&data[16]);
+ uint32_t pktCount = u32at(&data[20]);
+ uint32_t octCount = u32at(&data[24]);
+
+ ALOGD("SR received: ssrc=0x%08x, rtpTime%u == ntpTime %llu, pkt=%u, oct=%u",
+ senderId, rtpTime, (unsigned long long)ntpTime, pktCount, octCount);
+
+ sp<ARTPSource> source = findSource(s, senderId);
+ source->timeUpdate(recvTimeUs, rtpTime, ntpTime);
+
+ for (int32_t i = 0; i < receptionReportCount; i++) {
+ int32_t offset = 28 + (i * 24);
+ parseReceptionReportBlock(s, recvTimeUs, senderId, data + offset, size - offset);
+ }
+
+ return 0;
+}
+
+status_t ARTPConnection::parseReceiverReport(
+ StreamInfo *s, const uint8_t *data, size_t size) {
+ ALOG_ASSERT(size >= 1, "parseReceiverReport: invalid packet size.");
+ size_t receptionReportCount = data[0] & 0x1f;
+ if (size < (2 + (receptionReportCount * 6)) * 4) {
+ // Packet too short for the minimal receiver report header.
+ return -1;
+ }
#if 0
ALOGI("XXX timeUpdate: ssrc=0x%08x, rtpTime %u == ntpTime %.3f",
@@ -959,10 +994,40 @@
rtpTime,
(ntpTime >> 32) + (double)(ntpTime & 0xffffffff) / (1ll << 32));
#endif
+ int64_t recvTimeUs = ALooper::GetNowUs();
+ uint32_t senderId = u32at(&data[4]);
- sp<ARTPSource> source = findSource(s, id);
+ for (int i = 0; i < receptionReportCount; i++) {
+ int32_t offset = 8 + (i * 24);
+ parseReceptionReportBlock(s, recvTimeUs, senderId, data + offset, size - offset);
+ }
- source->timeUpdate(rtpTime, ntpTime);
+ return 0;
+}
+
+status_t ARTPConnection::parseReceptionReportBlock(
+ StreamInfo *s, int64_t recvTimeUs, uint32_t senderId, const uint8_t *data, size_t size) {
+ ALOG_ASSERT(size >= 24, "parseReceptionReportBlock: invalid packet size.");
+ if (size < 24) {
+ // remaining size is smaller than reception report block size.
+ return -1;
+ }
+
+ uint32_t rbId = u32at(&data[0]);
+ uint32_t fLost = data[4];
+ int32_t cumLost = u24at(&data[5]);
+ uint32_t ehSeq = u32at(&data[8]);
+ uint32_t jitter = u32at(&data[12]);
+ uint32_t lsr = u32at(&data[16]);
+ uint32_t dlsr = u32at(&data[20]);
+
+ ALOGD("Reception Report Block: t:%llu sid:%u rid:%u fl:%u cl:%u hs:%u jt:%u lsr:%u dlsr:%u",
+ (unsigned long long)recvTimeUs, senderId, rbId, fLost, cumLost,
+ ehSeq, jitter, lsr, dlsr);
+ sp<ARTPSource> source = findSource(s, senderId);
+ sp<ReceptionReportBlock> rrb = new ReceptionReportBlock(
+ rbId, fLost, cumLost, ehSeq, jitter, lsr, dlsr);
+ source->processReceptionReportBlock(recvTimeUs, senderId, rrb);
return 0;
}
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
index 5f62b9d..717d8af 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -132,10 +132,10 @@
}
}
-void ARTPSource::timeUpdate(uint32_t rtpTime, uint64_t ntpTime) {
+void ARTPSource::timeUpdate(int64_t recvTimeUs, uint32_t rtpTime, uint64_t ntpTime) {
mLastSrRtpTime = rtpTime;
mLastSrNtpTime = ntpTime;
- mLastSrUpdateTimeUs = ALooper::GetNowUs();
+ mLastSrUpdateTimeUs = recvTimeUs;
sp<AMessage> notify = mNotify->dup();
notify->setInt32("time-update", true);
@@ -143,7 +143,30 @@
notify->setInt64("ntp-time", ntpTime);
notify->setInt32("rtcp-event", 1);
notify->setInt32("payload-type", RTCP_SR);
- notify->setInt64("recv-time-us", mLastSrUpdateTimeUs);
+ notify->setInt64("recv-time-us", recvTimeUs);
+ notify->post();
+}
+
+void ARTPSource::processReceptionReportBlock(
+ int64_t recvTimeUs, uint32_t senderId, sp<ReceptionReportBlock> rrb) {
+ mLastRrUpdateTimeUs = recvTimeUs;
+
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("rtcp-event", 1);
+ // A Reception Report Block (RRB) can be included in both Sender Report and Receiver Report.
+ // But it means 'Packet Reception Report' actually.
+ // So that, we will report RRB as RR since there is no meaning difference
+ // between RRB(Reception Report Block) and RR(Receiver Report).
+ notify->setInt32("payload-type", RTCP_RR);
+ notify->setInt64("recv-time-us", recvTimeUs);
+ notify->setInt32("rtcp-rr-ssrc", senderId);
+ notify->setInt32("rtcp-rrb-ssrc", rrb->ssrc);
+ notify->setInt32("rtcp-rrb-fraction", rrb->fraction);
+ notify->setInt32("rtcp-rrb-lost", rrb->lost);
+ notify->setInt32("rtcp-rrb-lastSeq", rrb->lastSeq);
+ notify->setInt32("rtcp-rrb-jitter", rrb->jitter);
+ notify->setInt32("rtcp-rrb-lsr", rrb->lsr);
+ notify->setInt32("rtcp-rrb-dlsr", rrb->dlsr);
notify->post();
}
@@ -453,7 +476,8 @@
data[18] = (mHighestSeqNumber >> 8) & 0xff;
data[19] = mHighestSeqNumber & 0xff;
- uint32_t jitterTime = 0;
+ uint32_t jitterTimeMs = (uint32_t)getInterArrivalJitterTimeMs();
+ uint32_t jitterTime = jitterTimeMs * mClockRate / 1000;
data[20] = jitterTime >> 24; // Interarrival jitter
data[21] = (jitterTime >> 16) & 0xff;
data[22] = (jitterTime >> 8) & 0xff;
diff --git a/media/libstagefright/rtsp/include/media/stagefright/rtsp/ARTPAssembler.h b/media/libstagefright/rtsp/include/media/stagefright/rtsp/ARTPAssembler.h
index f959c40..39161b6 100644
--- a/media/libstagefright/rtsp/include/media/stagefright/rtsp/ARTPAssembler.h
+++ b/media/libstagefright/rtsp/include/media/stagefright/rtsp/ARTPAssembler.h
@@ -105,6 +105,27 @@
(long long)rtp, (long long)play, (long long)exp, isExp);
}
+struct ReceptionReportBlock : public RefBase {
+ uint32_t ssrc; // ssrc of data source being reported
+ uint32_t fraction; // fraction lost since last SR/RR
+ int32_t lost; // cumul. no. pkts lost (signed!)
+ uint32_t lastSeq; // extended last seq. no. received
+ uint32_t jitter; // interarrival jitter
+ uint32_t lsr; // last SR packet from this source
+ uint32_t dlsr; // delay since last SR packet
+
+ ReceptionReportBlock(uint32_t ssrc, uint32_t fraction, int32_t lost, uint32_t lastSeq,
+ uint32_t jitter, uint32_t lsr, uint32_t dlsr) {
+ this->ssrc = ssrc;
+ this->fraction = fraction;
+ this->lost = lost;
+ this->lastSeq = lastSeq;
+ this->jitter = jitter;
+ this->lsr = lsr;
+ this->dlsr = dlsr;
+ }
+};
+
} // namespace android
#endif // A_RTP_ASSEMBLER_H_
diff --git a/media/libstagefright/rtsp/include/media/stagefright/rtsp/ARTPConnection.h b/media/libstagefright/rtsp/include/media/stagefright/rtsp/ARTPConnection.h
index 36cca31..73d2866 100644
--- a/media/libstagefright/rtsp/include/media/stagefright/rtsp/ARTPConnection.h
+++ b/media/libstagefright/rtsp/include/media/stagefright/rtsp/ARTPConnection.h
@@ -110,7 +110,10 @@
status_t parseRTP(StreamInfo *info, const sp<ABuffer> &buffer);
status_t parseRTPExt(StreamInfo *s, const uint8_t *extData, size_t extLen, int32_t *cvoDegrees);
status_t parseRTCP(StreamInfo *info, const sp<ABuffer> &buffer);
- status_t parseSR(StreamInfo *info, const uint8_t *data, size_t size);
+ status_t parseSenderReport(StreamInfo *info, const uint8_t *data, size_t size);
+ status_t parseReceiverReport(StreamInfo *info, const uint8_t *data, size_t size);
+ status_t parseReceptionReportBlock(StreamInfo *info,
+ int64_t recvTimeUs, uint32_t senderId, const uint8_t *data, size_t size);
status_t parseTSFB(StreamInfo *info, const uint8_t *data, size_t size);
status_t parsePSFB(StreamInfo *info, const uint8_t *data, size_t size);
status_t parseBYE(StreamInfo *info, const uint8_t *data, size_t size);
diff --git a/media/libstagefright/rtsp/include/media/stagefright/rtsp/ARTPSource.h b/media/libstagefright/rtsp/include/media/stagefright/rtsp/ARTPSource.h
index 4984e91..e9b4942 100644
--- a/media/libstagefright/rtsp/include/media/stagefright/rtsp/ARTPSource.h
+++ b/media/libstagefright/rtsp/include/media/stagefright/rtsp/ARTPSource.h
@@ -36,6 +36,7 @@
struct ABuffer;
struct AMessage;
struct ARTPAssembler;
+struct ReceptionReportBlock;
struct ASessionDescription;
struct ARTPSource : public RefBase {
@@ -59,8 +60,10 @@
void processRTPPacket(const sp<ABuffer> &buffer);
void processRTPPacket();
+ void processReceptionReportBlock(
+ int64_t recvTimeUs, uint32_t senderId, sp<ReceptionReportBlock> rrb);
void timeReset();
- void timeUpdate(uint32_t rtpTime, uint64_t ntpTime);
+ void timeUpdate(int64_t recvTimeUs, uint32_t rtpTime, uint64_t ntpTime);
void byeReceived();
List<sp<ABuffer> > *queue() { return &mQueue; }
@@ -135,6 +138,8 @@
uint64_t mLastSrNtpTime;
int64_t mLastSrUpdateTimeUs;
+ int64_t mLastRrUpdateTimeUs;
+
bool mIsFirstRtpRtcpGap;
double mAvgRtpRtcpGapMs;
double mAvgUnderlineDelayMs;
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 6c6ddbd..5e91501 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -168,9 +168,8 @@
__FUNCTION__, mCameraIdStr.c_str(), entry.data.i64[i]);
}
}
- mDynamicProfileMap.emplace(
- ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
- standardBitmap);
+ mDynamicProfileMap[ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD] =
+ standardBitmap;
} else {
ALOGE("%s: Device %s supports 10-bit output but doesn't include a dynamic range"
" profile map!", __FUNCTION__, mCameraIdStr.c_str());
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3OutputUtils.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3OutputUtils.cpp
index 3809f37..02eebd2 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3OutputUtils.cpp
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3OutputUtils.cpp
@@ -244,6 +244,8 @@
__FUNCTION__, streamId, strerror(-res), res);
if (res == TIMED_OUT || res == NO_MEMORY) {
bufRet.val.set<Tag::error>(StreamBufferRequestError::NO_BUFFER_AVAILABLE);
+ } else if (res == INVALID_OPERATION) {
+ bufRet.val.set<Tag::error>(StreamBufferRequestError::MAX_BUFFER_EXCEEDED);
} else {
bufRet.val.set<Tag::error>(StreamBufferRequestError::UNKNOWN_ERROR);
}