summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/IRemoteDisplayClient.h2
-rw-r--r--media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp170
-rw-r--r--media/libeffects/lvm/wrapper/Bundle/EffectBundle.h2
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.cpp3
-rw-r--r--media/libstagefright/wifi-display/ANetworkSession.cpp220
-rw-r--r--media/libstagefright/wifi-display/ANetworkSession.h15
-rw-r--r--media/libstagefright/wifi-display/source/PlaybackSession.cpp150
-rw-r--r--media/libstagefright/wifi-display/source/PlaybackSession.h24
-rw-r--r--media/libstagefright/wifi-display/source/Serializer.cpp3
-rw-r--r--media/libstagefright/wifi-display/source/WifiDisplaySource.cpp309
-rw-r--r--media/libstagefright/wifi-display/source/WifiDisplaySource.h17
-rw-r--r--services/camera/libcameraservice/Camera2Client.cpp2
-rw-r--r--services/camera/libcameraservice/camera2/CaptureSequencer.cpp13
-rw-r--r--services/camera/libcameraservice/camera2/FrameProcessor.cpp11
-rw-r--r--services/camera/libcameraservice/camera2/Parameters.cpp15
-rw-r--r--services/camera/libcameraservice/camera2/ZslProcessor.cpp78
-rw-r--r--services/camera/libcameraservice/camera2/ZslProcessor.h2
17 files changed, 692 insertions, 344 deletions
diff --git a/include/media/IRemoteDisplayClient.h b/include/media/IRemoteDisplayClient.h
index 553ad36..252b401 100644
--- a/include/media/IRemoteDisplayClient.h
+++ b/include/media/IRemoteDisplayClient.h
@@ -59,8 +59,6 @@ public:
// Indicates that a connection could not be established to the remote display
// or an unrecoverable error occurred and the connection was severed.
- // The media server should continue listening for connection attempts from the
- // remote display.
virtual void onDisplayError(int32_t error) = 0; // one-way
};
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index f3f2d1e..2eae7df 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -1202,7 +1202,7 @@ void VirtualizerSetStrength(EffectContext *pContext, uint32_t strength){
//----------------------------------------------------------------------------
// EqualizerLimitBandLevels()
//----------------------------------------------------------------------------
-// Purpose: limit all EQ band gains to a value less than MAX_BAND_GAIN_DB while
+// Purpose: limit all EQ band gains to a value less than 0 dB while
// preserving the relative band levels.
//
// Inputs:
@@ -1214,7 +1214,6 @@ void VirtualizerSetStrength(EffectContext *pContext, uint32_t strength){
void EqualizerLimitBandLevels(EffectContext *pContext) {
LVM_ControlParams_t ActiveParams; /* Current control Parameters */
LVM_ReturnStatus_en LvmStatus=LVM_SUCCESS; /* Function call status */
- LVM_EQNB_BandDef_t *BandDef;
/* Get the current settings */
LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
@@ -1223,28 +1222,78 @@ void EqualizerLimitBandLevels(EffectContext *pContext) {
//ALOGV("\tEqualizerLimitBandLevels just Got -> %d\n",
// ActiveParams.pEQNB_BandDefinition[band].Gain);
- int gainCorrection = 0;
+ // Apply a volume correction to avoid clipping in the EQ based on 2 factors:
+ // - the maximum EQ band gain: the volume correction is such that the total of volume + max
+ // band gain is <= 0 dB
+ // - the average gain in all bands weighted by their proximity to max gain band.
+ int maxGain = 0;
+ int avgGain = 0;
+ int avgCount = 0;
for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
- int level = pContext->pBundledContext->bandGaindB[i] + ActiveParams.VC_EffectLevel;
- if (level > MAX_BAND_GAIN_DB) {
- int correction = MAX_BAND_GAIN_DB -level;
- if (correction < gainCorrection) {
- gainCorrection = correction;
+ if (pContext->pBundledContext->bandGaindB[i] >= maxGain) {
+ int tmpMaxGain = pContext->pBundledContext->bandGaindB[i];
+ int tmpAvgGain = 0;
+ int tmpAvgCount = 0;
+ for (int j = 0; j < FIVEBAND_NUMBANDS; j++) {
+ int gain = pContext->pBundledContext->bandGaindB[j];
+ // skip current band and gains < 0 dB
+ if (j == i || gain < 0)
+ continue;
+ // no need to continue if one band not processed yet has a higher gain than current
+ // max
+ if (gain > tmpMaxGain) {
+ // force skipping "if (tmpAvgGain >= avgGain)" below as tmpAvgGain is not
+ // meaningful in this case
+ tmpAvgGain = -1;
+ break;
+ }
+
+ int weight = 1;
+ if (j < (i + 2) && j > (i - 2))
+ weight = 4;
+ tmpAvgGain += weight * gain;
+ tmpAvgCount += weight;
+ }
+ if (tmpAvgGain >= avgGain) {
+ maxGain = tmpMaxGain;
+ avgGain = tmpAvgGain;
+ avgCount = tmpAvgCount;
}
}
+ ActiveParams.pEQNB_BandDefinition[i].Frequency = EQNB_5BandPresetsFrequencies[i];
+ ActiveParams.pEQNB_BandDefinition[i].QFactor = EQNB_5BandPresetsQFactors[i];
+ ActiveParams.pEQNB_BandDefinition[i].Gain = pContext->pBundledContext->bandGaindB[i];
}
- /* Set local EQ parameters */
- BandDef = ActiveParams.pEQNB_BandDefinition;
- for (int i=0; i < FIVEBAND_NUMBANDS; i++) {
- ActiveParams.pEQNB_BandDefinition[i].Gain = pContext->pBundledContext->bandGaindB[i] +
- gainCorrection;
+ int gainCorrection = 0;
+ if (maxGain + pContext->pBundledContext->volume > 0) {
+ gainCorrection = maxGain + pContext->pBundledContext->volume;
}
+ if (avgCount) {
+ gainCorrection += avgGain/avgCount;
+ }
+
+ ALOGV("EqualizerLimitBandLevels() gainCorrection %d maxGain %d avgGain %d avgCount %d",
+ gainCorrection, maxGain, avgGain, avgCount);
+
+ ActiveParams.VC_EffectLevel = pContext->pBundledContext->volume - gainCorrection;
+ if (ActiveParams.VC_EffectLevel < -96) {
+ ActiveParams.VC_EffectLevel = -96;
+ }
+
/* Activate the initial settings */
LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "EqualizerLimitBandLevels")
//ALOGV("\tEqualizerLimitBandLevels just Set -> %d\n",
// ActiveParams.pEQNB_BandDefinition[band].Gain);
+
+ //ALOGV("\tEqualizerLimitBandLevels just set (-96dB -> 0dB) -> %d\n",ActiveParams.VC_EffectLevel );
+ if(pContext->pBundledContext->firstVolume == LVM_TRUE){
+ LvmStatus = LVM_SetVolumeNoSmoothing(pContext->pBundledContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_SetVolumeNoSmoothing", "LvmBundle_process")
+ ALOGV("\tLVM_VOLUME: Disabling Smoothing for first volume change to remove spikes/clicks");
+ pContext->pBundledContext->firstVolume = LVM_FALSE;
+ }
}
@@ -1418,25 +1467,12 @@ void EqualizerSetPreset(EffectContext *pContext, int preset){
//ALOGV("\tEqualizerSetPreset(%d)", preset);
pContext->pBundledContext->CurPreset = preset;
- LVM_ControlParams_t ActiveParams; /* Current control Parameters */
- LVM_ReturnStatus_en LvmStatus=LVM_SUCCESS; /* Function call status */
-
- /* Get the current settings */
- LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
- LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "EqualizerSetPreset")
- //ALOGV("\tEqualizerSetPreset Succesfully returned from LVM_GetControlParameters\n");
-
//ActiveParams.pEQNB_BandDefinition = &BandDefs[0];
for (int i=0; i<FIVEBAND_NUMBANDS; i++)
{
- ActiveParams.pEQNB_BandDefinition[i].Frequency = EQNB_5BandPresetsFrequencies[i];
- ActiveParams.pEQNB_BandDefinition[i].QFactor = EQNB_5BandPresetsQFactors[i];
pContext->pBundledContext->bandGaindB[i] =
EQNB_5BandSoftPresets[i + preset * FIVEBAND_NUMBANDS];
}
- /* Activate the new settings */
- LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
- LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "EqualizerSetPreset")
EqualizerLimitBandLevels(pContext);
@@ -1483,39 +1519,14 @@ const char * EqualizerGetPresetName(int32_t preset){
int VolumeSetVolumeLevel(EffectContext *pContext, int16_t level){
- LVM_ControlParams_t ActiveParams; /* Current control Parameters */
- LVM_ReturnStatus_en LvmStatus=LVM_SUCCESS; /* Function call status */
-
- //ALOGV("\tVolumeSetVolumeLevel Level to be set is %d %d\n", level, (LVM_INT16)(level/100));
- /* Get the current settings */
- LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
- LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeSetVolumeLevel")
- if(LvmStatus != LVM_SUCCESS) return -EINVAL;
- //ALOGV("\tVolumeSetVolumeLevel Succesfully returned from LVM_GetControlParameters got: %d\n",
- //ActiveParams.VC_EffectLevel);
-
- /* Volume parameters */
- ActiveParams.VC_EffectLevel = (LVM_INT16)(level/100);
- //ALOGV("\tVolumeSetVolumeLevel() (-96dB -> 0dB) -> %d\n", ActiveParams.VC_EffectLevel );
-
- /* Activate the initial settings */
- LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
- LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "VolumeSetVolumeLevel")
- if(LvmStatus != LVM_SUCCESS) return -EINVAL;
-
- //ALOGV("\tVolumeSetVolumeLevel Succesfully called LVM_SetControlParameters\n");
-
- /* Get the current settings */
- LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
- LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeSetVolumeLevel")
- if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+ if (level > 0 || level < -9600) {
+ return -EINVAL;
+ }
- //ALOGV("\tVolumeSetVolumeLevel just set (-96dB -> 0dB) -> %d\n",ActiveParams.VC_EffectLevel );
- if(pContext->pBundledContext->firstVolume == LVM_TRUE){
- LvmStatus = LVM_SetVolumeNoSmoothing(pContext->pBundledContext->hInstance, &ActiveParams);
- LVM_ERROR_CHECK(LvmStatus, "LVM_SetVolumeNoSmoothing", "LvmBundle_process")
- ALOGV("\tLVM_VOLUME: Disabling Smoothing for first volume change to remove spikes/clicks");
- pContext->pBundledContext->firstVolume = LVM_FALSE;
+ if (pContext->pBundledContext->bMuteEnabled == LVM_TRUE) {
+ pContext->pBundledContext->levelSaved = level / 100;
+ } else {
+ pContext->pBundledContext->volume = level / 100;
}
EqualizerLimitBandLevels(pContext);
@@ -1535,20 +1546,11 @@ int VolumeSetVolumeLevel(EffectContext *pContext, int16_t level){
int VolumeGetVolumeLevel(EffectContext *pContext, int16_t *level){
- //ALOGV("\tVolumeGetVolumeLevel start");
-
- LVM_ControlParams_t ActiveParams; /* Current control Parameters */
- LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
-
- LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
- LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeGetVolumeLevel")
- if(LvmStatus != LVM_SUCCESS) return -EINVAL;
-
- //ALOGV("\tVolumeGetVolumeLevel() (-96dB -> 0dB) -> %d\n", ActiveParams.VC_EffectLevel );
- //ALOGV("\tVolumeGetVolumeLevel Succesfully returned from LVM_GetControlParameters\n");
-
- *level = ActiveParams.VC_EffectLevel*100; // Convert dB to millibels
- //ALOGV("\tVolumeGetVolumeLevel end");
+ if (pContext->pBundledContext->bMuteEnabled == LVM_TRUE) {
+ *level = pContext->pBundledContext->levelSaved * 100;
+ } else {
+ *level = pContext->pBundledContext->volume * 100;
+ }
return 0;
} /* end VolumeGetVolumeLevel */
@@ -1568,32 +1570,16 @@ int32_t VolumeSetMute(EffectContext *pContext, uint32_t mute){
pContext->pBundledContext->bMuteEnabled = mute;
- LVM_ControlParams_t ActiveParams; /* Current control Parameters */
- LVM_ReturnStatus_en LvmStatus=LVM_SUCCESS; /* Function call status */
-
- /* Get the current settings */
- LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
- LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeSetMute")
- if(LvmStatus != LVM_SUCCESS) return -EINVAL;
-
- //ALOGV("\tVolumeSetMute Succesfully returned from LVM_GetControlParameters\n");
- //ALOGV("\tVolumeSetMute to %d, level was %d\n", mute, ActiveParams.VC_EffectLevel );
-
/* Set appropriate volume level */
if(pContext->pBundledContext->bMuteEnabled == LVM_TRUE){
- pContext->pBundledContext->levelSaved = ActiveParams.VC_EffectLevel;
- ActiveParams.VC_EffectLevel = -96;
+ pContext->pBundledContext->levelSaved = pContext->pBundledContext->volume;
+ pContext->pBundledContext->volume = -96;
}else{
- ActiveParams.VC_EffectLevel = pContext->pBundledContext->levelSaved;
+ pContext->pBundledContext->volume = pContext->pBundledContext->levelSaved;
}
- /* Activate the initial settings */
- LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
- LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "VolumeSetMute")
- if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+ EqualizerLimitBandLevels(pContext);
- //ALOGV("\tVolumeSetMute Succesfully called LVM_SetControlParameters\n");
- //ALOGV("\tVolumeSetMute end");
return 0;
} /* end setMute */
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
index 9c58ecd..330bb32 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
@@ -38,7 +38,6 @@ extern "C" {
#define VOLUME_CUP_LOAD_ARM9E 0 // Expressed in 0.1 MIPS
#define BUNDLE_MEM_USAGE 25 // Expressed in kB
//#define LVM_PCM
-#define MAX_BAND_GAIN_DB 4
#ifndef OPENSL_ES_H_
static const effect_uuid_t SL_IID_VOLUME_ = { 0x09e8ede0, 0xddde, 0x11db, 0xb4f6,
@@ -97,6 +96,7 @@ struct BundledEffectContext{
LVM_INT16 *workBuffer;
int frameCount;
int32_t bandGaindB[FIVEBAND_NUMBANDS];
+ int volume;
#ifdef LVM_PCM
FILE *PcmInPtr;
FILE *PcmOutPtr;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index dc1e351..1ddf775 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -963,7 +963,8 @@ sp<AMessage> NuPlayer::Source::getFormat(bool audio) {
status_t NuPlayer::setVideoScalingMode(int32_t mode) {
mVideoScalingMode = mode;
- if (mNativeWindow != NULL) {
+ if (mNativeWindow != NULL
+ && mNativeWindow->getNativeWindow() != NULL) {
status_t ret = native_window_set_scaling_mode(
mNativeWindow->getNativeWindow().get(), mVideoScalingMode);
if (ret != OK) {
diff --git a/media/libstagefright/wifi-display/ANetworkSession.cpp b/media/libstagefright/wifi-display/ANetworkSession.cpp
index 435e72f..90db758 100644
--- a/media/libstagefright/wifi-display/ANetworkSession.cpp
+++ b/media/libstagefright/wifi-display/ANetworkSession.cpp
@@ -56,7 +56,8 @@ struct ANetworkSession::Session : public RefBase {
enum State {
CONNECTING,
CONNECTED,
- LISTENING,
+ LISTENING_RTSP,
+ LISTENING_TCP_DGRAMS,
DATAGRAM,
};
@@ -69,7 +70,8 @@ struct ANetworkSession::Session : public RefBase {
int socket() const;
sp<AMessage> getNotificationMessage() const;
- bool isListening() const;
+ bool isRTSPServer() const;
+ bool isTCPDatagramServer() const;
bool wantsToRead();
bool wantsToWrite();
@@ -79,12 +81,15 @@ struct ANetworkSession::Session : public RefBase {
status_t sendRequest(const void *data, ssize_t size);
+ void setIsRTSPConnection(bool yesno);
+
protected:
virtual ~Session();
private:
int32_t mSessionID;
State mState;
+ bool mIsRTSPConnection;
int mSocket;
sp<AMessage> mNotify;
bool mSawReceiveFailure, mSawSendFailure;
@@ -123,6 +128,7 @@ ANetworkSession::Session::Session(
const sp<AMessage> &notify)
: mSessionID(sessionID),
mState(state),
+ mIsRTSPConnection(false),
mSocket(s),
mNotify(notify),
mSawReceiveFailure(false),
@@ -184,12 +190,20 @@ int ANetworkSession::Session::socket() const {
return mSocket;
}
+void ANetworkSession::Session::setIsRTSPConnection(bool yesno) {
+ mIsRTSPConnection = yesno;
+}
+
sp<AMessage> ANetworkSession::Session::getNotificationMessage() const {
return mNotify;
}
-bool ANetworkSession::Session::isListening() const {
- return mState == LISTENING;
+bool ANetworkSession::Session::isRTSPServer() const {
+ return mState == LISTENING_RTSP;
+}
+
+bool ANetworkSession::Session::isTCPDatagramServer() const {
+ return mState == LISTENING_TCP_DGRAMS;
}
bool ANetworkSession::Session::wantsToRead() {
@@ -284,70 +298,93 @@ status_t ANetworkSession::Session::readMore() {
err = -ECONNRESET;
}
- for (;;) {
- size_t length;
+ if (!mIsRTSPConnection) {
+ // TCP stream carrying 16-bit length-prefixed datagrams.
- if (mInBuffer.size() > 0 && mInBuffer.c_str()[0] == '$') {
- if (mInBuffer.size() < 4) {
- break;
- }
-
- length = U16_AT((const uint8_t *)mInBuffer.c_str() + 2);
+ while (mInBuffer.size() >= 2) {
+ size_t packetSize = U16_AT((const uint8_t *)mInBuffer.c_str());
- if (mInBuffer.size() < 4 + length) {
+ if (mInBuffer.size() < packetSize + 2) {
break;
}
+ sp<ABuffer> packet = new ABuffer(packetSize);
+ memcpy(packet->data(), mInBuffer.c_str() + 2, packetSize);
+
sp<AMessage> notify = mNotify->dup();
notify->setInt32("sessionID", mSessionID);
- notify->setInt32("reason", kWhatBinaryData);
- notify->setInt32("channel", mInBuffer.c_str()[1]);
+ notify->setInt32("reason", kWhatDatagram);
+ notify->setBuffer("data", packet);
+ notify->post();
- sp<ABuffer> data = new ABuffer(length);
- memcpy(data->data(), mInBuffer.c_str() + 4, length);
+ mInBuffer.erase(0, packetSize + 2);
+ }
+ } else {
+ for (;;) {
+ size_t length;
- int64_t nowUs = ALooper::GetNowUs();
- data->meta()->setInt64("arrivalTimeUs", nowUs);
+ if (mInBuffer.size() > 0 && mInBuffer.c_str()[0] == '$') {
+ if (mInBuffer.size() < 4) {
+ break;
+ }
- notify->setBuffer("data", data);
- notify->post();
+ length = U16_AT((const uint8_t *)mInBuffer.c_str() + 2);
- mInBuffer.erase(0, 4 + length);
- continue;
- }
+ if (mInBuffer.size() < 4 + length) {
+ break;
+ }
- sp<ParsedMessage> msg =
- ParsedMessage::Parse(
- mInBuffer.c_str(), mInBuffer.size(), err != OK, &length);
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("sessionID", mSessionID);
+ notify->setInt32("reason", kWhatBinaryData);
+ notify->setInt32("channel", mInBuffer.c_str()[1]);
- if (msg == NULL) {
- break;
- }
+ sp<ABuffer> data = new ABuffer(length);
+ memcpy(data->data(), mInBuffer.c_str() + 4, length);
- sp<AMessage> notify = mNotify->dup();
- notify->setInt32("sessionID", mSessionID);
- notify->setInt32("reason", kWhatData);
- notify->setObject("data", msg);
- notify->post();
+ int64_t nowUs = ALooper::GetNowUs();
+ data->meta()->setInt64("arrivalTimeUs", nowUs);
+
+ notify->setBuffer("data", data);
+ notify->post();
+
+ mInBuffer.erase(0, 4 + length);
+ continue;
+ }
+
+ sp<ParsedMessage> msg =
+ ParsedMessage::Parse(
+ mInBuffer.c_str(), mInBuffer.size(), err != OK, &length);
+
+ if (msg == NULL) {
+ break;
+ }
+
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("sessionID", mSessionID);
+ notify->setInt32("reason", kWhatData);
+ notify->setObject("data", msg);
+ notify->post();
#if 1
- // XXX The (old) dongle sends the wrong content length header on a
- // SET_PARAMETER request that signals a "wfd_idr_request".
- // (17 instead of 19).
- const char *content = msg->getContent();
- if (content
- && !memcmp(content, "wfd_idr_request\r\n", 17)
- && length >= 19
- && mInBuffer.c_str()[length] == '\r'
- && mInBuffer.c_str()[length + 1] == '\n') {
- length += 2;
- }
+ // XXX The (old) dongle sends the wrong content length header on a
+ // SET_PARAMETER request that signals a "wfd_idr_request".
+ // (17 instead of 19).
+ const char *content = msg->getContent();
+ if (content
+ && !memcmp(content, "wfd_idr_request\r\n", 17)
+ && length >= 19
+ && mInBuffer.c_str()[length] == '\r'
+ && mInBuffer.c_str()[length + 1] == '\n') {
+ length += 2;
+ }
#endif
- mInBuffer.erase(0, length);
+ mInBuffer.erase(0, length);
- if (err != OK) {
- break;
+ if (err != OK) {
+ break;
+ }
}
}
@@ -408,7 +445,7 @@ status_t ANetworkSession::Session::writeMore() {
notifyError(kWhatError, -err, "Connection failed");
mSawSendFailure = true;
- return UNKNOWN_ERROR;
+ return -err;
}
mState = CONNECTED;
@@ -451,6 +488,16 @@ status_t ANetworkSession::Session::writeMore() {
status_t ANetworkSession::Session::sendRequest(const void *data, ssize_t size) {
CHECK(mState == CONNECTED || mState == DATAGRAM);
+ if (mState == CONNECTED && !mIsRTSPConnection) {
+ CHECK_LE(size, 65535);
+
+ uint8_t prefix[2];
+ prefix[0] = size >> 8;
+ prefix[1] = size & 0xff;
+
+ mOutBuffer.append((const char *)prefix, sizeof(prefix));
+ }
+
mOutBuffer.append(
(const char *)data,
(size >= 0) ? size : strlen((const char *)data));
@@ -585,6 +632,35 @@ status_t ANetworkSession::createUDPSession(
sessionID);
}
+status_t ANetworkSession::createTCPDatagramSession(
+ const struct in_addr &addr, unsigned port,
+ const sp<AMessage> &notify, int32_t *sessionID) {
+ return createClientOrServer(
+ kModeCreateTCPDatagramSessionPassive,
+ &addr,
+ port,
+ NULL /* remoteHost */,
+ 0 /* remotePort */,
+ notify,
+ sessionID);
+}
+
+status_t ANetworkSession::createTCPDatagramSession(
+ unsigned localPort,
+ const char *remoteHost,
+ unsigned remotePort,
+ const sp<AMessage> &notify,
+ int32_t *sessionID) {
+ return createClientOrServer(
+ kModeCreateTCPDatagramSessionActive,
+ NULL /* addr */,
+ localPort,
+ remoteHost,
+ remotePort,
+ notify,
+ sessionID);
+}
+
status_t ANetworkSession::destroySession(int32_t sessionID) {
Mutex::Autolock autoLock(mLock);
@@ -641,7 +717,8 @@ status_t ANetworkSession::createClientOrServer(
goto bail;
}
- if (mode == kModeCreateRTSPServer) {
+ if (mode == kModeCreateRTSPServer
+ || mode == kModeCreateTCPDatagramSessionPassive) {
const int yes = 1;
res = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
@@ -679,7 +756,8 @@ status_t ANetworkSession::createClientOrServer(
memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
addr.sin_family = AF_INET;
- if (mode == kModeCreateRTSPClient) {
+ if (mode == kModeCreateRTSPClient
+ || mode == kModeCreateTCPDatagramSessionActive) {
struct hostent *ent= gethostbyname(remoteHost);
if (ent == NULL) {
err = -h_errno;
@@ -696,7 +774,17 @@ status_t ANetworkSession::createClientOrServer(
addr.sin_port = htons(port);
}
- if (mode == kModeCreateRTSPClient) {
+ if (mode == kModeCreateRTSPClient
+ || mode == kModeCreateTCPDatagramSessionActive) {
+ in_addr_t x = ntohl(addr.sin_addr.s_addr);
+ ALOGI("connecting socket %d to %d.%d.%d.%d:%d",
+ s,
+ (x >> 24),
+ (x >> 16) & 0xff,
+ (x >> 8) & 0xff,
+ x & 0xff,
+ ntohs(addr.sin_port));
+
res = connect(s, (const struct sockaddr *)&addr, sizeof(addr));
CHECK_LT(res, 0);
@@ -707,7 +795,8 @@ status_t ANetworkSession::createClientOrServer(
res = bind(s, (const struct sockaddr *)&addr, sizeof(addr));
if (res == 0) {
- if (mode == kModeCreateRTSPServer) {
+ if (mode == kModeCreateRTSPServer
+ || mode == kModeCreateTCPDatagramSessionPassive) {
res = listen(s, 4);
} else {
CHECK_EQ(mode, kModeCreateUDPSession);
@@ -746,8 +835,16 @@ status_t ANetworkSession::createClientOrServer(
state = Session::CONNECTING;
break;
+ case kModeCreateTCPDatagramSessionActive:
+ state = Session::CONNECTING;
+ break;
+
+ case kModeCreateTCPDatagramSessionPassive:
+ state = Session::LISTENING_TCP_DGRAMS;
+ break;
+
case kModeCreateRTSPServer:
- state = Session::LISTENING;
+ state = Session::LISTENING_RTSP;
break;
default:
@@ -762,6 +859,12 @@ status_t ANetworkSession::createClientOrServer(
s,
notify);
+ if (mode == kModeCreateTCPDatagramSessionActive) {
+ session->setIsRTSPConnection(false);
+ } else if (mode == kModeCreateRTSPClient) {
+ session->setIsRTSPConnection(true);
+ }
+
mSessions.add(session->sessionID(), session);
interrupt();
@@ -797,7 +900,7 @@ status_t ANetworkSession::connectUDPSession(
remoteAddr.sin_port = htons(remotePort);
status_t err = OK;
- struct hostent *ent= gethostbyname(remoteHost);
+ struct hostent *ent = gethostbyname(remoteHost);
if (ent == NULL) {
err = -h_errno;
} else {
@@ -932,7 +1035,7 @@ void ANetworkSession::threadLoop() {
}
if (FD_ISSET(s, &rs)) {
- if (session->isListening()) {
+ if (session->isRTSPServer() || session->isTCPDatagramServer()) {
struct sockaddr_in remoteAddr;
socklen_t remoteAddrLen = sizeof(remoteAddr);
@@ -969,6 +1072,9 @@ void ANetworkSession::threadLoop() {
clientSocket,
session->getNotificationMessage());
+ clientSession->setIsRTSPConnection(
+ session->isRTSPServer());
+
sessionsToAdd.push_back(clientSession);
}
} else {
diff --git a/media/libstagefright/wifi-display/ANetworkSession.h b/media/libstagefright/wifi-display/ANetworkSession.h
index 8d961ee..c1acdcc 100644
--- a/media/libstagefright/wifi-display/ANetworkSession.h
+++ b/media/libstagefright/wifi-display/ANetworkSession.h
@@ -58,6 +58,19 @@ struct ANetworkSession : public RefBase {
status_t connectUDPSession(
int32_t sessionID, const char *remoteHost, unsigned remotePort);
+ // passive
+ status_t createTCPDatagramSession(
+ const struct in_addr &addr, unsigned port,
+ const sp<AMessage> &notify, int32_t *sessionID);
+
+ // active
+ status_t createTCPDatagramSession(
+ unsigned localPort,
+ const char *remoteHost,
+ unsigned remotePort,
+ const sp<AMessage> &notify,
+ int32_t *sessionID);
+
status_t destroySession(int32_t sessionID);
status_t sendRequest(
@@ -90,6 +103,8 @@ private:
enum Mode {
kModeCreateUDPSession,
+ kModeCreateTCPDatagramSessionPassive,
+ kModeCreateTCPDatagramSessionActive,
kModeCreateRTSPServer,
kModeCreateRTSPClient,
};
diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.cpp b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
index f6f7030..e961518 100644
--- a/media/libstagefright/wifi-display/source/PlaybackSession.cpp
+++ b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
@@ -46,8 +46,8 @@
#include <OMX_IVCommon.h>
-//#define FAKE_VIDEO 1
-#define USE_SERIALIZER 0
+//#define FAKE_VIDEO 1
+#define USE_SERIALIZER 0
namespace android {
@@ -171,20 +171,26 @@ status_t WifiDisplaySource::PlaybackSession::Track::stop() {
WifiDisplaySource::PlaybackSession::PlaybackSession(
const sp<ANetworkSession> &netSession,
const sp<AMessage> &notify,
+ const in_addr &interfaceAddr,
bool legacyMode)
: mNetSession(netSession),
mNotify(notify),
+ mInterfaceAddr(interfaceAddr),
mLegacyMode(legacyMode),
mLastLifesignUs(),
mVideoTrackIndex(-1),
mTSQueue(new ABuffer(12 + kMaxNumTSPacketsPerRTPPacket * 188)),
mPrevTimeUs(-1ll),
- mUseInterleavedTCP(false),
+ mTransportMode(TRANSPORT_UDP),
mRTPChannel(0),
mRTCPChannel(0),
mRTPPort(0),
mRTPSessionID(0),
mRTCPSessionID(0),
+ mClientRTPPort(0),
+ mClientRTCPPort(0),
+ mRTPConnected(false),
+ mRTCPConnected(false),
mRTPSeqNo(0),
mLastNTPTime(0),
mLastRTPTime(0),
@@ -208,15 +214,18 @@ WifiDisplaySource::PlaybackSession::PlaybackSession(
status_t WifiDisplaySource::PlaybackSession::init(
const char *clientIP, int32_t clientRtp, int32_t clientRtcp,
- bool useInterleavedTCP) {
+ TransportMode transportMode) {
+ mClientIP = clientIP;
+
status_t err = setupPacketizer();
if (err != OK) {
return err;
}
- if (useInterleavedTCP) {
- mUseInterleavedTCP = true;
+ mTransportMode = transportMode;
+
+ if (transportMode == TRANSPORT_TCP_INTERLEAVED) {
mRTPChannel = clientRtp;
mRTCPChannel = clientRtcp;
mRTPPort = 0;
@@ -227,19 +236,38 @@ status_t WifiDisplaySource::PlaybackSession::init(
return OK;
}
- mUseInterleavedTCP = false;
mRTPChannel = 0;
mRTCPChannel = 0;
+ if (mTransportMode == TRANSPORT_TCP) {
+ // XXX This is wrong, we need to allocate sockets here, we only
+ // need to do this because the dongles are not establishing their
+ // end until after PLAY instead of before SETUP.
+ mRTPPort = 20000;
+ mRTPSessionID = 0;
+ mRTCPSessionID = 0;
+ mClientRTPPort = clientRtp;
+ mClientRTCPPort = clientRtcp;
+
+ updateLiveness();
+ return OK;
+ }
+
int serverRtp;
sp<AMessage> rtpNotify = new AMessage(kWhatRTPNotify, id());
sp<AMessage> rtcpNotify = new AMessage(kWhatRTCPNotify, id());
for (serverRtp = 15550;; serverRtp += 2) {
int32_t rtpSession;
- err = mNetSession->createUDPSession(
- serverRtp, clientIP, clientRtp,
- rtpNotify, &rtpSession);
+ if (mTransportMode == TRANSPORT_UDP) {
+ err = mNetSession->createUDPSession(
+ serverRtp, clientIP, clientRtp,
+ rtpNotify, &rtpSession);
+ } else {
+ err = mNetSession->createTCPDatagramSession(
+ serverRtp, clientIP, clientRtp,
+ rtpNotify, &rtpSession);
+ }
if (err != OK) {
ALOGI("failed to create RTP socket on port %d", serverRtp);
@@ -258,9 +286,15 @@ status_t WifiDisplaySource::PlaybackSession::init(
}
int32_t rtcpSession;
- err = mNetSession->createUDPSession(
- serverRtp + 1, clientIP, clientRtcp,
- rtcpNotify, &rtcpSession);
+ if (mTransportMode == TRANSPORT_UDP) {
+ err = mNetSession->createUDPSession(
+ serverRtp + 1, clientIP, clientRtcp,
+ rtcpNotify, &rtcpSession);
+ } else {
+ err = mNetSession->createTCPDatagramSession(
+ serverRtp + 1, clientIP, clientRtcp,
+ rtcpNotify, &rtcpSession);
+ }
if (err == OK) {
mRTPPort = serverRtp;
@@ -308,6 +342,42 @@ void WifiDisplaySource::PlaybackSession::updateLiveness() {
status_t WifiDisplaySource::PlaybackSession::play() {
updateLiveness();
+ return OK;
+}
+
+status_t WifiDisplaySource::PlaybackSession::finishPlay() {
+ // XXX Give the dongle 3 secs to bind its sockets.
+ (new AMessage(kWhatFinishPlay, id()))->post(3000000ll);
+ return OK;
+}
+
+status_t WifiDisplaySource::PlaybackSession::onFinishPlay() {
+ if (mTransportMode != TRANSPORT_TCP) {
+ return onFinishPlay2();
+ }
+
+ sp<AMessage> rtpNotify = new AMessage(kWhatRTPNotify, id());
+
+ status_t err = mNetSession->createTCPDatagramSession(
+ mRTPPort, mClientIP.c_str(), mClientRTPPort,
+ rtpNotify, &mRTPSessionID);
+
+ if (err != OK) {
+ return err;
+ }
+
+ if (mClientRTCPPort >= 0) {
+ sp<AMessage> rtcpNotify = new AMessage(kWhatRTCPNotify, id());
+
+ err = mNetSession->createTCPDatagramSession(
+ mRTPPort + 1, mClientIP.c_str(), mClientRTCPPort,
+ rtcpNotify, &mRTCPSessionID);
+ }
+
+ return err;
+}
+
+status_t WifiDisplaySource::PlaybackSession::onFinishPlay2() {
if (mRTCPSessionID != 0) {
scheduleSendSR();
}
@@ -328,6 +398,10 @@ status_t WifiDisplaySource::PlaybackSession::play() {
}
}
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kWhatSessionEstablished);
+ notify->post();
+
return OK;
}
@@ -445,6 +519,32 @@ void WifiDisplaySource::PlaybackSession::onMessageReceived(
break;
}
+ case ANetworkSession::kWhatConnected:
+ {
+ CHECK_EQ(mTransportMode, TRANSPORT_TCP);
+
+ int32_t sessionID;
+ CHECK(msg->findInt32("sessionID", &sessionID));
+
+ if (sessionID == mRTPSessionID) {
+ CHECK(!mRTPConnected);
+ mRTPConnected = true;
+ ALOGI("RTP Session now connected.");
+ } else if (sessionID == mRTCPSessionID) {
+ CHECK(!mRTCPConnected);
+ mRTCPConnected = true;
+ ALOGI("RTCP Session now connected.");
+ } else {
+ TRESPASS();
+ }
+
+ if (mRTPConnected
+ && (mClientRTCPPort < 0 || mRTCPConnected)) {
+ onFinishPlay2();
+ }
+ break;
+ }
+
default:
TRESPASS();
}
@@ -610,6 +710,12 @@ void WifiDisplaySource::PlaybackSession::onMessageReceived(
break;
}
+ case kWhatFinishPlay:
+ {
+ onFinishPlay();
+ break;
+ }
+
default:
TRESPASS();
}
@@ -956,15 +1062,14 @@ void WifiDisplaySource::PlaybackSession::onSendSR() {
addSR(buffer);
addSDES(buffer);
- if (mUseInterleavedTCP) {
+ if (mTransportMode == TRANSPORT_TCP_INTERLEAVED) {
sp<AMessage> notify = mNotify->dup();
notify->setInt32("what", kWhatBinaryData);
notify->setInt32("channel", mRTCPChannel);
notify->setBuffer("data", buffer);
notify->post();
} else {
- mNetSession->sendRequest(
- mRTCPSessionID, buffer->data(), buffer->size());
+ sendPacket(mRTCPSessionID, buffer->data(), buffer->size());
}
++mNumSRsSent;
@@ -1011,7 +1116,7 @@ ssize_t WifiDisplaySource::PlaybackSession::appendTSData(
mLastRTPTime = rtpTime;
mLastNTPTime = GetNowNTP();
- if (mUseInterleavedTCP) {
+ if (mTransportMode == TRANSPORT_TCP_INTERLEAVED) {
sp<AMessage> notify = mNotify->dup();
notify->setInt32("what", kWhatBinaryData);
@@ -1022,8 +1127,7 @@ ssize_t WifiDisplaySource::PlaybackSession::appendTSData(
notify->setBuffer("data", data);
notify->post();
} else {
- mNetSession->sendRequest(
- mRTPSessionID, rtp, mTSQueue->size());
+ sendPacket(mRTPSessionID, rtp, mTSQueue->size());
mTotalBytesSent += mTSQueue->size();
int64_t delayUs = ALooper::GetNowUs() - mFirstPacketTimeUs;
@@ -1144,8 +1248,7 @@ status_t WifiDisplaySource::PlaybackSession::parseTSFB(
uint16_t bufferSeqNo = buffer->int32Data() & 0xffff;
if (bufferSeqNo == seqNo) {
- mNetSession->sendRequest(
- mRTPSessionID, buffer->data(), buffer->size());
+ sendPacket(mRTPSessionID, buffer->data(), buffer->size());
found = true;
break;
@@ -1172,5 +1275,10 @@ void WifiDisplaySource::PlaybackSession::requestIDRFrame() {
}
}
+status_t WifiDisplaySource::PlaybackSession::sendPacket(
+ int32_t sessionID, const void *data, size_t size) {
+ return mNetSession->sendRequest(sessionID, data, size);
+}
+
} // namespace android
diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.h b/media/libstagefright/wifi-display/source/PlaybackSession.h
index 8b6ddee..0047842 100644
--- a/media/libstagefright/wifi-display/source/PlaybackSession.h
+++ b/media/libstagefright/wifi-display/source/PlaybackSession.h
@@ -38,11 +38,17 @@ struct WifiDisplaySource::PlaybackSession : public AHandler {
PlaybackSession(
const sp<ANetworkSession> &netSession,
const sp<AMessage> &notify,
+ const struct in_addr &interfaceAddr,
bool legacyMode);
+ enum TransportMode {
+ TRANSPORT_UDP,
+ TRANSPORT_TCP_INTERLEAVED,
+ TRANSPORT_TCP,
+ };
status_t init(
const char *clientIP, int32_t clientRtp, int32_t clientRtcp,
- bool useInterleavedTCP);
+ TransportMode transportMode);
status_t destroy();
@@ -52,6 +58,7 @@ struct WifiDisplaySource::PlaybackSession : public AHandler {
void updateLiveness();
status_t play();
+ status_t finishPlay();
status_t pause();
sp<ISurfaceTexture> getSurfaceTexture();
@@ -63,6 +70,7 @@ struct WifiDisplaySource::PlaybackSession : public AHandler {
enum {
kWhatSessionDead,
kWhatBinaryData,
+ kWhatSessionEstablished,
};
protected:
@@ -79,6 +87,7 @@ private:
kWhatSerializerNotify,
kWhatConverterNotify,
kWhatUpdateSurface,
+ kWhatFinishPlay,
};
static const int64_t kSendSRIntervalUs = 10000000ll;
@@ -87,6 +96,7 @@ private:
sp<ANetworkSession> mNetSession;
sp<AMessage> mNotify;
+ in_addr mInterfaceAddr;
bool mLegacyMode;
int64_t mLastLifesignUs;
@@ -102,7 +112,9 @@ private:
sp<ABuffer> mTSQueue;
int64_t mPrevTimeUs;
- bool mUseInterleavedTCP;
+ TransportMode mTransportMode;
+
+ AString mClientIP;
// in TCP mode
int32_t mRTPChannel;
@@ -113,6 +125,10 @@ private:
int32_t mRTPSessionID;
int32_t mRTCPSessionID;
+ int32_t mClientRTPPort;
+ int32_t mClientRTCPPort;
+ bool mRTPConnected;
+ bool mRTCPConnected;
uint32_t mRTPSeqNo;
@@ -160,6 +176,10 @@ private:
status_t parseRTCP(const sp<ABuffer> &buffer);
status_t parseTSFB(const uint8_t *data, size_t size);
+ status_t sendPacket(int32_t sessionID, const void *data, size_t size);
+ status_t onFinishPlay();
+ status_t onFinishPlay2();
+
DISALLOW_EVIL_CONSTRUCTORS(PlaybackSession);
};
diff --git a/media/libstagefright/wifi-display/source/Serializer.cpp b/media/libstagefright/wifi-display/source/Serializer.cpp
index 78dc4e6..598fd3e 100644
--- a/media/libstagefright/wifi-display/source/Serializer.cpp
+++ b/media/libstagefright/wifi-display/source/Serializer.cpp
@@ -286,8 +286,7 @@ status_t Serializer::onStart() {
}
if (err == OK) {
- // XXX add a 5 second delay for the client to get ready.
- schedulePoll(5000000ll);
+ schedulePoll();
}
return err;
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
index 53adb87..8fead96 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
@@ -31,7 +31,7 @@
#include <media/stagefright/MediaErrors.h>
#include <arpa/inet.h>
-#include <netinet/in.h>
+#include <cutils/properties.h>
namespace android {
@@ -41,6 +41,7 @@ WifiDisplaySource::WifiDisplaySource(
: mNetSession(netSession),
mClient(client),
mSessionID(0),
+ mClientSessionID(0),
mReaperPending(false),
mNextCSeq(1) {
}
@@ -114,14 +115,12 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) {
port = kWifiDisplayDefaultPort;
}
- struct in_addr addr;
-
if (err == OK) {
- if (inet_aton(iface.c_str(), &addr) != 0) {
+ if (inet_aton(iface.c_str(), &mInterfaceAddr) != 0) {
sp<AMessage> notify = new AMessage(kWhatRTSPNotify, id());
err = mNetSession->createRTSPServer(
- addr, port, notify, &mSessionID);
+ mInterfaceAddr, port, notify, &mSessionID);
} else {
err = -EINVAL;
}
@@ -158,7 +157,11 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) {
mNetSession->destroySession(sessionID);
- mClientInfos.removeItem(sessionID);
+ if (sessionID == mClientSessionID) {
+ mClientSessionID = -1;
+
+ disconnectClient(UNKNOWN_ERROR);
+ }
break;
}
@@ -167,15 +170,31 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) {
int32_t sessionID;
CHECK(msg->findInt32("sessionID", &sessionID));
- ClientInfo info;
- CHECK(msg->findString("client-ip", &info.mRemoteIP));
- CHECK(msg->findString("server-ip", &info.mLocalIP));
- CHECK(msg->findInt32("server-port", &info.mLocalPort));
- info.mPlaybackSessionID = -1;
+ if (mClientSessionID > 0) {
+ ALOGW("A client tried to connect, but we already "
+ "have one.");
- ALOGI("We now have a client (%d) connected.", sessionID);
+ mNetSession->destroySession(sessionID);
+ break;
+ }
+
+ CHECK(msg->findString("client-ip", &mClientInfo.mRemoteIP));
+ CHECK(msg->findString("server-ip", &mClientInfo.mLocalIP));
+
+ if (mClientInfo.mRemoteIP == mClientInfo.mLocalIP) {
+ // Disallow connections from the local interface
+ // for security reasons.
+ mNetSession->destroySession(sessionID);
+ break;
+ }
- mClientInfos.add(sessionID, info);
+ CHECK(msg->findInt32(
+ "server-port", &mClientInfo.mLocalPort));
+ mClientInfo.mPlaybackSessionID = -1;
+
+ mClientSessionID = sessionID;
+
+ ALOGI("We now have a client (%d) connected.", sessionID);
status_t err = sendM1(sessionID);
CHECK_EQ(err, (status_t)OK);
@@ -199,20 +218,7 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) {
uint32_t replyID;
CHECK(msg->senderAwaitsResponse(&replyID));
- for (size_t i = mPlaybackSessions.size(); i-- > 0;) {
- sp<PlaybackSession> playbackSession =
- mPlaybackSessions.valueAt(i);
-
- mPlaybackSessions.removeItemsAt(i);
-
- playbackSession->destroy();
- looper()->unregisterHandler(playbackSession->id());
- playbackSession.clear();
- }
-
- if (mClient != NULL) {
- mClient->onDisplayDisconnected();
- }
+ disconnectClient(OK);
status_t err = OK;
@@ -226,21 +232,17 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) {
{
mReaperPending = false;
- for (size_t i = mPlaybackSessions.size(); i-- > 0;) {
- const sp<PlaybackSession> &playbackSession =
- mPlaybackSessions.valueAt(i);
-
- if (playbackSession->getLastLifesignUs()
- + kPlaybackSessionTimeoutUs < ALooper::GetNowUs()) {
- ALOGI("playback session %d timed out, reaping.",
- mPlaybackSessions.keyAt(i));
-
- looper()->unregisterHandler(playbackSession->id());
- mPlaybackSessions.removeItemsAt(i);
- }
+ if (mClientSessionID == 0
+ || mClientInfo.mPlaybackSession == NULL) {
+ break;
}
- if (!mPlaybackSessions.isEmpty()) {
+ if (mClientInfo.mPlaybackSession->getLastLifesignUs()
+ + kPlaybackSessionTimeoutUs < ALooper::GetNowUs()) {
+ ALOGI("playback session timed out, reaping.");
+
+ disconnectClient(-ETIMEDOUT);
+ } else {
scheduleReaper();
}
break;
@@ -254,44 +256,44 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) {
int32_t what;
CHECK(msg->findInt32("what", &what));
- ssize_t index = mPlaybackSessions.indexOfKey(playbackSessionID);
- if (index >= 0) {
- const sp<PlaybackSession> &playbackSession =
- mPlaybackSessions.valueAt(index);
-
- if (what == PlaybackSession::kWhatSessionDead) {
- ALOGI("playback sessions %d wants to quit.",
- playbackSessionID);
-
- looper()->unregisterHandler(playbackSession->id());
- mPlaybackSessions.removeItemsAt(index);
- } else {
- CHECK_EQ(what, PlaybackSession::kWhatBinaryData);
+ if (what == PlaybackSession::kWhatSessionDead) {
+ ALOGI("playback session wants to quit.");
+
+ disconnectClient(UNKNOWN_ERROR);
+ } else if (what == PlaybackSession::kWhatSessionEstablished) {
+ if (mClient != NULL) {
+ mClient->onDisplayConnected(
+ mClientInfo.mPlaybackSession->getSurfaceTexture(),
+ mClientInfo.mPlaybackSession->width(),
+ mClientInfo.mPlaybackSession->height(),
+ 0 /* flags */);
+ }
+ } else {
+ CHECK_EQ(what, PlaybackSession::kWhatBinaryData);
- int32_t channel;
- CHECK(msg->findInt32("channel", &channel));
+ int32_t channel;
+ CHECK(msg->findInt32("channel", &channel));
- sp<ABuffer> data;
- CHECK(msg->findBuffer("data", &data));
+ sp<ABuffer> data;
+ CHECK(msg->findBuffer("data", &data));
- CHECK_LE(channel, 0xffu);
- CHECK_LE(data->size(), 0xffffu);
+ CHECK_LE(channel, 0xffu);
+ CHECK_LE(data->size(), 0xffffu);
- int32_t sessionID;
- CHECK(msg->findInt32("sessionID", &sessionID));
+ int32_t sessionID;
+ CHECK(msg->findInt32("sessionID", &sessionID));
- char header[4];
- header[0] = '$';
- header[1] = channel;
- header[2] = data->size() >> 8;
- header[3] = data->size() & 0xff;
+ char header[4];
+ header[0] = '$';
+ header[1] = channel;
+ header[2] = data->size() >> 8;
+ header[3] = data->size() & 0xff;
- mNetSession->sendRequest(
- sessionID, header, sizeof(header));
+ mNetSession->sendRequest(
+ sessionID, header, sizeof(header));
- mNetSession->sendRequest(
- sessionID, data->data(), data->size());
- }
+ mNetSession->sendRequest(
+ sessionID, data->data(), data->size());
}
break;
}
@@ -301,7 +303,7 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) {
int32_t sessionID;
CHECK(msg->findInt32("sessionID", &sessionID));
- if (mClientInfos.indexOfKey(sessionID) < 0) {
+ if (mClientSessionID != sessionID) {
// Obsolete event, client is already gone.
break;
}
@@ -392,15 +394,25 @@ status_t WifiDisplaySource::sendM4(int32_t sessionID) {
// max-hres (none or 2 byte)
// max-vres (none or 2 byte)
- const ClientInfo &info = mClientInfos.valueFor(sessionID);
+ CHECK_EQ(sessionID, mClientSessionID);
+
+ AString transportString = "UDP";
+
+ char val[PROPERTY_VALUE_MAX];
+ if (property_get("media.wfd.enable-tcp", val, NULL)
+ && (!strcasecmp("true", val) || !strcmp("1", val))) {
+ ALOGI("Using TCP transport.");
+ transportString = "TCP";
+ }
AString body = StringPrintf(
"wfd_video_formats: "
"30 00 02 02 00000040 00000000 00000000 00 0000 0000 00 none none\r\n"
"wfd_audio_codecs: AAC 00000001 00\r\n" // 2 ch AAC 48kHz
"wfd_presentation_URL: rtsp://%s:%d/wfd1.0/streamid=0 none\r\n"
- "wfd_client_rtp_ports: RTP/AVP/UDP;unicast 19000 0 mode=play\r\n",
- info.mLocalIP.c_str(), info.mLocalPort);
+ "wfd_client_rtp_ports: RTP/AVP/%s;unicast 19000 0 mode=play\r\n",
+ mClientInfo.mLocalIP.c_str(), mClientInfo.mLocalPort,
+ transportString.c_str());
AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n";
AppendCommonResponse(&request, mNextCSeq);
@@ -455,8 +467,9 @@ status_t WifiDisplaySource::sendM16(int32_t sessionID) {
AString request = "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n";
AppendCommonResponse(&request, mNextCSeq);
- const ClientInfo &info = mClientInfos.valueFor(sessionID);
- request.append(StringPrintf("Session: %d\r\n", info.mPlaybackSessionID));
+ CHECK_EQ(sessionID, mClientSessionID);
+ request.append(
+ StringPrintf("Session: %d\r\n", mClientInfo.mPlaybackSessionID));
request.append("\r\n"); // Empty body
status_t err =
@@ -534,11 +547,10 @@ status_t WifiDisplaySource::onReceiveM16Response(
int32_t sessionID, const sp<ParsedMessage> &msg) {
// If only the response was required to include a "Session:" header...
- const ClientInfo &info = mClientInfos.valueFor(sessionID);
+ CHECK_EQ(sessionID, mClientSessionID);
- ssize_t index = mPlaybackSessions.indexOfKey(info.mPlaybackSessionID);
- if (index >= 0) {
- mPlaybackSessions.valueAt(index)->updateLiveness();
+ if (mClientInfo.mPlaybackSession != NULL) {
+ mClientInfo.mPlaybackSession->updateLiveness();
scheduleKeepAlive(sessionID);
}
@@ -712,8 +724,8 @@ void WifiDisplaySource::onSetupRequest(
int32_t sessionID,
int32_t cseq,
const sp<ParsedMessage> &data) {
- ClientInfo *info = &mClientInfos.editValueFor(sessionID);
- if (info->mPlaybackSessionID != -1) {
+ CHECK_EQ(sessionID, mClientSessionID);
+ if (mClientInfo.mPlaybackSessionID != -1) {
// We only support a single playback session per client.
// This is due to the reversed keep-alive design in the wfd specs...
sendErrorResponse(sessionID, "400 Bad Request", cseq);
@@ -726,20 +738,40 @@ void WifiDisplaySource::onSetupRequest(
return;
}
- bool useInterleavedTCP = false;
+ PlaybackSession::TransportMode transportMode =
+ PlaybackSession::TRANSPORT_UDP;
int clientRtp, clientRtcp;
if (transport.startsWith("RTP/AVP/TCP;")) {
AString interleaved;
- if (!ParsedMessage::GetAttribute(
+ if (ParsedMessage::GetAttribute(
transport.c_str(), "interleaved", &interleaved)
- || sscanf(interleaved.c_str(), "%d-%d",
- &clientRtp, &clientRtcp) != 2) {
- sendErrorResponse(sessionID, "400 Bad Request", cseq);
- return;
- }
+ && sscanf(interleaved.c_str(), "%d-%d",
+ &clientRtp, &clientRtcp) == 2) {
+ transportMode = PlaybackSession::TRANSPORT_TCP_INTERLEAVED;
+ } else {
+ bool badRequest = false;
+
+ AString clientPort;
+ if (!ParsedMessage::GetAttribute(
+ transport.c_str(), "client_port", &clientPort)) {
+ badRequest = true;
+ } else if (sscanf(clientPort.c_str(), "%d-%d",
+ &clientRtp, &clientRtcp) == 2) {
+ } else if (sscanf(clientPort.c_str(), "%d", &clientRtp) == 1) {
+ // No RTCP.
+ clientRtcp = -1;
+ } else {
+ badRequest = true;
+ }
+
+ if (badRequest) {
+ sendErrorResponse(sessionID, "400 Bad Request", cseq);
+ return;
+ }
- useInterleavedTCP = true;
+ transportMode = PlaybackSession::TRANSPORT_TCP;
+ }
} else if (transport.startsWith("RTP/AVP;unicast;")
|| transport.startsWith("RTP/AVP/UDP;unicast;")) {
bool badRequest = false;
@@ -780,7 +812,8 @@ void WifiDisplaySource::onSetupRequest(
sp<PlaybackSession> playbackSession =
new PlaybackSession(
- mNetSession, notify, mClient == NULL /* legacyMode */);
+ mNetSession, notify, mInterfaceAddr,
+ mClient == NULL /* legacyMode */);
looper()->registerHandler(playbackSession);
@@ -798,10 +831,10 @@ void WifiDisplaySource::onSetupRequest(
}
status_t err = playbackSession->init(
- info->mRemoteIP.c_str(),
+ mClientInfo.mRemoteIP.c_str(),
clientRtp,
clientRtcp,
- useInterleavedTCP);
+ transportMode);
if (err != OK) {
looper()->unregisterHandler(playbackSession->id());
@@ -819,14 +852,13 @@ void WifiDisplaySource::onSetupRequest(
return;
}
- mPlaybackSessions.add(playbackSessionID, playbackSession);
-
- info->mPlaybackSessionID = playbackSessionID;
+ mClientInfo.mPlaybackSessionID = playbackSessionID;
+ mClientInfo.mPlaybackSession = playbackSession;
AString response = "RTSP/1.0 200 OK\r\n";
AppendCommonResponse(&response, cseq, playbackSessionID);
- if (useInterleavedTCP) {
+ if (transportMode == PlaybackSession::TRANSPORT_TCP_INTERLEAVED) {
response.append(
StringPrintf(
"Transport: RTP/AVP/TCP;interleaved=%d-%d;",
@@ -834,17 +866,24 @@ void WifiDisplaySource::onSetupRequest(
} else {
int32_t serverRtp = playbackSession->getRTPPort();
+ AString transportString = "UDP";
+ if (transportMode == PlaybackSession::TRANSPORT_TCP) {
+ transportString = "TCP";
+ }
+
if (clientRtcp >= 0) {
response.append(
StringPrintf(
- "Transport: RTP/AVP;unicast;client_port=%d-%d;"
+ "Transport: RTP/AVP/%s;unicast;client_port=%d-%d;"
"server_port=%d-%d\r\n",
+ transportString.c_str(),
clientRtp, clientRtcp, serverRtp, serverRtp + 1));
} else {
response.append(
StringPrintf(
- "Transport: RTP/AVP;unicast;client_port=%d;"
+ "Transport: RTP/AVP/%s;unicast;client_port=%d;"
"server_port=%d\r\n",
+ transportString.c_str(),
clientRtp, serverRtp));
}
}
@@ -882,13 +921,7 @@ void WifiDisplaySource::onPlayRequest(
err = mNetSession->sendRequest(sessionID, response.c_str());
CHECK_EQ(err, (status_t)OK);
- if (mClient != NULL) {
- mClient->onDisplayConnected(
- playbackSession->getSurfaceTexture(),
- playbackSession->width(),
- playbackSession->height(),
- 0 /* flags */);
- }
+ playbackSession->finishPlay();
}
void WifiDisplaySource::onPauseRequest(
@@ -928,15 +961,15 @@ void WifiDisplaySource::onTeardownRequest(
return;
}
- looper()->unregisterHandler(playbackSession->id());
- mPlaybackSessions.removeItem(playbackSessionID);
-
AString response = "RTSP/1.0 200 OK\r\n";
AppendCommonResponse(&response, cseq, playbackSessionID);
+ response.append("Connection: close\r\n");
response.append("\r\n");
status_t err = mNetSession->sendRequest(sessionID, response.c_str());
CHECK_EQ(err, (status_t)OK);
+
+ disconnectClient(UNKNOWN_ERROR);
}
void WifiDisplaySource::onGetParameterRequest(
@@ -970,19 +1003,10 @@ void WifiDisplaySource::onSetParameterRequest(
sp<PlaybackSession> playbackSession =
findPlaybackSession(data, &playbackSessionID);
-#if 1
- // XXX the older dongles do not include a "Session:" header in this request.
- if (playbackSession == NULL) {
- CHECK_EQ(mPlaybackSessions.size(), 1u);
- playbackSessionID = mPlaybackSessions.keyAt(0);
- playbackSession = mPlaybackSessions.valueAt(0);
- }
-#else
if (playbackSession == NULL) {
sendErrorResponse(sessionID, "454 Session Not Found", cseq);
return;
}
-#endif
// XXX check that the parameter is about that.
playbackSession->requestIDRFrame();
@@ -1041,37 +1065,42 @@ void WifiDisplaySource::sendErrorResponse(
}
int32_t WifiDisplaySource::makeUniquePlaybackSessionID() const {
- for (;;) {
- int32_t playbackSessionID = rand();
-
- if (playbackSessionID == -1) {
- // reserved.
- continue;
- }
-
- for (size_t i = 0; i < mPlaybackSessions.size(); ++i) {
- if (mPlaybackSessions.keyAt(i) == playbackSessionID) {
- continue;
- }
- }
-
- return playbackSessionID;
- }
+ return rand();
}
sp<WifiDisplaySource::PlaybackSession> WifiDisplaySource::findPlaybackSession(
const sp<ParsedMessage> &data, int32_t *playbackSessionID) const {
if (!data->findInt32("session", playbackSessionID)) {
- *playbackSessionID = 0;
- return NULL;
+ // XXX the older dongles do not always include a "Session:" header.
+ *playbackSessionID = mClientInfo.mPlaybackSessionID;
+ return mClientInfo.mPlaybackSession;
}
- ssize_t index = mPlaybackSessions.indexOfKey(*playbackSessionID);
- if (index < 0) {
+ if (*playbackSessionID != mClientInfo.mPlaybackSessionID) {
return NULL;
}
- return mPlaybackSessions.valueAt(index);
+ return mClientInfo.mPlaybackSession;
+}
+
+void WifiDisplaySource::disconnectClient(status_t err) {
+ if (mClientSessionID != 0) {
+ if (mClientInfo.mPlaybackSession != NULL) {
+ looper()->unregisterHandler(mClientInfo.mPlaybackSession->id());
+ mClientInfo.mPlaybackSession.clear();
+ }
+
+ mNetSession->destroySession(mClientSessionID);
+ mClientSessionID = 0;
+ }
+
+ if (mClient != NULL) {
+ if (err != OK) {
+ mClient->onDisplayError(IRemoteDisplayClient::kDisplayErrorUnknown);
+ } else {
+ mClient->onDisplayDisconnected();
+ }
+ }
}
} // namespace android
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.h b/media/libstagefright/wifi-display/source/WifiDisplaySource.h
index 99eb4f5..3c8d50f 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.h
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.h
@@ -22,6 +22,8 @@
#include <media/stagefright/foundation/AHandler.h>
+#include <netinet/in.h>
+
namespace android {
struct IRemoteDisplayClient;
@@ -78,16 +80,19 @@ private:
sp<ANetworkSession> mNetSession;
sp<IRemoteDisplayClient> mClient;
+ struct in_addr mInterfaceAddr;
int32_t mSessionID;
+ int32_t mClientSessionID;
+
struct ClientInfo {
AString mRemoteIP;
AString mLocalIP;
int32_t mLocalPort;
int32_t mPlaybackSessionID;
+ sp<PlaybackSession> mPlaybackSession;
};
- // by sessionID.
- KeyedVector<int32_t, ClientInfo> mClientInfos;
+ ClientInfo mClientInfo;
bool mReaperPending;
@@ -95,8 +100,6 @@ private:
KeyedVector<ResponseID, HandleRTSPResponseFunc> mResponseHandlers;
- KeyedVector<int32_t, sp<PlaybackSession> > mPlaybackSessions;
-
status_t sendM1(int32_t sessionID);
status_t sendM3(int32_t sessionID);
status_t sendM4(int32_t sessionID);
@@ -179,6 +182,12 @@ private:
sp<PlaybackSession> findPlaybackSession(
const sp<ParsedMessage> &data, int32_t *playbackSessionID) const;
+ // Disconnects the current client and shuts down its playback session
+ // (if any). The reason for the disconnection is OK for orderly shutdown
+ // or a nonzero error code.
+ // A listener is notified accordingly.
+ void disconnectClient(status_t err);
+
DISALLOW_EVIL_CONSTRUCTORS(WifiDisplaySource);
};
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index eb72412..4fad83e 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -345,6 +345,8 @@ status_t Camera2Client::dump(int fd, const Vector<String16>& args) {
mFrameProcessor->dump(fd, args);
+ mZslProcessor->dump(fd, args);
+
result = " Device dump:\n";
write(fd, result.string(), result.size());
diff --git a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
index 678f114..eb9eb5b 100644
--- a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
+++ b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
@@ -274,8 +274,14 @@ CaptureSequencer::CaptureState CaptureSequencer::manageZslStart(
// TODO: Actually select the right thing here.
res = processor->pushToReprocess(mCaptureId);
if (res != OK) {
- ALOGW("%s: Camera %d: Failed to use ZSL queue, falling back to standard capture",
- __FUNCTION__, client->getCameraId());
+ if (res == NOT_ENOUGH_DATA) {
+ ALOGV("%s: Camera %d: ZSL queue doesn't have good frame, "
+ "falling back to normal capture", __FUNCTION__,
+ client->getCameraId());
+ } else {
+ ALOGE("%s: Camera %d: Error in ZSL queue: %s (%d)",
+ __FUNCTION__, client->getCameraId(), strerror(-res), res);
+ }
return STANDARD_START;
}
@@ -410,7 +416,8 @@ CaptureSequencer::CaptureState CaptureSequencer::manageStandardCapture(
return DONE;
}
- if (l.mParameters.playShutterSound) {
+ if (l.mParameters.playShutterSound &&
+ l.mParameters.state == Parameters::STILL_CAPTURE) {
client->getCameraService()->playSound(CameraService::SOUND_SHUTTER);
}
diff --git a/services/camera/libcameraservice/camera2/FrameProcessor.cpp b/services/camera/libcameraservice/camera2/FrameProcessor.cpp
index e24db0b..a7d19aa 100644
--- a/services/camera/libcameraservice/camera2/FrameProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/FrameProcessor.cpp
@@ -174,8 +174,7 @@ status_t FrameProcessor::processFaceDetect(const CameraMetadata &frame,
SharedParameters::Lock l(client->getParameters());
entry = frame.find(ANDROID_STATS_FACE_RECTANGLES);
if (entry.count == 0) {
- ALOGE("%s: Camera %d: Unable to read face rectangles",
- __FUNCTION__, client->getCameraId());
+ // No faces this frame
return res;
}
metadata.number_of_faces = entry.count / 4;
@@ -220,7 +219,13 @@ status_t FrameProcessor::processFaceDetect(const CameraMetadata &frame,
faces.setCapacity(metadata.number_of_faces);
- for (int i = 0; i < metadata.number_of_faces; i++) {
+ size_t maxFaces = metadata.number_of_faces;
+ for (size_t i = 0; i < maxFaces; i++) {
+ if (faceScores[i] == 0) {
+ metadata.number_of_faces--;
+ continue;
+ }
+
camera_face_t face;
face.rect[0] = l.mParameters.arrayXToNormalized(faceRects[i*4 + 0]);
diff --git a/services/camera/libcameraservice/camera2/Parameters.cpp b/services/camera/libcameraservice/camera2/Parameters.cpp
index c07a6ac..0a72c5f 100644
--- a/services/camera/libcameraservice/camera2/Parameters.cpp
+++ b/services/camera/libcameraservice/camera2/Parameters.cpp
@@ -750,12 +750,12 @@ status_t Parameters::initialize(const CameraMetadata *info) {
previewCallbackFlags = 0;
char value[PROPERTY_VALUE_MAX];
- property_get("camera.zsl_mode", value, "0");
+ property_get("camera.disable_zsl_mode", value, "0");
if (!strcmp(value,"1")) {
- ALOGI("Camera %d: Enabling ZSL mode", cameraId);
- zslMode = true;
- } else {
+ ALOGI("Camera %d: Disabling ZSL mode", cameraId);
zslMode = false;
+ } else {
+ zslMode = true;
}
lightFx = LIGHTFX_NONE;
@@ -1380,8 +1380,11 @@ status_t Parameters::updateRequest(CameraMetadata *request) const {
&reqControlMode, 1);
if (res != OK) return res;
- uint8_t reqSceneMode = enableFaceDetect ?
- (uint8_t)ANDROID_CONTROL_SCENE_MODE_FACE_PRIORITY : sceneMode;
+ uint8_t reqSceneMode =
+ (sceneMode !=
+ (uint8_t)ANDROID_CONTROL_SCENE_MODE_UNSUPPORTED) ? sceneMode :
+ enableFaceDetect ? (uint8_t)ANDROID_CONTROL_SCENE_MODE_FACE_PRIORITY :
+ (uint8_t)ANDROID_CONTROL_SCENE_MODE_UNSUPPORTED;
res = request->update(ANDROID_CONTROL_SCENE_MODE,
&reqSceneMode, 1);
if (res != OK) return res;
diff --git a/services/camera/libcameraservice/camera2/ZslProcessor.cpp b/services/camera/libcameraservice/camera2/ZslProcessor.cpp
index f17b5d3..8906cd7 100644
--- a/services/camera/libcameraservice/camera2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/ZslProcessor.cpp
@@ -87,12 +87,14 @@ void ZslProcessor::onFrameAvailable(int32_t frameId, CameraMetadata &frame) {
void ZslProcessor::onBufferReleased(buffer_handle_t *handle) {
Mutex::Autolock l(mInputMutex);
- buffer_handle_t *expectedHandle =
- &(mZslQueue[mZslQueueTail].buffer.mGraphicBuffer->handle);
-
- if (handle != expectedHandle) {
- ALOGE("%s: Expected buffer %p, got buffer %p",
- __FUNCTION__, expectedHandle, handle);
+ // Verify that the buffer is in our queue
+ size_t i = 0;
+ for (; i < mZslQueue.size(); i++) {
+ if (&(mZslQueue[i].buffer.mGraphicBuffer->handle) == handle) break;
+ }
+ if (i == mZslQueue.size()) {
+ ALOGW("%s: Released buffer %p not found in queue",
+ __FUNCTION__, handle);
}
mState = RUNNING;
@@ -232,7 +234,12 @@ status_t ZslProcessor::pushToReprocess(int32_t requestId) {
status_t res;
sp<Camera2Client> client = mClient.promote();
- if (client == 0) return false;
+ if (client == 0) return INVALID_OPERATION;
+
+ IF_ALOGV() {
+ dumpZslQueue(-1);
+ }
+
if (mZslQueueTail != mZslQueueHead) {
CameraMetadata request;
@@ -242,9 +249,26 @@ status_t ZslProcessor::pushToReprocess(int32_t requestId) {
index = (index + 1) % kZslBufferDepth;
}
if (request.isEmpty()) {
- ALOGE("No request in ZSL queue to send!");
+ ALOGV("%s: ZSL queue has no valid frames to send yet.",
+ __FUNCTION__);
+ return NOT_ENOUGH_DATA;
+ }
+ // Verify that the frame is reasonable for reprocessing
+
+ camera_metadata_entry_t entry;
+ entry = request.find(ANDROID_CONTROL_AE_STATE);
+ if (entry.count == 0) {
+ ALOGE("%s: ZSL queue frame has no AE state field!",
+ __FUNCTION__);
return BAD_VALUE;
}
+ if (entry.data.u8[0] != ANDROID_CONTROL_AE_STATE_CONVERGED &&
+ entry.data.u8[0] != ANDROID_CONTROL_AE_STATE_LOCKED) {
+ ALOGV("%s: ZSL queue frame AE state is %d, need full capture",
+ __FUNCTION__, entry.data.u8[0]);
+ return NOT_ENOUGH_DATA;
+ }
+
buffer_handle_t *handle =
&(mZslQueue[index].buffer.mGraphicBuffer->handle);
@@ -282,13 +306,15 @@ status_t ZslProcessor::pushToReprocess(int32_t requestId) {
mState = LOCKED;
} else {
- ALOGE("%s: Nothing to push", __FUNCTION__);
- return BAD_VALUE;
+ ALOGV("%s: No ZSL buffers yet", __FUNCTION__);
+ return NOT_ENOUGH_DATA;
}
return OK;
}
void ZslProcessor::dump(int fd, const Vector<String16>& args) const {
+ Mutex::Autolock l(mInputMutex);
+ dumpZslQueue(fd);
}
bool ZslProcessor::threadLoop() {
@@ -413,5 +439,37 @@ void ZslProcessor::findMatchesLocked() {
}
}
+void ZslProcessor::dumpZslQueue(int fd) const {
+ String8 header("ZSL queue contents:");
+ String8 indent(" ");
+ ALOGV("%s", header.string());
+ if (fd != -1) {
+ header = indent + header + "\n";
+ write(fd, header.string(), header.size());
+ }
+ for (size_t i = 0; i < mZslQueue.size(); i++) {
+ const ZslPair &queueEntry = mZslQueue[i];
+ nsecs_t bufferTimestamp = queueEntry.buffer.mTimestamp;
+ camera_metadata_ro_entry_t entry;
+ nsecs_t frameTimestamp = 0;
+ int frameAeState = -1;
+ if (!queueEntry.frame.isEmpty()) {
+ entry = queueEntry.frame.find(ANDROID_SENSOR_TIMESTAMP);
+ if (entry.count > 0) frameTimestamp = entry.data.i64[0];
+ entry = queueEntry.frame.find(ANDROID_CONTROL_AE_STATE);
+ if (entry.count > 0) frameAeState = entry.data.u8[0];
+ }
+ String8 result =
+ String8::format(" %d: b: %lld\tf: %lld, AE state: %d", i,
+ bufferTimestamp, frameTimestamp, frameAeState);
+ ALOGV("%s", result.string());
+ if (fd != -1) {
+ result = indent + result + "\n";
+ write(fd, result.string(), result.size());
+ }
+
+ }
+}
+
}; // namespace camera2
}; // namespace android
diff --git a/services/camera/libcameraservice/camera2/ZslProcessor.h b/services/camera/libcameraservice/camera2/ZslProcessor.h
index b60f61b..268f4f5 100644
--- a/services/camera/libcameraservice/camera2/ZslProcessor.h
+++ b/services/camera/libcameraservice/camera2/ZslProcessor.h
@@ -110,6 +110,8 @@ class ZslProcessor:
// Match up entries from frame list to buffers in ZSL queue
void findMatchesLocked();
+
+ void dumpZslQueue(int id) const;
};