Merge "Camera2: Emit FaceDetection events for all except repeating 0-face frames" into jb-mr1-dev
diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp
index b76572c..0282036 100644
--- a/drm/common/IDrmManagerService.cpp
+++ b/drm/common/IDrmManagerService.cpp
@@ -310,7 +310,13 @@
const String8 key = keyIt.next();
data.writeString8(key);
const String8 value = drmInforequest->get(key);
- data.writeString8((value == String8("")) ? String8("NULL") : value);
+ if (key == String8("FileDescriptorKey")) {
+ int fd = -1;
+ sscanf(value.string(), "FileDescriptor[%d]", &fd);
+ data.writeFileDescriptor(fd);
+ } else {
+ data.writeString8((value == String8("")) ? String8("NULL") : value);
+ }
}
remote()->transact(ACQUIRE_DRM_INFO, data, &reply);
@@ -1002,8 +1008,15 @@
const int size = data.readInt32();
for (int index = 0; index < size; ++index) {
const String8 key(data.readString8());
- const String8 value(data.readString8());
- drmInfoRequest->put(key, (value == String8("NULL")) ? String8("") : value);
+ if (key == String8("FileDescriptorKey")) {
+ char buffer[16];
+ int fd = data.readFileDescriptor();
+ sprintf(buffer, "%lu", (unsigned long)fd);
+ drmInfoRequest->put(key, String8(buffer));
+ } else {
+ const String8 value(data.readString8());
+ drmInfoRequest->put(key, (value == String8("NULL")) ? String8("") : value);
+ }
}
DrmInfo* drmInfo = acquireDrmInfo(uniqueId, drmInfoRequest);
@@ -1505,4 +1518,3 @@
return BBinder::onTransact(code, data, reply, flags);
}
}
-
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
index 6090176..7a89135 100644
--- a/include/media/IMediaPlayerService.h
+++ b/include/media/IMediaPlayerService.h
@@ -64,12 +64,6 @@
virtual sp<IRemoteDisplay> listenForRemoteDisplay(const sp<IRemoteDisplayClient>& client,
const String8& iface) = 0;
- // If iface == NULL, disable remote display, otherwise
- // iface should be of the form "x.x.x.x:y", i.e. ip address
- // of the local interface to bind to and the port number
- // to listen on.
- virtual status_t enableRemoteDisplay(const char *iface) = 0;
-
// codecs and audio devices usage tracking for the battery app
enum BatteryDataBits {
// tracking audio codec
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
index c702d76..c0a0260 100644
--- a/media/libmedia/IMediaPlayerService.cpp
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -43,7 +43,6 @@
GET_OMX,
MAKE_CRYPTO,
MAKE_HDCP,
- ENABLE_REMOTE_DISPLAY,
ADD_BATTERY_DATA,
PULL_BATTERY_DATA,
LISTEN_FOR_REMOTE_DISPLAY,
@@ -134,21 +133,6 @@
return interface_cast<IHDCP>(reply.readStrongBinder());
}
- virtual status_t enableRemoteDisplay(const char *iface) {
- Parcel data, reply;
- data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
-
- if (iface != NULL) {
- data.writeInt32(1);
- data.writeCString(iface);
- } else {
- data.writeInt32(0);
- }
-
- remote()->transact(ENABLE_REMOTE_DISPLAY, data, &reply);
- return reply.readInt32();
- }
-
virtual void addBatteryData(uint32_t params) {
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
@@ -252,15 +236,6 @@
reply->writeStrongBinder(hdcp->asBinder());
return NO_ERROR;
} break;
- case ENABLE_REMOTE_DISPLAY: {
- CHECK_INTERFACE(IMediaPlayerService, data, reply);
- const char *iface = NULL;
- if (data.readInt32()) {
- iface = data.readCString();
- }
- reply->writeInt32(enableRemoteDisplay(iface));
- return NO_ERROR;
- } break;
case ADD_BATTERY_DATA: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
uint32_t params = data.readInt32();
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index eaa44e2..9bedff1 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -295,31 +295,6 @@
return new RemoteDisplay(client, iface.string());
}
-// TODO: delete this method
-status_t MediaPlayerService::enableRemoteDisplay(const char *iface) {
- if (!checkPermission("android.permission.CONTROL_WIFI_DISPLAY")) {
- return PERMISSION_DENIED;
- }
-
- Mutex::Autolock autoLock(mLock);
-
- if (iface != NULL) {
- if (mRemoteDisplay != NULL) {
- return INVALID_OPERATION;
- }
-
- mRemoteDisplay = new RemoteDisplay(NULL /* client */, iface);
- return OK;
- }
-
- if (mRemoteDisplay != NULL) {
- mRemoteDisplay->dispose();
- mRemoteDisplay.clear();
- }
-
- return OK;
-}
-
status_t MediaPlayerService::AudioCache::dump(int fd, const Vector<String16>& args) const
{
const size_t SIZE = 256;
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 6105ce4..fd648df 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -44,7 +44,6 @@
class IRemoteDisplay;
class IRemoteDisplayClient;
class MediaRecorderClient;
-struct RemoteDisplay;
#define CALLBACK_ANTAGONIZER 0
#if CALLBACK_ANTAGONIZER
@@ -254,8 +253,6 @@
virtual sp<IRemoteDisplay> listenForRemoteDisplay(const sp<IRemoteDisplayClient>& client,
const String8& iface);
- virtual status_t enableRemoteDisplay(const char *iface);
-
virtual status_t dump(int fd, const Vector<String16>& args);
void removeClient(wp<Client> client);
@@ -431,7 +428,6 @@
int32_t mNextConnId;
sp<IOMX> mOMX;
sp<ICrypto> mCrypto;
- sp<RemoteDisplay> mRemoteDisplay;
};
// ----------------------------------------------------------------------------
diff --git a/media/libstagefright/wifi-display/Android.mk b/media/libstagefright/wifi-display/Android.mk
index a392532..f8e4219 100644
--- a/media/libstagefright/wifi-display/Android.mk
+++ b/media/libstagefright/wifi-display/Android.mk
@@ -14,7 +14,6 @@
source/MediaPuller.cpp \
source/PlaybackSession.cpp \
source/RepeaterSource.cpp \
- source/Serializer.cpp \
source/TSPacketizer.cpp \
source/WifiDisplaySource.cpp \
diff --git a/media/libstagefright/wifi-display/source/Converter.cpp b/media/libstagefright/wifi-display/source/Converter.cpp
index 390b2e2..c5c47d6 100644
--- a/media/libstagefright/wifi-display/source/Converter.cpp
+++ b/media/libstagefright/wifi-display/source/Converter.cpp
@@ -115,7 +115,7 @@
mOutputFormat->setString("mime", outputMIME.c_str());
int32_t audioBitrate = getBitrate("media.wfd.audio-bitrate", 64000);
- int32_t videoBitrate = getBitrate("media.wfd.video-bitrate", 10000000);
+ int32_t videoBitrate = getBitrate("media.wfd.video-bitrate", 2500000);
ALOGI("using audio bitrate of %d bps, video bitrate of %d bps",
audioBitrate, videoBitrate);
@@ -328,4 +328,3 @@
}
} // namespace android
-
diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.cpp b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
index ceea08f..24f33df 100644
--- a/media/libstagefright/wifi-display/source/PlaybackSession.cpp
+++ b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
@@ -23,7 +23,6 @@
#include "Converter.h"
#include "MediaPuller.h"
#include "RepeaterSource.h"
-#include "Serializer.h"
#include "TSPacketizer.h"
#include <binder/IServiceManager.h>
@@ -47,9 +46,6 @@
#include <OMX_IVCommon.h>
-//#define FAKE_VIDEO 1
-#define USE_SERIALIZER 0
-
namespace android {
static size_t kMaxRTPPacketSize = 1500;
@@ -192,12 +188,10 @@
const sp<ANetworkSession> &netSession,
const sp<AMessage> ¬ify,
const in_addr &interfaceAddr,
- bool legacyMode,
const sp<IHDCP> &hdcp)
: mNetSession(netSession),
mNotify(notify),
mInterfaceAddr(interfaceAddr),
- mLegacyMode(legacyMode),
mHDCP(hdcp),
mLastLifesignUs(),
mVideoTrackIndex(-1),
@@ -209,11 +203,18 @@
mRTPPort(0),
mRTPSessionID(0),
mRTCPSessionID(0),
+#if ENABLE_RETRANSMISSION
+ mRTPRetransmissionSessionID(0),
+ mRTCPRetransmissionSessionID(0),
+#endif
mClientRTPPort(0),
mClientRTCPPort(0),
mRTPConnected(false),
mRTCPConnected(false),
mRTPSeqNo(0),
+#if ENABLE_RETRANSMISSION
+ mRTPRetransmissionSeqNo(0),
+#endif
mLastNTPTime(0),
mLastRTPTime(0),
mNumRTPSent(0),
@@ -279,6 +280,15 @@
sp<AMessage> rtpNotify = new AMessage(kWhatRTPNotify, id());
sp<AMessage> rtcpNotify = new AMessage(kWhatRTCPNotify, id());
+
+#if ENABLE_RETRANSMISSION
+ sp<AMessage> rtpRetransmissionNotify =
+ new AMessage(kWhatRTPRetransmissionNotify, id());
+
+ sp<AMessage> rtcpRetransmissionNotify =
+ new AMessage(kWhatRTCPRetransmissionNotify, id());
+#endif
+
for (serverRtp = 15550;; serverRtp += 2) {
int32_t rtpSession;
if (mTransportMode == TRANSPORT_UDP) {
@@ -296,39 +306,76 @@
continue;
}
- if (clientRtcp < 0) {
- // No RTCP.
+ int32_t rtcpSession = 0;
- mRTPPort = serverRtp;
- mRTPSessionID = rtpSession;
- mRTCPSessionID = 0;
+ if (clientRtcp >= 0) {
+ if (mTransportMode == TRANSPORT_UDP) {
+ err = mNetSession->createUDPSession(
+ serverRtp + 1, clientIP, clientRtcp,
+ rtcpNotify, &rtcpSession);
+ } else {
+ err = mNetSession->createTCPDatagramSession(
+ serverRtp + 1, clientIP, clientRtcp,
+ rtcpNotify, &rtcpSession);
+ }
- ALOGI("rtpSessionId = %d", rtpSession);
- break;
+ if (err != OK) {
+ ALOGI("failed to create RTCP socket on port %d", serverRtp + 1);
+
+ mNetSession->destroySession(rtpSession);
+ continue;
+ }
}
- int32_t rtcpSession;
+#if ENABLE_RETRANSMISSION
if (mTransportMode == TRANSPORT_UDP) {
+ int32_t rtpRetransmissionSession;
+
err = mNetSession->createUDPSession(
- serverRtp + 1, clientIP, clientRtcp,
- rtcpNotify, &rtcpSession);
- } else {
- err = mNetSession->createTCPDatagramSession(
- serverRtp + 1, clientIP, clientRtcp,
- rtcpNotify, &rtcpSession);
+ serverRtp + kRetransmissionPortOffset,
+ clientIP,
+ clientRtp + kRetransmissionPortOffset,
+ rtpRetransmissionNotify,
+ &rtpRetransmissionSession);
+
+ if (err != OK) {
+ mNetSession->destroySession(rtcpSession);
+ mNetSession->destroySession(rtpSession);
+ continue;
+ }
+
+ CHECK_GE(clientRtcp, 0);
+
+ int32_t rtcpRetransmissionSession;
+ err = mNetSession->createUDPSession(
+ serverRtp + 1 + kRetransmissionPortOffset,
+ clientIP,
+ clientRtp + 1 + kRetransmissionPortOffset,
+ rtcpRetransmissionNotify,
+ &rtcpRetransmissionSession);
+
+ if (err != OK) {
+ mNetSession->destroySession(rtpRetransmissionSession);
+ mNetSession->destroySession(rtcpSession);
+ mNetSession->destroySession(rtpSession);
+ continue;
+ }
+
+ mRTPRetransmissionSessionID = rtpRetransmissionSession;
+ mRTCPRetransmissionSessionID = rtcpRetransmissionSession;
+
+ ALOGI("rtpRetransmissionSessionID = %d, "
+ "rtcpRetransmissionSessionID = %d",
+ rtpRetransmissionSession, rtcpRetransmissionSession);
}
+#endif
- if (err == OK) {
- mRTPPort = serverRtp;
- mRTPSessionID = rtpSession;
- mRTCPSessionID = rtcpSession;
+ mRTPPort = serverRtp;
+ mRTPSessionID = rtpSession;
+ mRTCPSessionID = rtcpSession;
- ALOGI("rtpSessionID = %d, rtcpSessionID = %d", rtpSession, rtcpSession);
- break;
- }
-
- ALOGI("failed to create RTCP socket on port %d", serverRtp + 1);
- mNetSession->destroySession(rtpSession);
+ ALOGI("rtpSessionID = %d, rtcpSessionID = %d", rtpSession, rtcpSession);
+ break;
}
if (mRTPPort == 0) {
@@ -404,10 +451,6 @@
scheduleSendSR();
}
- if (mSerializer != NULL) {
- return mSerializer->start();
- }
-
for (size_t i = 0; i < mTracks.size(); ++i) {
status_t err = mTracks.editValueAt(i)->start();
@@ -438,28 +481,17 @@
mPacketizer.clear();
- if (mSerializer != NULL) {
- mSerializer->stop();
-
- looper()->unregisterHandler(mSerializer->id());
- mSerializer.clear();
- }
-
mTracks.clear();
- if (mSerializerLooper != NULL) {
- mSerializerLooper->stop();
- mSerializerLooper.clear();
+#if ENABLE_RETRANSMISSION
+ if (mRTCPRetransmissionSessionID != 0) {
+ mNetSession->destroySession(mRTCPRetransmissionSessionID);
}
- if (mLegacyMode) {
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder = sm->getService(String16("SurfaceFlinger"));
- sp<ISurfaceComposer> service = interface_cast<ISurfaceComposer>(binder);
- CHECK(service != NULL);
-
- service->connectDisplay(NULL);
+ if (mRTPRetransmissionSessionID != 0) {
+ mNetSession->destroySession(mRTPRetransmissionSessionID);
}
+#endif
if (mRTCPSessionID != 0) {
mNetSession->destroySession(mRTCPSessionID);
@@ -477,6 +509,10 @@
switch (msg->what()) {
case kWhatRTPNotify:
case kWhatRTCPNotify:
+#if ENABLE_RETRANSMISSION
+ case kWhatRTPRetransmissionNotify:
+ case kWhatRTCPRetransmissionNotify:
+#endif
{
int32_t reason;
CHECK(msg->findInt32("reason", &reason));
@@ -496,8 +532,11 @@
AString detail;
CHECK(msg->findString("detail", &detail));
- if (msg->what() == kWhatRTPNotify
- && !errorOccuredDuringSend) {
+ if ((msg->what() == kWhatRTPNotify
+#if ENABLE_RETRANSMISSION
+ || msg->what() == kWhatRTPRetransmissionNotify
+#endif
+ ) && !errorOccuredDuringSend) {
// This is ok, we don't expect to receive anything on
// the RTP socket.
break;
@@ -518,6 +557,13 @@
} else if (sessionID == mRTCPSessionID) {
mRTCPSessionID = 0;
}
+#if ENABLE_RETRANSMISSION
+ else if (sessionID == mRTPRetransmissionSessionID) {
+ mRTPRetransmissionSessionID = 0;
+ } else if (sessionID == mRTCPRetransmissionSessionID) {
+ mRTCPRetransmissionSessionID = 0;
+ }
+#endif
// Inform WifiDisplaySource of our premature death (wish).
sp<AMessage> notify = mNotify->dup();
@@ -535,7 +581,12 @@
CHECK(msg->findBuffer("data", &data));
status_t err;
- if (msg->what() == kWhatRTCPNotify) {
+ if (msg->what() == kWhatRTCPNotify
+#if ENABLE_RETRANSMISSION
+ || msg->what() == kWhatRTCPRetransmissionNotify
+#endif
+ )
+ {
err = parseRTCP(data);
}
break;
@@ -587,26 +638,19 @@
break;
}
- case kWhatSerializerNotify:
+ case kWhatMediaPullerNotify:
{
int32_t what;
CHECK(msg->findInt32("what", &what));
- if (what == Serializer::kWhatEOS) {
+ if (what == MediaPuller::kWhatEOS) {
ALOGI("input eos");
for (size_t i = 0; i < mTracks.size(); ++i) {
-#if FAKE_VIDEO
- sp<AMessage> msg = new AMessage(kWhatConverterNotify, id());
- msg->setInt32("what", Converter::kWhatEOS);
- msg->setSize("trackIndex", i);
- msg->post();
-#else
mTracks.valueAt(i)->converter()->signalEOS();
-#endif
}
} else {
- CHECK_EQ(what, Serializer::kWhatAccessUnit);
+ CHECK_EQ(what, MediaPuller::kWhatAccessUnit);
size_t trackIndex;
CHECK(msg->findSize("trackIndex", &trackIndex));
@@ -614,25 +658,8 @@
sp<ABuffer> accessUnit;
CHECK(msg->findBuffer("accessUnit", &accessUnit));
-#if FAKE_VIDEO
- int64_t timeUs;
- CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
-
- void *mbuf;
- CHECK(accessUnit->meta()->findPointer("mediaBuffer", &mbuf));
-
- ((MediaBuffer *)mbuf)->release();
- mbuf = NULL;
-
- sp<AMessage> msg = new AMessage(kWhatConverterNotify, id());
- msg->setInt32("what", Converter::kWhatAccessUnit);
- msg->setSize("trackIndex", trackIndex);
- msg->setBuffer("accessUnit", accessUnit);
- msg->post();
-#else
mTracks.valueFor(trackIndex)->converter()
->feedAccessUnit(accessUnit);
-#endif
}
break;
}
@@ -779,11 +806,9 @@
ssize_t index = mTracks.indexOfKey(trackIndex);
CHECK_GE(index, 0);
-#if !FAKE_VIDEO
const sp<Converter> &converter =
mTracks.valueAt(index)->converter();
looper()->unregisterHandler(converter->id());
-#endif
mTracks.removeItemsAt(index);
@@ -813,13 +838,8 @@
}
status_t WifiDisplaySource::PlaybackSession::setupPacketizer() {
- sp<AMessage> msg = new AMessage(kWhatSerializerNotify, id());
-
mPacketizer = new TSPacketizer;
-#if FAKE_VIDEO
- return addFakeSources();
-#else
status_t err = addVideoSource();
if (err != OK) {
@@ -827,85 +847,10 @@
}
return addAudioSource();
-#endif
-}
-
-status_t WifiDisplaySource::PlaybackSession::addFakeSources() {
-#if FAKE_VIDEO
- mSerializerLooper = new ALooper;
- mSerializerLooper->setName("serializer_looper");
- mSerializerLooper->start();
-
- sp<AMessage> msg = new AMessage(kWhatSerializerNotify, id());
- mSerializer = new Serializer(
- true /* throttled */, msg);
-
- mSerializerLooper->registerHandler(mSerializer);
-
- DataSource::RegisterDefaultSniffers();
-
- sp<DataSource> dataSource =
- DataSource::CreateFromURI(
- "/system/etc/inception_1500.mp4");
-
- CHECK(dataSource != NULL);
-
- sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
- CHECK(extractor != NULL);
-
- bool haveAudio = false;
- bool haveVideo = false;
- for (size_t i = 0; i < extractor->countTracks(); ++i) {
- sp<MetaData> meta = extractor->getTrackMetaData(i);
-
- const char *mime;
- CHECK(meta->findCString(kKeyMIMEType, &mime));
-
- bool useTrack = false;
- if (!strncasecmp(mime, "audio/", 6) && !haveAudio) {
- useTrack = true;
- haveAudio = true;
- } else if (!strncasecmp(mime, "video/", 6) && !haveVideo) {
- useTrack = true;
- haveVideo = true;
- }
-
- if (!useTrack) {
- continue;
- }
-
- sp<MediaSource> source = extractor->getTrack(i);
-
- ssize_t index = mSerializer->addSource(source);
- CHECK_GE(index, 0);
-
- sp<AMessage> format;
- status_t err = convertMetaDataToMessage(source->getFormat(), &format);
- CHECK_EQ(err, (status_t)OK);
-
- mTracks.add(index, new Track(format));
- }
- CHECK(haveAudio || haveVideo);
-#endif
-
- return OK;
}
status_t WifiDisplaySource::PlaybackSession::addSource(
bool isVideo, const sp<MediaSource> &source, size_t *numInputBuffers) {
-#if USE_SERIALIZER
- if (mSerializer == NULL) {
- mSerializerLooper = new ALooper;
- mSerializerLooper->setName("serializer_looper");
- mSerializerLooper->start();
-
- sp<AMessage> msg = new AMessage(kWhatSerializerNotify, id());
- mSerializer = new Serializer(
- false /* throttled */, msg);
-
- mSerializerLooper->registerHandler(mSerializer);
- }
-#else
sp<ALooper> pullLooper = new ALooper;
pullLooper->setName("pull_looper");
@@ -913,7 +858,6 @@
false /* runOnCallingThread */,
false /* canCallJava */,
PRIORITY_DEFAULT);
-#endif
sp<ALooper> codecLooper = new ALooper;
codecLooper->setName("codec_looper");
@@ -927,16 +871,12 @@
sp<AMessage> notify;
-#if USE_SERIALIZER
- trackIndex = mSerializer->addSource(source);
-#else
trackIndex = mTracks.size();
- notify = new AMessage(kWhatSerializerNotify, id());
+ notify = new AMessage(kWhatMediaPullerNotify, id());
notify->setSize("trackIndex", trackIndex);
sp<MediaPuller> puller = new MediaPuller(source, notify);
pullLooper->registerHandler(puller);
-#endif
sp<AMessage> format;
status_t err = convertMetaDataToMessage(source->getFormat(), &format);
@@ -962,11 +902,7 @@
*numInputBuffers = converter->getInputBufferCount();
}
-#if USE_SERIALIZER
- mTracks.add(trackIndex, new Track(NULL, codecLooper, NULL, converter));
-#else
mTracks.add(trackIndex, new Track(pullLooper, codecLooper, puller, converter));
-#endif
if (isVideo) {
mVideoTrackIndex = trackIndex;
@@ -988,21 +924,11 @@
return err;
}
- // Add one reference to account for the serializer.
err = source->setMaxAcquiredBufferCount(numInputBuffers);
CHECK_EQ(err, (status_t)OK);
mBufferQueue = source->getBufferQueue();
- if (mLegacyMode) {
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder = sm->getService(String16("SurfaceFlinger"));
- sp<ISurfaceComposer> service = interface_cast<ISurfaceComposer>(binder);
- CHECK(service != NULL);
-
- service->connectDisplay(mBufferQueue);
- }
-
return OK;
}
@@ -1029,11 +955,11 @@
}
int32_t WifiDisplaySource::PlaybackSession::width() const {
- return mLegacyMode ? 720 : 1280;
+ return 1280;
}
int32_t WifiDisplaySource::PlaybackSession::height() const {
- return mLegacyMode ? 1280 : 720;
+ return 720;
}
void WifiDisplaySource::PlaybackSession::scheduleSendSR() {
@@ -1293,9 +1219,11 @@
case 204: // APP
break;
+#if ENABLE_RETRANSMISSION
case 205: // TSFB (transport layer specific feedback)
parseTSFB(data, headerLength);
break;
+#endif
case 206: // PSFB (payload specific feedback)
hexdump(data, headerLength);
@@ -1316,6 +1244,7 @@
return OK;
}
+#if ENABLE_RETRANSMISSION
status_t WifiDisplaySource::PlaybackSession::parseTSFB(
const uint8_t *data, size_t size) {
if ((data[0] & 0x1f) != 1) {
@@ -1332,31 +1261,64 @@
uint16_t blp = U16_AT(&data[i + 2]);
List<sp<ABuffer> >::iterator it = mHistory.begin();
- bool found = false;
+ bool foundSeqNo = false;
while (it != mHistory.end()) {
const sp<ABuffer> &buffer = *it;
uint16_t bufferSeqNo = buffer->int32Data() & 0xffff;
+ bool retransmit = false;
if (bufferSeqNo == seqNo) {
- sendPacket(mRTPSessionID, buffer->data(), buffer->size());
+ retransmit = true;
+ } else if (blp != 0) {
+ for (size_t i = 0; i < 16; ++i) {
+ if ((blp & (1 << i))
+ && (bufferSeqNo == ((seqNo + i + 1) & 0xffff))) {
+ blp &= ~(1 << i);
+ retransmit = true;
+ }
+ }
+ }
- found = true;
- break;
+ if (retransmit) {
+ ALOGI("retransmitting seqNo %d", bufferSeqNo);
+
+ sp<ABuffer> retransRTP = new ABuffer(2 + buffer->size());
+ uint8_t *rtp = retransRTP->data();
+ memcpy(rtp, buffer->data(), 12);
+ rtp[2] = (mRTPRetransmissionSeqNo >> 8) & 0xff;
+ rtp[3] = mRTPRetransmissionSeqNo & 0xff;
+ rtp[12] = (bufferSeqNo >> 8) & 0xff;
+ rtp[13] = bufferSeqNo & 0xff;
+ memcpy(&rtp[14], buffer->data() + 12, buffer->size() - 12);
+
+ ++mRTPRetransmissionSeqNo;
+
+ sendPacket(
+ mRTPRetransmissionSessionID,
+ retransRTP->data(), retransRTP->size());
+
+ if (bufferSeqNo == seqNo) {
+ foundSeqNo = true;
+ }
+
+ if (foundSeqNo && blp == 0) {
+ break;
+ }
}
++it;
}
- if (found) {
- ALOGI("retransmitting seqNo %d", seqNo);
- } else {
- ALOGI("seqNo %d no longer available", seqNo);
+ if (!foundSeqNo || blp != 0) {
+ ALOGI("Some sequence numbers were no longer available for "
+ "retransmission");
}
}
return OK;
}
+#endif
void WifiDisplaySource::PlaybackSession::requestIDRFrame() {
for (size_t i = 0; i < mTracks.size(); ++i) {
diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.h b/media/libstagefright/wifi-display/source/PlaybackSession.h
index 0823ee6..f2090b4 100644
--- a/media/libstagefright/wifi-display/source/PlaybackSession.h
+++ b/media/libstagefright/wifi-display/source/PlaybackSession.h
@@ -28,10 +28,10 @@
struct ISurfaceTexture;
struct MediaPuller;
struct MediaSource;
-struct Serializer;
struct TSPacketizer;
-#define LOG_TRANSPORT_STREAM 0
+#define LOG_TRANSPORT_STREAM 0
+#define ENABLE_RETRANSMISSION 0
// Encapsulates the state of an RTP/RTCP session in the context of wifi
// display.
@@ -40,7 +40,6 @@
const sp<ANetworkSession> &netSession,
const sp<AMessage> ¬ify,
const struct in_addr &interfaceAddr,
- bool legacyMode,
const sp<IHDCP> &hdcp);
enum TransportMode {
@@ -86,7 +85,11 @@
kWhatSendSR,
kWhatRTPNotify,
kWhatRTCPNotify,
- kWhatSerializerNotify,
+#if ENABLE_RETRANSMISSION
+ kWhatRTPRetransmissionNotify,
+ kWhatRTCPRetransmissionNotify,
+#endif
+ kWhatMediaPullerNotify,
kWhatConverterNotify,
kWhatUpdateSurface,
kWhatFinishPlay,
@@ -96,16 +99,17 @@
static const uint32_t kSourceID = 0xdeadbeef;
static const size_t kMaxHistoryLength = 128;
+#if ENABLE_RETRANSMISSION
+ static const size_t kRetransmissionPortOffset = 120;
+#endif
+
sp<ANetworkSession> mNetSession;
sp<AMessage> mNotify;
in_addr mInterfaceAddr;
- bool mLegacyMode;
sp<IHDCP> mHDCP;
int64_t mLastLifesignUs;
- sp<ALooper> mSerializerLooper;
- sp<Serializer> mSerializer;
sp<TSPacketizer> mPacketizer;
sp<BufferQueue> mBufferQueue;
@@ -128,12 +132,20 @@
int32_t mRTPSessionID;
int32_t mRTCPSessionID;
+#if ENABLE_RETRANSMISSION
+ int32_t mRTPRetransmissionSessionID;
+ int32_t mRTCPRetransmissionSessionID;
+#endif
+
int32_t mClientRTPPort;
int32_t mClientRTCPPort;
bool mRTPConnected;
bool mRTCPConnected;
uint32_t mRTPSeqNo;
+#if ENABLE_RETRANSMISSION
+ uint32_t mRTPRetransmissionSeqNo;
+#endif
uint64_t mLastNTPTime;
uint32_t mLastRTPTime;
@@ -161,8 +173,6 @@
status_t setupPacketizer();
- status_t addFakeSources();
-
status_t addSource(
bool isVideo,
const sp<MediaSource> &source,
@@ -177,7 +187,10 @@
void scheduleSendSR();
status_t parseRTCP(const sp<ABuffer> &buffer);
+
+#if ENABLE_RETRANSMISSION
status_t parseTSFB(const uint8_t *data, size_t size);
+#endif
status_t sendPacket(int32_t sessionID, const void *data, size_t size);
status_t onFinishPlay();
diff --git a/media/libstagefright/wifi-display/source/Serializer.cpp b/media/libstagefright/wifi-display/source/Serializer.cpp
deleted file mode 100644
index 598fd3e..0000000
--- a/media/libstagefright/wifi-display/source/Serializer.cpp
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright 2012, 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "Serializer"
-#include <utils/Log.h>
-
-#include "Serializer.h"
-
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/MediaSource.h>
-#include <media/stagefright/MetaData.h>
-
-namespace android {
-
-struct Serializer::Track : public RefBase {
- Track(const sp<MediaSource> &source);
-
- status_t start();
- status_t stop();
-
- void readBufferIfNecessary();
-
- bool reachedEOS() const;
- int64_t bufferTimeUs() const;
-
- sp<ABuffer> drainBuffer();
-
-protected:
- virtual ~Track();
-
-private:
- sp<MediaSource> mSource;
- AString mMIME;
-
- bool mStarted;
- status_t mFinalResult;
- MediaBuffer *mBuffer;
- int64_t mBufferTimeUs;
-
- DISALLOW_EVIL_CONSTRUCTORS(Track);
-};
-
-Serializer::Track::Track(const sp<MediaSource> &source)
- : mSource(source),
- mStarted(false),
- mFinalResult(OK),
- mBuffer(NULL),
- mBufferTimeUs(-1ll) {
- const char *mime;
- sp<MetaData> meta = mSource->getFormat();
- CHECK(meta->findCString(kKeyMIMEType, &mime));
-
- mMIME = mime;
-}
-
-Serializer::Track::~Track() {
- stop();
-}
-
-status_t Serializer::Track::start() {
- if (mStarted) {
- return OK;
- }
-
- status_t err = mSource->start();
-
- if (err == OK) {
- mStarted = true;
- }
-
- return err;
-}
-
-status_t Serializer::Track::stop() {
- if (!mStarted) {
- return OK;
- }
-
- if (mBuffer != NULL) {
- mBuffer->release();
- mBuffer = NULL;
-
- mBufferTimeUs = -1ll;
- }
-
- status_t err = mSource->stop();
-
- mStarted = false;
-
- return err;
-}
-
-void Serializer::Track::readBufferIfNecessary() {
- if (mBuffer != NULL) {
- return;
- }
-
- int64_t nowUs = ALooper::GetNowUs();
- mFinalResult = mSource->read(&mBuffer);
- int64_t delayUs = ALooper::GetNowUs() - nowUs;
-
- ALOGV("read on track %s took %lld us, got %d bytes",
- mMIME.c_str(), delayUs, mBuffer->range_length());
-
- if (mFinalResult != OK) {
- ALOGI("read failed w/ err %d", mFinalResult);
- return;
- }
-
- CHECK(mBuffer->meta_data()->findInt64(kKeyTime, &mBufferTimeUs));
-}
-
-bool Serializer::Track::reachedEOS() const {
- return mFinalResult != OK;
-}
-
-int64_t Serializer::Track::bufferTimeUs() const {
- return mBufferTimeUs;
-}
-
-sp<ABuffer> Serializer::Track::drainBuffer() {
- sp<ABuffer> accessUnit = new ABuffer(mBuffer->range_length());
-
- memcpy(accessUnit->data(),
- (const uint8_t *)mBuffer->data() + mBuffer->range_offset(),
- mBuffer->range_length());
-
- accessUnit->meta()->setInt64("timeUs", mBufferTimeUs);
- accessUnit->meta()->setPointer("mediaBuffer", mBuffer);
-
- mBuffer = NULL;
- mBufferTimeUs = -1ll;
-
- return accessUnit;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-Serializer::Serializer(bool throttle, const sp<AMessage> ¬ify)
- : mThrottle(throttle),
- mNotify(notify),
- mPollGeneration(0),
- mStartTimeUs(-1ll) {
-}
-
-Serializer::~Serializer() {
-}
-
-status_t Serializer::postSynchronouslyAndReturnError(
- const sp<AMessage> &msg) {
- sp<AMessage> response;
- status_t err = msg->postAndAwaitResponse(&response);
-
- if (err != OK) {
- return err;
- }
-
- if (!response->findInt32("err", &err)) {
- err = OK;
- }
-
- return err;
-}
-
-ssize_t Serializer::addSource(const sp<MediaSource> &source) {
- sp<AMessage> msg = new AMessage(kWhatAddSource, id());
- msg->setPointer("source", source.get());
-
- sp<AMessage> response;
- status_t err = msg->postAndAwaitResponse(&response);
-
- if (err != OK) {
- return err;
- }
-
- if (!response->findInt32("err", &err)) {
- size_t index;
- CHECK(response->findSize("index", &index));
-
- return index;
- }
-
- return err;
-}
-
-status_t Serializer::start() {
- return postSynchronouslyAndReturnError(new AMessage(kWhatStart, id()));
-}
-
-status_t Serializer::stop() {
- return postSynchronouslyAndReturnError(new AMessage(kWhatStop, id()));
-}
-
-void Serializer::onMessageReceived(const sp<AMessage> &msg) {
- switch (msg->what()) {
- case kWhatAddSource:
- {
- ssize_t index = onAddSource(msg);
-
- sp<AMessage> response = new AMessage;
-
- if (index < 0) {
- response->setInt32("err", index);
- } else {
- response->setSize("index", index);
- }
-
- uint32_t replyID;
- CHECK(msg->senderAwaitsResponse(&replyID));
-
- response->postReply(replyID);
- break;
- }
-
- case kWhatStart:
- case kWhatStop:
- {
- status_t err = (msg->what() == kWhatStart) ? onStart() : onStop();
-
- sp<AMessage> response = new AMessage;
- response->setInt32("err", err);
-
- uint32_t replyID;
- CHECK(msg->senderAwaitsResponse(&replyID));
-
- response->postReply(replyID);
- break;
- }
-
- case kWhatPoll:
- {
- int32_t generation;
- CHECK(msg->findInt32("generation", &generation));
-
- if (generation != mPollGeneration) {
- break;
- }
-
- int64_t delayUs = onPoll();
- if (delayUs >= 0ll) {
- schedulePoll(delayUs);
- }
- break;
- }
-
- default:
- TRESPASS();
- }
-}
-
-ssize_t Serializer::onAddSource(const sp<AMessage> &msg) {
- void *obj;
- CHECK(msg->findPointer("source", &obj));
-
- sp<MediaSource> source = static_cast<MediaSource *>(obj);
-
- sp<Track> track = new Track(source);
- return mTracks.add(track);
-}
-
-status_t Serializer::onStart() {
- status_t err = OK;
- for (size_t i = 0; i < mTracks.size(); ++i) {
- err = mTracks.itemAt(i)->start();
-
- if (err != OK) {
- break;
- }
- }
-
- if (err == OK) {
- schedulePoll();
- }
-
- return err;
-}
-
-status_t Serializer::onStop() {
- for (size_t i = 0; i < mTracks.size(); ++i) {
- mTracks.itemAt(i)->stop();
- }
-
- cancelPoll();
-
- return OK;
-}
-
-int64_t Serializer::onPoll() {
- int64_t minTimeUs = -1ll;
- ssize_t minTrackIndex = -1;
-
- for (size_t i = 0; i < mTracks.size(); ++i) {
- const sp<Track> &track = mTracks.itemAt(i);
-
- track->readBufferIfNecessary();
-
- if (!track->reachedEOS()) {
- int64_t timeUs = track->bufferTimeUs();
-
- if (minTrackIndex < 0 || timeUs < minTimeUs) {
- minTimeUs = timeUs;
- minTrackIndex = i;
- }
- }
- }
-
- if (minTrackIndex < 0) {
- sp<AMessage> notify = mNotify->dup();
- notify->setInt32("what", kWhatEOS);
- notify->post();
-
- return -1ll;
- }
-
- if (mThrottle) {
- int64_t nowUs = ALooper::GetNowUs();
-
- if (mStartTimeUs < 0ll) {
- mStartTimeUs = nowUs;
- }
-
- int64_t lateByUs = nowUs - (minTimeUs + mStartTimeUs);
-
- if (lateByUs < 0ll) {
- // Too early
- return -lateByUs;
- }
- }
-
- sp<AMessage> notify = mNotify->dup();
-
- notify->setInt32("what", kWhatAccessUnit);
- notify->setSize("trackIndex", minTrackIndex);
-
- notify->setBuffer(
- "accessUnit", mTracks.itemAt(minTrackIndex)->drainBuffer());
-
- notify->post();
-
- return 0ll;
-}
-
-void Serializer::schedulePoll(int64_t delayUs) {
- sp<AMessage> msg = new AMessage(kWhatPoll, id());
- msg->setInt32("generation", mPollGeneration);
- msg->post(delayUs);
-}
-
-void Serializer::cancelPoll() {
- ++mPollGeneration;
-}
-
-} // namespace android
diff --git a/media/libstagefright/wifi-display/source/Serializer.h b/media/libstagefright/wifi-display/source/Serializer.h
deleted file mode 100644
index 07950fa..0000000
--- a/media/libstagefright/wifi-display/source/Serializer.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2012, 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SERIALIZER_H_
-
-#define SERIALIZER_H_
-
-#include <media/stagefright/foundation/AHandler.h>
-#include <utils/Vector.h>
-
-namespace android {
-
-struct AMessage;
-struct MediaSource;
-
-// After adding a number of MediaSource objects and starting the Serializer,
-// it'll emit their access units in order of increasing timestamps.
-struct Serializer : public AHandler {
- enum {
- kWhatEOS,
- kWhatAccessUnit
- };
-
- // In throttled operation, data is emitted at a pace corresponding
- // to the incoming media timestamps.
- Serializer(bool throttle, const sp<AMessage> ¬ify);
-
- ssize_t addSource(const sp<MediaSource> &source);
-
- status_t start();
- status_t stop();
-
-protected:
- virtual void onMessageReceived(const sp<AMessage> &what);
- virtual ~Serializer();
-
-private:
- enum {
- kWhatAddSource,
- kWhatStart,
- kWhatStop,
- kWhatPoll
- };
-
- struct Track;
-
- bool mThrottle;
- sp<AMessage> mNotify;
- Vector<sp<Track> > mTracks;
-
- int32_t mPollGeneration;
-
- int64_t mStartTimeUs;
-
- status_t postSynchronouslyAndReturnError(const sp<AMessage> &msg);
-
- ssize_t onAddSource(const sp<AMessage> &msg);
- status_t onStart();
- status_t onStop();
- int64_t onPoll();
-
- void schedulePoll(int64_t delayUs = 0ll);
- void cancelPoll();
-
- DISALLOW_EVIL_CONSTRUCTORS(Serializer);
-};
-
-} // namespace android
-
-#endif // SERIALIZER_H_
-
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
index 133b094..9ad978f 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
@@ -869,6 +869,7 @@
} else if (sscanf(clientPort.c_str(), "%d", &clientRtp) == 1) {
// No RTCP.
clientRtcp = -1;
+ clientRtcp = clientRtp + 1; // XXX
} else {
badRequest = true;
}
@@ -897,7 +898,6 @@
sp<PlaybackSession> playbackSession =
new PlaybackSession(
mNetSession, notify, mInterfaceAddr,
- mClient == NULL, /* legacyMode */
#if REQUIRE_HDCP
mHDCP
#else
diff --git a/media/libstagefright/wifi-display/wfd.cpp b/media/libstagefright/wifi-display/wfd.cpp
index d886f14..011edab 100644
--- a/media/libstagefright/wifi-display/wfd.cpp
+++ b/media/libstagefright/wifi-display/wfd.cpp
@@ -29,27 +29,13 @@
namespace android {
-static void enableDisableRemoteDisplay(const char *iface) {
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder = sm->getService(String16("media.player"));
-
- sp<IMediaPlayerService> service =
- interface_cast<IMediaPlayerService>(binder);
-
- CHECK(service.get() != NULL);
-
- service->enableRemoteDisplay(iface);
-}
-
} // namespace android
static void usage(const char *me) {
fprintf(stderr,
"usage:\n"
" %s -c host[:port]\tconnect to wifi source\n"
- " -u uri \tconnect to an rtsp uri\n"
- " -e ip[:port] \tenable remote display\n"
- " -d \tdisable remote display\n",
+ " -u uri \tconnect to an rtsp uri\n",
me);
}
@@ -65,7 +51,7 @@
AString uri;
int res;
- while ((res = getopt(argc, argv, "hc:l:u:e:d")) >= 0) {
+ while ((res = getopt(argc, argv, "hc:l:u:")) >= 0) {
switch (res) {
case 'c':
{
@@ -95,20 +81,6 @@
break;
}
- case 'e':
- {
- enableDisableRemoteDisplay(optarg);
- exit(0);
- break;
- }
-
- case 'd':
- {
- enableDisableRemoteDisplay(NULL);
- exit(0);
- break;
- }
-
case '?':
case 'h':
default:
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index 4fad83e..495feda 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -137,7 +137,6 @@
Camera2Client::~Camera2Client() {
ATRACE_CALL();
- ALOGV("Camera %d: Shutting down", mCameraId);
mDestructionStarted = true;
@@ -145,12 +144,6 @@
mClientPid = getCallingPid();
disconnect();
- mFrameProcessor->requestExit();
- mCaptureSequencer->requestExit();
- mJpegProcessor->requestExit();
- mZslProcessor->requestExit();
- mCallbackProcessor->requestExit();
-
ALOGI("Camera %d: Closed", mCameraId);
}
@@ -365,15 +358,21 @@
void Camera2Client::disconnect() {
ATRACE_CALL();
- ALOGV("%s: E", __FUNCTION__);
Mutex::Autolock icl(mICameraLock);
status_t res;
if ( (res = checkPid(__FUNCTION__) ) != OK) return;
if (mDevice == 0) return;
+ ALOGV("Camera %d: Shutting down", mCameraId);
+
stopPreviewL();
+ {
+ SharedParameters::Lock l(mParameters);
+ l.mParameters.state = Parameters::DISCONNECTED;
+ }
+
if (mPreviewStreamId != NO_STREAM) {
mDevice->deleteStream(mPreviewStreamId);
mPreviewStreamId = NO_STREAM;
@@ -390,9 +389,25 @@
mZslProcessor->deleteStream();
+ mFrameProcessor->requestExit();
+ mCaptureSequencer->requestExit();
+ mJpegProcessor->requestExit();
+ mZslProcessor->requestExit();
+ mCallbackProcessor->requestExit();
+
+ ALOGV("Camera %d: Waiting for threads", mCameraId);
+
+ mFrameProcessor->join();
+ mCaptureSequencer->join();
+ mJpegProcessor->join();
+ mZslProcessor->join();
+ mCallbackProcessor->join();
+
+ ALOGV("Camera %d: Disconnecting device", mCameraId);
+
+ mDevice->disconnect();
+
mDevice.clear();
- SharedParameters::Lock l(mParameters);
- l.mParameters.state = Parameters::DISCONNECTED;
CameraService::Client::disconnect();
}
diff --git a/services/camera/libcameraservice/Camera2Device.cpp b/services/camera/libcameraservice/Camera2Device.cpp
index a171c46..81c0496 100644
--- a/services/camera/libcameraservice/Camera2Device.cpp
+++ b/services/camera/libcameraservice/Camera2Device.cpp
@@ -38,30 +38,25 @@
Camera2Device::~Camera2Device()
{
- ALOGV("%s: Shutting down device for camera %d", __FUNCTION__, mId);
- if (mDevice) {
- status_t res;
- res = mDevice->common.close(&mDevice->common);
- if (res != OK) {
- ALOGE("%s: Could not close camera %d: %s (%d)",
- __FUNCTION__,
- mId, strerror(-res), res);
- }
- mDevice = NULL;
- }
- ALOGV("%s: Shutdown complete", __FUNCTION__);
+ disconnect();
}
status_t Camera2Device::initialize(camera_module_t *module)
{
ALOGV("%s: Initializing device for camera %d", __FUNCTION__, mId);
+ if (mDevice != NULL) {
+ ALOGE("%s: Already initialized!", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
status_t res;
char name[10];
snprintf(name, sizeof(name), "%d", mId);
+ camera2_device_t *device;
+
res = module->common.methods->open(&module->common, name,
- reinterpret_cast<hw_device_t**>(&mDevice));
+ reinterpret_cast<hw_device_t**>(&device));
if (res != OK) {
ALOGE("%s: Could not open camera %d: %s (%d)", __FUNCTION__,
@@ -69,11 +64,12 @@
return res;
}
- if (mDevice->common.version != CAMERA_DEVICE_API_VERSION_2_0) {
+ if (device->common.version != CAMERA_DEVICE_API_VERSION_2_0) {
ALOGE("%s: Could not open camera %d: "
"Camera device is not version %x, reports %x instead",
__FUNCTION__, mId, CAMERA_DEVICE_API_VERSION_2_0,
- mDevice->common.version);
+ device->common.version);
+ device->common.close(&device->common);
return BAD_VALUE;
}
@@ -81,45 +77,81 @@
res = module->get_camera_info(mId, &info);
if (res != OK ) return res;
- if (info.device_version != mDevice->common.version) {
+ if (info.device_version != device->common.version) {
ALOGE("%s: HAL reporting mismatched camera_info version (%x)"
" and device version (%x).", __FUNCTION__,
- mDevice->common.version, info.device_version);
+ device->common.version, info.device_version);
+ device->common.close(&device->common);
return BAD_VALUE;
}
- mDeviceInfo = info.static_camera_characteristics;
-
- res = mRequestQueue.setConsumerDevice(mDevice);
+ res = mRequestQueue.setConsumerDevice(device);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to connect request queue to device: %s (%d)",
__FUNCTION__, mId, strerror(-res), res);
+ device->common.close(&device->common);
return res;
}
- res = mFrameQueue.setProducerDevice(mDevice);
+ res = mFrameQueue.setProducerDevice(device);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to connect frame queue to device: %s (%d)",
__FUNCTION__, mId, strerror(-res), res);
+ device->common.close(&device->common);
return res;
}
- res = mDevice->ops->get_metadata_vendor_tag_ops(mDevice, &mVendorTagOps);
+ res = device->ops->get_metadata_vendor_tag_ops(device, &mVendorTagOps);
if (res != OK ) {
ALOGE("%s: Camera %d: Unable to retrieve tag ops from device: %s (%d)",
__FUNCTION__, mId, strerror(-res), res);
+ device->common.close(&device->common);
return res;
}
res = set_camera_metadata_vendor_tag_ops(mVendorTagOps);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to set tag ops: %s (%d)",
__FUNCTION__, mId, strerror(-res), res);
+ device->common.close(&device->common);
return res;
}
- setNotifyCallback(NULL);
+ res = device->ops->set_notify_callback(device, notificationCallback,
+ NULL);
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Unable to initialize notification callback!",
+ __FUNCTION__, mId);
+ device->common.close(&device->common);
+ return res;
+ }
+
+ mDeviceInfo = info.static_camera_characteristics;
+ mDevice = device;
return OK;
}
+status_t Camera2Device::disconnect() {
+ status_t res = OK;
+ if (mDevice) {
+ ALOGV("%s: Closing device for camera %d", __FUNCTION__, mId);
+
+ int inProgressCount = mDevice->ops->get_in_progress_count(mDevice);
+ if (inProgressCount > 0) {
+ ALOGW("%s: Closing camera device %d with %d requests in flight!",
+ __FUNCTION__, mId, inProgressCount);
+ }
+ mStreams.clear();
+ res = mDevice->common.close(&mDevice->common);
+ if (res != OK) {
+ ALOGE("%s: Could not close camera %d: %s (%d)",
+ __FUNCTION__,
+ mId, strerror(-res), res);
+ }
+ mDevice = NULL;
+ ALOGV("%s: Shutdown complete", __FUNCTION__);
+ }
+ return res;
+}
+
status_t Camera2Device::dump(int fd, const Vector<String16>& args) {
String8 result;
@@ -354,7 +386,7 @@
status_t Camera2Device::waitUntilDrained() {
static const uint32_t kSleepTime = 50000; // 50 ms
static const uint32_t kMaxSleepTime = 10000000; // 10 s
- ALOGV("%s: E", __FUNCTION__);
+ ALOGV("%s: Camera %d: Starting wait", __FUNCTION__, mId);
if (mRequestQueue.getBufferCount() ==
CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS) return INVALID_OPERATION;
@@ -364,11 +396,12 @@
usleep(kSleepTime);
totalTime += kSleepTime;
if (totalTime > kMaxSleepTime) {
- ALOGE("%s: Waited %d us, requests still in flight", __FUNCTION__,
- totalTime);
+ ALOGE("%s: Waited %d us, %d requests still in flight", __FUNCTION__,
+ mDevice->ops->get_in_progress_count(mDevice), totalTime);
return TIMED_OUT;
}
}
+ ALOGV("%s: Camera %d: HAL is idle", __FUNCTION__, mId);
return OK;
}
diff --git a/services/camera/libcameraservice/Camera2Device.h b/services/camera/libcameraservice/Camera2Device.h
index a327d8d..38662e3 100644
--- a/services/camera/libcameraservice/Camera2Device.h
+++ b/services/camera/libcameraservice/Camera2Device.h
@@ -40,6 +40,7 @@
~Camera2Device();
status_t initialize(camera_module_t *module);
+ status_t disconnect();
status_t dump(int fd, const Vector<String16>& args);
@@ -191,7 +192,6 @@
buffer_handle_t *buffer, wp<BufferReleasedListener> listener);
private:
-
const int mId;
camera2_device_t *mDevice;
diff --git a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
index 941ad15..a836321 100644
--- a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
+++ b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
@@ -223,6 +223,11 @@
res = INVALID_OPERATION;
}
}
+ sp<ZslProcessor> processor = mZslProcessor.promote();
+ if (processor != 0) {
+ processor->clearZslQueue();
+ }
+
if (mCaptureBuffer != 0 && res == OK) {
Camera2Client::SharedCameraClient::Lock l(client->mSharedCameraClient);
ALOGV("%s: Sending still image to client", __FUNCTION__);
diff --git a/services/camera/libcameraservice/camera2/ZslProcessor.cpp b/services/camera/libcameraservice/camera2/ZslProcessor.cpp
index 8906cd7..c7a679e 100644
--- a/services/camera/libcameraservice/camera2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/ZslProcessor.cpp
@@ -97,6 +97,10 @@
__FUNCTION__, handle);
}
+ // Erase entire ZSL queue since we've now completed the capture and preview
+ // is stopped.
+ clearZslQueueLocked();
+
mState = RUNNING;
}
@@ -240,7 +244,6 @@
dumpZslQueue(-1);
}
-
if (mZslQueueTail != mZslQueueHead) {
CameraMetadata request;
size_t index = mZslQueueTail;
@@ -312,6 +315,26 @@
return OK;
}
+status_t ZslProcessor::clearZslQueue() {
+ Mutex::Autolock l(mInputMutex);
+ // If in middle of capture, can't clear out queue
+ if (mState == LOCKED) return OK;
+
+ return clearZslQueueLocked();
+}
+
+status_t ZslProcessor::clearZslQueueLocked() {
+ for (size_t i = 0; i < mZslQueue.size(); i++) {
+ if (mZslQueue[i].buffer.mTimestamp != 0) {
+ mZslConsumer->releaseBuffer(mZslQueue[i].buffer);
+ }
+ mZslQueue.replaceAt(i);
+ }
+ mZslQueueHead = 0;
+ mZslQueueTail = 0;
+ return OK;
+}
+
void ZslProcessor::dump(int fd, const Vector<String16>& args) const {
Mutex::Autolock l(mInputMutex);
dumpZslQueue(fd);
diff --git a/services/camera/libcameraservice/camera2/ZslProcessor.h b/services/camera/libcameraservice/camera2/ZslProcessor.h
index 268f4f5..96ad5fb 100644
--- a/services/camera/libcameraservice/camera2/ZslProcessor.h
+++ b/services/camera/libcameraservice/camera2/ZslProcessor.h
@@ -62,6 +62,7 @@
int getReprocessStreamId() const;
status_t pushToReprocess(int32_t requestId);
+ status_t clearZslQueue();
void dump(int fd, const Vector<String16>& args) const;
private:
@@ -111,6 +112,8 @@
// Match up entries from frame list to buffers in ZSL queue
void findMatchesLocked();
+ status_t clearZslQueueLocked();
+
void dumpZslQueue(int id) const;
};