Merge "Camera2: Fix deadlock on shutdown due to client getting killed." into jb-mr2-dev
diff --git a/camera/Android.mk b/camera/Android.mk
index e33fb50..fa518ff 100644
--- a/camera/Android.mk
+++ b/camera/Android.mk
@@ -22,6 +22,7 @@
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
+ liblog \
libbinder \
libhardware \
libui \
diff --git a/camera/tests/Android.mk b/camera/tests/Android.mk
index e455943..ec13911 100644
--- a/camera/tests/Android.mk
+++ b/camera/tests/Android.mk
@@ -35,4 +35,4 @@
LOCAL_MODULE:= camera_client_test
LOCAL_MODULE_TAGS := tests
-include $(BUILD_EXECUTABLE)
+include $(BUILD_NATIVE_TEST)
diff --git a/camera/tests/ProCameraTests.cpp b/camera/tests/ProCameraTests.cpp
index 2b5f3ad..f203949 100644
--- a/camera/tests/ProCameraTests.cpp
+++ b/camera/tests/ProCameraTests.cpp
@@ -80,7 +80,7 @@
void onStatusChanged(Status status, int32_t cameraId) {
dout << "On status changed: 0x" << std::hex
- << status << " cameraId " << cameraId
+ << (unsigned int) status << " cameraId " << cameraId
<< std::endl;
Mutex::Autolock al(mMutex);
@@ -121,7 +121,7 @@
ACQUIRED,
RELEASED,
STOLEN,
- BUFFER_RECEIVED,
+ FRAME_RECEIVED,
RESULT_RECEIVED,
};
@@ -158,6 +158,7 @@
ProCameraTestListener() {
mEventMask = EVENT_MASK_ALL;
+ mDropFrames = false;
}
status_t WaitForEvent() {
@@ -208,12 +209,19 @@
mEventMask = eventMask;
}
+ // Automatically acquire/release frames as they are available
+ void SetDropFrames(bool dropFrames) {
+ Mutex::Autolock al(mListenerMutex);
+ mDropFrames = dropFrames;
+ }
+
private:
void QueueEvent(ProEvent ev) {
bool eventAdded = false;
{
Mutex::Autolock al(mListenerMutex);
+ // Drop events not part of mask
if (ProEvent_Mask(ev) & mEventMask) {
mProEventList.push(ev);
eventAdded = true;
@@ -253,16 +261,30 @@
<< " " << ext3 << std::endl;
}
- virtual void onBufferReceived(int streamId,
- const CpuConsumer::LockedBuffer& buf) {
+ virtual void onFrameAvailable(int streamId,
+ const sp<CpuConsumer>& consumer) {
- dout << "Buffer received on streamId = " << streamId <<
- ", dataPtr = " << (void*)buf.data <<
- ", timestamp = " << buf.timestamp << std::endl;
+ QueueEvent(FRAME_RECEIVED);
- QueueEvent(BUFFER_RECEIVED);
+ Mutex::Autolock al(mListenerMutex);
+ if (mDropFrames) {
+ CpuConsumer::LockedBuffer buf;
+ status_t ret;
+ EXPECT_OK(ret);
+ if (OK == (ret = consumer->lockNextBuffer(&buf))) {
+
+ dout << "Frame received on streamId = " << streamId <<
+ ", dataPtr = " << (void*)buf.data <<
+ ", timestamp = " << buf.timestamp << std::endl;
+
+ EXPECT_OK(consumer->unlockBuffer(buf));
+ }
+ } else {
+ dout << "Frame received on streamId = " << streamId << std::endl;
+ }
}
+
virtual void onResultReceived(int32_t frameId,
camera_metadata* request) {
dout << "Result received frameId = " << frameId
@@ -282,6 +304,7 @@
Mutex mConditionMutex;
Condition mListenerCondition;
int mEventMask;
+ bool mDropFrames;
};
class ProCameraTest : public ::testing::Test {
@@ -723,8 +746,11 @@
return;
}
- // FIXME: Note this test is broken because onBufferReceived was removed
- mListener->SetEventMask(ProEvent_Mask(BUFFER_RECEIVED));
+ mListener->SetEventMask(ProEvent_Mask(ACQUIRED) |
+ ProEvent_Mask(STOLEN) |
+ ProEvent_Mask(RELEASED) |
+ ProEvent_Mask(FRAME_RECEIVED));
+ mListener->SetDropFrames(true);
int streamId = -1;
sp<CpuConsumer> consumer;
@@ -776,7 +802,7 @@
// Consume a couple of frames
for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
EXPECT_EQ(OK, mListener->WaitForEvent());
- EXPECT_EQ(BUFFER_RECEIVED, mListener->ReadEvent());
+ EXPECT_EQ(FRAME_RECEIVED, mListener->ReadEvent());
}
// Done: clean up
@@ -790,8 +816,8 @@
return;
}
- // FIXME: Note this test is broken because onBufferReceived was removed
- mListener->SetEventMask(ProEvent_Mask(BUFFER_RECEIVED));
+ mListener->SetEventMask(ProEvent_Mask(FRAME_RECEIVED));
+ mListener->SetDropFrames(true);
int streamId = -1;
sp<CpuConsumer> consumer;
@@ -849,11 +875,11 @@
for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
// stream id 1
EXPECT_EQ(OK, mListener->WaitForEvent());
- EXPECT_EQ(BUFFER_RECEIVED, mListener->ReadEvent());
+ EXPECT_EQ(FRAME_RECEIVED, mListener->ReadEvent());
// stream id 2
EXPECT_EQ(OK, mListener->WaitForEvent());
- EXPECT_EQ(BUFFER_RECEIVED, mListener->ReadEvent());
+ EXPECT_EQ(FRAME_RECEIVED, mListener->ReadEvent());
//TODO: events should be a struct with some data like the stream id
}
@@ -870,7 +896,8 @@
}
mListener->SetEventMask(ProEvent_Mask(RESULT_RECEIVED));
- //FIXME: if this is run right after the previous test we get BUFFER_RECEIVED
+ mListener->SetDropFrames(true);
+ //FIXME: if this is run right after the previous test we get FRAME_RECEIVED
// need to filter out events at read time
int streamId = -1;
@@ -931,11 +958,14 @@
EXPECT_OK(mCamera->exclusiveUnlock());
}
-TEST_F(ProCameraTest, WaitForResult) {
+// FIXME: This is racy and sometimes fails on waitForFrameMetadata
+TEST_F(ProCameraTest, DISABLED_WaitForResult) {
if (HasFatalFailure()) {
return;
}
+ mListener->SetDropFrames(true);
+
int streamId = -1;
sp<CpuConsumer> consumer;
EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
@@ -955,7 +985,6 @@
}
// Done: clean up
- consumer->abandon(); // since we didn't consume any of the buffers
EXPECT_OK(mCamera->deleteStream(streamId));
EXPECT_OK(mCamera->exclusiveUnlock());
}
@@ -996,7 +1025,8 @@
EXPECT_OK(mCamera->exclusiveUnlock());
}
-TEST_F(ProCameraTest, WaitForDualStreamBuffer) {
+// FIXME: This is racy and sometimes fails on waitForFrameMetadata
+TEST_F(ProCameraTest, DISABLED_WaitForDualStreamBuffer) {
if (HasFatalFailure()) {
return;
}
@@ -1142,6 +1172,7 @@
}
const int NUM_REQUESTS = 20 * TEST_CPU_FRAME_COUNT;
+ const int CONSECUTIVE_FAILS_ASSUME_TIME_OUT = 5;
int streamId = -1;
sp<CpuConsumer> consumer;
@@ -1156,10 +1187,13 @@
ASSERT_NO_FATAL_FAILURE(createSubmitRequestForStreams(streams, /*count*/1,
/*requests*/NUM_REQUESTS));
+ uint64_t lastFrameNumber = 0;
+ int numFrames;
+
// Consume a couple of results
- for (int i = 0; i < NUM_REQUESTS; ++i) {
- int numFrames;
- EXPECT_TRUE((numFrames = mCamera->waitForFrameBuffer(streamId)) > 0);
+ int i;
+ for (i = 0; i < NUM_REQUESTS && lastFrameNumber < NUM_REQUESTS; ++i) {
+ EXPECT_LT(0, (numFrames = mCamera->waitForFrameBuffer(streamId)));
dout << "Dropped " << (numFrames - 1) << " frames" << std::endl;
@@ -1168,11 +1202,15 @@
// "Consume" the buffer
CpuConsumer::LockedBuffer buf;
- EXPECT_OK(consumer->lockNextBuffer(&buf));
+
+ EXPECT_EQ(OK, consumer->lockNextBuffer(&buf));
+
+ lastFrameNumber = buf.frameNumber;
dout << "Buffer asynchronously received on streamId = " << streamId <<
", dataPtr = " << (void*)buf.data <<
- ", timestamp = " << buf.timestamp << std::endl;
+ ", timestamp = " << buf.timestamp <<
+ ", framenumber = " << buf.frameNumber << std::endl;
// Process at 10fps, stream is at 15fps.
// This means we will definitely fill up the buffer queue with
@@ -1182,6 +1220,8 @@
EXPECT_OK(consumer->unlockBuffer(buf));
}
+ dout << "Done after " << i << " iterations " << std::endl;
+
// Done: clean up
EXPECT_OK(mCamera->deleteStream(streamId));
EXPECT_OK(mCamera->exclusiveUnlock());
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index d583e65..3844487 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -9,7 +9,7 @@
LOCAL_SHARED_LIBRARIES := \
libstagefright libmedia libutils libbinder libstagefright_foundation \
- libjpeg libgui libcutils
+ libjpeg libgui libcutils liblog
LOCAL_C_INCLUDES:= \
frameworks/av/media/libstagefright \
@@ -187,4 +187,3 @@
LOCAL_MODULE:= muxer
include $(BUILD_EXECUTABLE)
-
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 5bdbfbb..115b07c 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -523,7 +523,7 @@
}
sp<MetaData> params = new MetaData;
- params->setInt32(kKeyNotRealTime, true);
+ params->setInt32(kKeyRealTimeRecording, false);
CHECK_EQ(writer->start(params.get()), (status_t)OK);
while (!writer->reachedEOS()) {
diff --git a/drm/drmserver/Android.mk b/drm/drmserver/Android.mk
index 96205a1..dc973da 100644
--- a/drm/drmserver/Android.mk
+++ b/drm/drmserver/Android.mk
@@ -24,6 +24,7 @@
LOCAL_SHARED_LIBRARIES := \
libmedia \
libutils \
+ liblog \
libbinder \
libdl
diff --git a/drm/libdrmframework/Android.mk b/drm/libdrmframework/Android.mk
index 9e07fe3..49c4f9b 100644
--- a/drm/libdrmframework/Android.mk
+++ b/drm/libdrmframework/Android.mk
@@ -25,6 +25,7 @@
LOCAL_SHARED_LIBRARIES := \
libutils \
+ liblog \
libbinder \
libdl
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
index 205b9a5..e251f82 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
@@ -36,6 +36,7 @@
libicui18n \
libicuuc \
libutils \
+ liblog \
libdl \
libcrypto \
libssl \
diff --git a/drm/libdrmframework/plugins/passthru/Android.mk b/drm/libdrmframework/plugins/passthru/Android.mk
index d170d49..cb3a2e2 100644
--- a/drm/libdrmframework/plugins/passthru/Android.mk
+++ b/drm/libdrmframework/plugins/passthru/Android.mk
@@ -25,6 +25,7 @@
LOCAL_SHARED_LIBRARIES := \
libutils \
+ liblog \
libdl
diff --git a/drm/mediadrm/plugins/mock/Android.mk b/drm/mediadrm/plugins/mock/Android.mk
index a056cd8..ada23a2 100644
--- a/drm/mediadrm/plugins/mock/Android.mk
+++ b/drm/mediadrm/plugins/mock/Android.mk
@@ -24,7 +24,7 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_SHARED_LIBRARIES)/mediadrm
LOCAL_SHARED_LIBRARIES := \
- libutils
+ libutils liblog
LOCAL_C_INCLUDES += \
$(TOP)/frameworks/av/include \
diff --git a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp
index 00f6de3..06fc29d 100644
--- a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp
+++ b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp
@@ -291,16 +291,30 @@
{
Mutex::Autolock lock(mLock);
ALOGD("MockDrmPlugin::getSecureStops()");
- const uint8_t ss1[] = {0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89};
- const uint8_t ss2[] = {0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99};
- Vector<uint8_t> vec;
- vec.appendArray(ss1, sizeof(ss1));
- secureStops.push_back(vec);
+ // Properties used in mock test, set by cts test app returned from mock plugin
+ // byte[] mock-secure-stop1 -> first secure stop in list
+ // byte[] mock-secure-stop2 -> second secure stop in list
- vec.clear();
- vec.appendArray(ss2, sizeof(ss2));
- secureStops.push_back(vec);
+ Vector<uint8_t> ss1, ss2;
+ ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-secure-stop1"));
+ if (index < 0) {
+ ALOGD("Missing 'mock-secure-stop1' parameter for mock");
+ return BAD_VALUE;
+ } else {
+ ss1 = mByteArrayProperties.valueAt(index);
+ }
+
+ index = mByteArrayProperties.indexOfKey(String8("mock-secure-stop2"));
+ if (index < 0) {
+ ALOGD("Missing 'mock-secure-stop2' parameter for mock");
+ return BAD_VALUE;
+ } else {
+ ss2 = mByteArrayProperties.valueAt(index);
+ }
+
+ secureStops.push_back(ss1);
+ secureStops.push_back(ss2);
return OK;
}
@@ -309,6 +323,11 @@
Mutex::Autolock lock(mLock);
ALOGD("MockDrmPlugin::releaseSecureStops(%s)",
vectorToString(ssRelease).string());
+
+ // Properties used in mock test, set by mock plugin and verifed cts test app
+ // byte[] secure-stop-release -> mock-ssrelease
+ mByteArrayProperties.add(String8("mock-ssrelease"), ssRelease);
+
return OK;
}
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 96baf34..34bae29 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -46,6 +46,7 @@
kWhatInputSurfaceCreated = 'isfc',
kWhatSignaledInputEOS = 'seos',
kWhatBuffersAllocated = 'allc',
+ kWhatOMXDied = 'OMXd',
};
ACodec();
@@ -97,6 +98,7 @@
struct ExecutingToIdleState;
struct IdleToLoadedState;
struct FlushingState;
+ struct DeathNotifier;
enum {
kWhatSetup = 'setu',
@@ -262,12 +264,16 @@
status_t pushBlankBuffersToNativeWindow();
- // Returns true iff all buffers on the given port have status OWNED_BY_US.
+ // Returns true iff all buffers on the given port have status
+ // OWNED_BY_US or OWNED_BY_NATIVE_WINDOW.
bool allYourBuffersAreBelongToUs(OMX_U32 portIndex);
bool allYourBuffersAreBelongToUs();
+ void waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
+
size_t countBuffersOwnedByComponent(OMX_U32 portIndex) const;
+ size_t countBuffersOwnedByNativeWindow() const;
void deferMessage(const sp<AMessage> &msg);
void processDeferredMessages();
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index 88df6b0..3ef6b9a 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -74,6 +74,7 @@
int mFd;
status_t mInitCheck;
+ bool mIsRealTimeRecording;
bool mUse4ByteNalLength;
bool mUse32BitOffset;
bool mIsFileSizeLimitExplicitlyRequested;
@@ -168,6 +169,13 @@
// Only makes sense for H.264/AVC
bool useNalLengthFour();
+ // Return whether the writer is used for real time recording.
+ // In real time recording mode, new samples will be allowed to buffered into
+ // chunks in higher priority thread, even though the file writer has not
+ // drained the chunks yet.
+ // By default, real time recording is on.
+ bool isRealTimeRecording() const;
+
void lock();
void unlock();
diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h
index 35f46dc..a06a8e1 100644
--- a/include/media/stagefright/MediaCodec.h
+++ b/include/media/stagefright/MediaCodec.h
@@ -176,6 +176,7 @@
kFlagDequeueInputPending = 16,
kFlagDequeueOutputPending = 32,
kFlagIsSecure = 64,
+ kFlagSawMediaServerDie = 128,
};
struct BufferInfo {
diff --git a/include/media/stagefright/MediaErrors.h b/include/media/stagefright/MediaErrors.h
index bb01467..ee5e4e2 100644
--- a/include/media/stagefright/MediaErrors.h
+++ b/include/media/stagefright/MediaErrors.h
@@ -54,6 +54,8 @@
ERROR_DRM_DECRYPT = DRM_ERROR_BASE - 5,
ERROR_DRM_CANNOT_HANDLE = DRM_ERROR_BASE - 6,
ERROR_DRM_TAMPER_DETECTED = DRM_ERROR_BASE - 7,
+ ERROR_DRM_NOT_PROVISIONED = DRM_ERROR_BASE - 8,
+ ERROR_DRM_DEVICE_REVOKED = DRM_ERROR_BASE - 9,
ERROR_DRM_VENDOR_MAX = DRM_ERROR_BASE - 500,
ERROR_DRM_VENDOR_MIN = DRM_ERROR_BASE - 999,
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 9ab3edc..de3fc36 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -112,7 +112,7 @@
// kKeyTrackTimeStatus is used to track progress in elapsed time
kKeyTrackTimeStatus = 'tktm', // int64_t
- kKeyNotRealTime = 'ntrt', // bool (int32_t)
+ kKeyRealTimeRecording = 'rtrc', // bool (int32_t)
kKeyNumBuffers = 'nbbf', // int32_t
// Ogg files can be tagged to be automatically looping...
diff --git a/libvideoeditor/lvpp/Android.mk b/libvideoeditor/lvpp/Android.mk
index 778c5ac..2286827 100755
--- a/libvideoeditor/lvpp/Android.mk
+++ b/libvideoeditor/lvpp/Android.mk
@@ -50,6 +50,7 @@
libaudioutils \
libbinder \
libcutils \
+ liblog \
libEGL \
libGLESv2 \
libgui \
diff --git a/libvideoeditor/osal/src/Android.mk b/libvideoeditor/osal/src/Android.mk
index b73b9ae..4f38b0c 100755
--- a/libvideoeditor/osal/src/Android.mk
+++ b/libvideoeditor/osal/src/Android.mk
@@ -41,7 +41,7 @@
LOCAL_MODULE_TAGS := optional
-LOCAL_SHARED_LIBRARIES := libcutils libutils
+LOCAL_SHARED_LIBRARIES := libcutils libutils liblog
LOCAL_C_INCLUDES += \
$(TOP)/frameworks/av/libvideoeditor/osal/inc \
@@ -64,4 +64,3 @@
-DUSE_STAGEFRIGHT_3GPP_READER
include $(BUILD_SHARED_LIBRARY)
-
diff --git a/libvideoeditor/vss/src/Android.mk b/libvideoeditor/vss/src/Android.mk
index cda7a83..0caa15b 100755
--- a/libvideoeditor/vss/src/Android.mk
+++ b/libvideoeditor/vss/src/Android.mk
@@ -57,6 +57,7 @@
libaudioutils \
libbinder \
libcutils \
+ liblog \
libmedia \
libstagefright \
libstagefright_foundation \
@@ -96,4 +97,3 @@
-DDECODE_GIF_ON_SAVING
include $(BUILD_SHARED_LIBRARY)
-
diff --git a/libvideoeditor/vss/stagefrightshells/src/VideoEditorUtils.cpp b/libvideoeditor/vss/stagefrightshells/src/VideoEditorUtils.cpp
index 5309bd4..5a7237d 100755
--- a/libvideoeditor/vss/stagefrightshells/src/VideoEditorUtils.cpp
+++ b/libvideoeditor/vss/stagefrightshells/src/VideoEditorUtils.cpp
@@ -189,8 +189,8 @@
if (meta->findInt64(kKeyTrackTimeStatus, &int64Data)) {
LOG1("displayMetaData kKeyTrackTimeStatus %lld", int64Data);
}
- if (meta->findInt32(kKeyNotRealTime, &int32Data)) {
- LOG1("displayMetaData kKeyNotRealTime %d", int32Data);
+ if (meta->findInt32(kKeyRealTimeRecording, &int32Data)) {
+ LOG1("displayMetaData kKeyRealTimeRecording %d", int32Data);
}
}
diff --git a/media/common_time/Android.mk b/media/common_time/Android.mk
index 526f17b..632acbc 100644
--- a/media/common_time/Android.mk
+++ b/media/common_time/Android.mk
@@ -16,6 +16,7 @@
utils.cpp
LOCAL_SHARED_LIBRARIES := libbinder \
libhardware \
- libutils
+ libutils \
+ liblog
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libeffects/downmix/Android.mk b/media/libeffects/downmix/Android.mk
index 3052ad9..5d0a87c 100644
--- a/media/libeffects/downmix/Android.mk
+++ b/media/libeffects/downmix/Android.mk
@@ -7,7 +7,7 @@
EffectDownmix.c
LOCAL_SHARED_LIBRARIES := \
- libcutils
+ libcutils liblog
LOCAL_MODULE:= libdownmix
diff --git a/media/libeffects/factory/Android.mk b/media/libeffects/factory/Android.mk
index 6e69151..60a6ce5 100644
--- a/media/libeffects/factory/Android.mk
+++ b/media/libeffects/factory/Android.mk
@@ -7,7 +7,7 @@
EffectsFactory.c
LOCAL_SHARED_LIBRARIES := \
- libcutils
+ libcutils liblog
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
LOCAL_MODULE:= libeffects
diff --git a/media/libeffects/preprocessing/Android.mk b/media/libeffects/preprocessing/Android.mk
index dfa1711..c344352 100644
--- a/media/libeffects/preprocessing/Android.mk
+++ b/media/libeffects/preprocessing/Android.mk
@@ -21,7 +21,8 @@
LOCAL_SHARED_LIBRARIES := \
libwebrtc_audio_preprocessing \
libspeexresampler \
- libutils
+ libutils \
+ liblog
ifeq ($(TARGET_SIMULATOR),true)
LOCAL_LDLIBS += -ldl
diff --git a/media/libeffects/visualizer/Android.mk b/media/libeffects/visualizer/Android.mk
index 49cf4fa..e196eb2 100644
--- a/media/libeffects/visualizer/Android.mk
+++ b/media/libeffects/visualizer/Android.mk
@@ -10,6 +10,7 @@
LOCAL_SHARED_LIBRARIES := \
libcutils \
+ liblog \
libdl
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index fbe71ad..2c0c3a5 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -63,7 +63,7 @@
LOCAL_CFLAGS += -DSINGLE_STATE_QUEUE_INSTANTIATIONS='"SingleStateQueueInstantiations.cpp"'
LOCAL_SHARED_LIBRARIES := \
- libui libcutils libutils libbinder libsonivox libicuuc libexpat \
+ libui liblog libcutils libutils libbinder libsonivox libicuuc libexpat \
libcamera_client libstagefright_foundation \
libgui libdl libaudioutils
diff --git a/media/libmedia/IDrm.cpp b/media/libmedia/IDrm.cpp
index 1578846..902aeb2 100644
--- a/media/libmedia/IDrm.cpp
+++ b/media/libmedia/IDrm.cpp
@@ -590,6 +590,7 @@
size_t size = iter->size();
reply->writeInt32(size);
reply->write(iter->array(), iter->size());
+ iter++;
}
reply->writeInt32(result);
return OK;
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 3defec3..ecae3d3 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -398,6 +398,13 @@
if (mPlayer != 0 && isValidState) {
int durationMs;
status_t ret = mPlayer->getDuration(&durationMs);
+
+ if (ret != OK) {
+ // Do not enter error state just because no duration was available.
+ durationMs = -1;
+ ret = OK;
+ }
+
if (msec) {
*msec = durationMs;
}
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index 2a6f3c7..d87bc7f 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -27,6 +27,7 @@
libbinder \
libcamera_client \
libcutils \
+ liblog \
libdl \
libgui \
libmedia \
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 46d0a5a..b89b1c8 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -1158,7 +1158,7 @@
void NuPlayer::performDecoderFlush() {
ALOGV("performDecoderFlush");
- if (mAudioDecoder != NULL && mVideoDecoder == NULL) {
+ if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
return;
}
@@ -1176,7 +1176,7 @@
void NuPlayer::performDecoderShutdown() {
ALOGV("performDecoderShutdown");
- if (mAudioDecoder != NULL && mVideoDecoder == NULL) {
+ if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
return;
}
@@ -1257,6 +1257,13 @@
switch (what) {
case Source::kWhatPrepared:
{
+ if (mSource == NULL) {
+ // This is a stale notification from a source that was
+ // asynchronously preparing when the client called reset().
+ // We handled the reset, the source is gone.
+ break;
+ }
+
int32_t err;
CHECK(msg->findInt32("err", &err));
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 723af09..68b9623 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -314,11 +314,11 @@
Mutex::Autolock autoLock(mLock);
if (mDurationUs < 0) {
- *msec = 0;
- } else {
- *msec = (mDurationUs + 500ll) / 1000;
+ return UNKNOWN_ERROR;
}
+ *msec = (mDurationUs + 500ll) / 1000;
+
return OK;
}
@@ -333,6 +333,14 @@
case STATE_RESET_IN_PROGRESS:
return INVALID_OPERATION;
+ case STATE_PREPARING:
+ {
+ CHECK(mIsAsyncPrepare);
+
+ notifyListener(MEDIA_PREPARED);
+ break;
+ }
+
default:
break;
}
@@ -503,6 +511,14 @@
void NuPlayerDriver::notifyPrepareCompleted(status_t err) {
Mutex::Autolock autoLock(mLock);
+ if (mState != STATE_PREPARING) {
+ // We were preparing asynchronously when the client called
+ // reset(), we sent a premature "prepared" notification and
+ // then initiated the reset. This notification is stale.
+ CHECK(mState == STATE_RESET_IN_PROGRESS || mState == STATE_IDLE);
+ return;
+ }
+
CHECK_EQ(mState, STATE_PREPARING);
mAsyncResult = err;
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index a5ff0ca..50ebf9c 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -66,7 +66,9 @@
}
NuPlayer::RTSPSource::~RTSPSource() {
- mLooper->stop();
+ if (mLooper != NULL) {
+ mLooper->stop();
+ }
}
void NuPlayer::RTSPSource::prepareAsync() {
diff --git a/media/libnbaio/Android.mk b/media/libnbaio/Android.mk
index d372d20..5d00d15 100644
--- a/media/libnbaio/Android.mk
+++ b/media/libnbaio/Android.mk
@@ -30,6 +30,7 @@
libbinder \
libcommon_time_client \
libcutils \
- libutils
+ libutils \
+ liblog
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index ff72b71..6d952c3 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -166,6 +166,24 @@
////////////////////////////////////////////////////////////////////////////////
+struct ACodec::DeathNotifier : public IBinder::DeathRecipient {
+ DeathNotifier(const sp<AMessage> ¬ify)
+ : mNotify(notify) {
+ }
+
+ virtual void binderDied(const wp<IBinder> &) {
+ mNotify->post();
+ }
+
+protected:
+ virtual ~DeathNotifier() {}
+
+private:
+ sp<AMessage> mNotify;
+
+ DISALLOW_EVIL_CONSTRUCTORS(DeathNotifier);
+};
+
struct ACodec::UninitializedState : public ACodec::BaseState {
UninitializedState(ACodec *codec);
@@ -177,6 +195,8 @@
void onSetup(const sp<AMessage> &msg);
bool onAllocateComponent(const sp<AMessage> &msg);
+ sp<DeathNotifier> mDeathNotifier;
+
DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
};
@@ -940,6 +960,19 @@
err = setupVideoDecoder(mime, width, height);
}
}
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
+ int32_t numChannels, sampleRate;
+ if (!msg->findInt32("channel-count", &numChannels)
+ || !msg->findInt32("sample-rate", &sampleRate)) {
+ // Since we did not always check for these, leave them optional
+ // and have the decoder figure it all out.
+ err = OK;
+ } else {
+ err = setupRawAudioFormat(
+ encoder ? kPortIndexInput : kPortIndexOutput,
+ sampleRate,
+ numChannels);
+ }
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
int32_t numChannels, sampleRate;
if (!msg->findInt32("channel-count", &numChannels)
@@ -1432,14 +1465,6 @@
CHECK_EQ(err, (status_t)OK);
CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
- CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
- || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
- || format.eColorFormat == OMX_COLOR_FormatCbYCrY
- || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
- || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar
- || format.eColorFormat == OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka
- || format.eColorFormat == OMX_SEC_COLOR_FormatNV12Tiled);
-
return mOMX->setParameter(
mNode, OMX_IndexParamVideoPortFormat,
&format, sizeof(format));
@@ -2110,6 +2135,42 @@
return n;
}
+size_t ACodec::countBuffersOwnedByNativeWindow() const {
+ size_t n = 0;
+
+ for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
+ const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i);
+
+ if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
+ ++n;
+ }
+ }
+
+ return n;
+}
+
+void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() {
+ if (mNativeWindow == NULL) {
+ return;
+ }
+
+ int minUndequeuedBufs = 0;
+ status_t err = mNativeWindow->query(
+ mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
+ &minUndequeuedBufs);
+
+ if (err != OK) {
+ ALOGE("[%s] NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
+ mComponentName.c_str(), strerror(-err), -err);
+
+ minUndequeuedBufs = 0;
+ }
+
+ while (countBuffersOwnedByNativeWindow() > (size_t)minUndequeuedBufs
+ && dequeueBufferFromNativeWindow() != NULL) {
+ }
+}
+
bool ACodec::allYourBuffersAreBelongToUs(
OMX_U32 portIndex) {
for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
@@ -2487,6 +2548,13 @@
return true;
}
+ case ACodec::kWhatOMXDied:
+ {
+ ALOGE("OMX/mediaserver died, signalling error!");
+ mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);
+ break;
+ }
+
default:
return false;
}
@@ -3035,6 +3103,18 @@
void ACodec::UninitializedState::stateEntered() {
ALOGV("Now uninitialized");
+
+ if (mDeathNotifier != NULL) {
+ mCodec->mOMX->asBinder()->unlinkToDeath(mDeathNotifier);
+ mDeathNotifier.clear();
+ }
+
+ mCodec->mNativeWindow.clear();
+ mCodec->mNode = NULL;
+ mCodec->mOMX.clear();
+ mCodec->mQuirks = 0;
+ mCodec->mFlags = 0;
+ mCodec->mComponentName.clear();
}
bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
@@ -3106,6 +3186,15 @@
sp<IOMX> omx = client.interface();
+ sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec->id());
+
+ mDeathNotifier = new DeathNotifier(notify);
+ if (omx->asBinder()->linkToDeath(mDeathNotifier) != OK) {
+ // This was a local binder, if it dies so do we, we won't care
+ // about any notifications in the afterlife.
+ mDeathNotifier.clear();
+ }
+
Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs;
AString mime;
@@ -3170,7 +3259,7 @@
return false;
}
- sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
+ notify = new AMessage(kWhatOMXMessage, mCodec->id());
observer->setNotificationMessage(notify);
mCodec->mComponentName = componentName;
@@ -3224,13 +3313,6 @@
if (!keepComponentAllocated) {
CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
- mCodec->mNativeWindow.clear();
- mCodec->mNode = NULL;
- mCodec->mOMX.clear();
- mCodec->mQuirks = 0;
- mCodec->mFlags = 0;
- mCodec->mComponentName.clear();
-
mCodec->changeState(mCodec->mUninitializedState);
}
@@ -3626,7 +3708,6 @@
(status_t)OK);
mCodec->changeState(mCodec->mFlushingState);
-
handled = true;
break;
}
@@ -4132,6 +4213,10 @@
if (mFlushComplete[kPortIndexInput]
&& mFlushComplete[kPortIndexOutput]
&& mCodec->allYourBuffersAreBelongToUs()) {
+ // We now own all buffers except possibly those still queued with
+ // the native window for rendering. Let's get those back as well.
+ mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
+
sp<AMessage> notify = mCodec->mNotify->dup();
notify->setInt32("what", ACodec::kWhatFlushCompleted);
notify->post();
@@ -4141,6 +4226,10 @@
mCodec->mInputEOSResult = OK;
+ if (mCodec->mSkipCutBuffer != NULL) {
+ mCodec->mSkipCutBuffer->clear();
+ }
+
mCodec->changeState(mCodec->mExecutingState);
}
}
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 3503aaf..145869e 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -83,7 +83,7 @@
uint8_t mCryptoKey[16]; // passed in from extractor
uint32_t mCurrentAuxInfoType;
uint32_t mCurrentAuxInfoTypeParameter;
- uint32_t mCurrentDefaultSampleInfoSize;
+ int32_t mCurrentDefaultSampleInfoSize;
uint32_t mCurrentSampleInfoCount;
uint32_t mCurrentSampleInfoAllocSize;
uint8_t* mCurrentSampleInfoSizes;
@@ -320,6 +320,21 @@
}
}
+static bool AdjustChannelsAndRate(uint32_t fourcc, uint32_t *channels, uint32_t *rate) {
+ if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, FourCC2MIME(fourcc))) {
+ // AMR NB audio is always mono, 8kHz
+ *channels = 1;
+ *rate = 8000;
+ return true;
+ } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, FourCC2MIME(fourcc))) {
+ // AMR WB audio is always mono, 16kHz
+ *channels = 1;
+ *rate = 16000;
+ return true;
+ }
+ return false;
+}
+
MPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
: mSidxDuration(0),
mMoofOffset(0),
@@ -443,6 +458,14 @@
return track->meta;
}
+static void MakeFourCCString(uint32_t x, char *s) {
+ s[0] = x >> 24;
+ s[1] = (x >> 16) & 0xff;
+ s[2] = (x >> 8) & 0xff;
+ s[3] = x & 0xff;
+ s[4] = '\0';
+}
+
status_t MPEG4Extractor::readMetaData() {
if (mInitCheck != NO_INIT) {
return mInitCheck;
@@ -673,14 +696,6 @@
return UNKNOWN_ERROR; // Return a dummy error.
}
-static void MakeFourCCString(uint32_t x, char *s) {
- s[0] = x >> 24;
- s[1] = (x >> 16) & 0xff;
- s[2] = (x >> 8) & 0xff;
- s[3] = x & 0xff;
- s[4] = '\0';
-}
-
struct PathAdder {
PathAdder(Vector<uint32_t> *path, uint32_t chunkType)
: mPath(path) {
@@ -891,13 +906,19 @@
case FOURCC('f', 'r', 'm', 'a'):
{
- int32_t original_fourcc;
+ uint32_t original_fourcc;
if (mDataSource->readAt(data_offset, &original_fourcc, 4) < 4) {
return ERROR_IO;
}
original_fourcc = ntohl(original_fourcc);
ALOGV("read original format: %d", original_fourcc);
mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
+ uint32_t num_channels = 0;
+ uint32_t sample_rate = 0;
+ if (AdjustChannelsAndRate(original_fourcc, &num_channels, &sample_rate)) {
+ mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
+ mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
+ }
*offset += chunk_size;
break;
}
@@ -1134,6 +1155,7 @@
}
case FOURCC('m', 'p', '4', 'a'):
+ case FOURCC('e', 'n', 'c', 'a'):
case FOURCC('s', 'a', 'm', 'r'):
case FOURCC('s', 'a', 'w', 'b'):
{
@@ -1149,29 +1171,18 @@
}
uint16_t data_ref_index = U16_AT(&buffer[6]);
- uint16_t num_channels = U16_AT(&buffer[16]);
+ uint32_t num_channels = U16_AT(&buffer[16]);
uint16_t sample_size = U16_AT(&buffer[18]);
uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
- if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB,
- FourCC2MIME(chunk_type))) {
- // AMR NB audio is always mono, 8kHz
- num_channels = 1;
- sample_rate = 8000;
- } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB,
- FourCC2MIME(chunk_type))) {
- // AMR WB audio is always mono, 16kHz
- num_channels = 1;
- sample_rate = 16000;
+ if (chunk_type != FOURCC('e', 'n', 'c', 'a')) {
+ // if the chunk type is enca, we'll get the type from the sinf/frma box later
+ mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
+ AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate);
}
-
-#if 0
- printf("*** coding='%s' %d channels, size %d, rate %d\n",
+ ALOGV("*** coding='%s' %d channels, size %d, rate %d\n",
chunk, num_channels, sample_size, sample_rate);
-#endif
-
- mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
@@ -2297,6 +2308,7 @@
mSrcBuffer(NULL) {
mFormat->findInt32(kKeyCryptoMode, &mCryptoMode);
+ mDefaultIVSize = 0;
mFormat->findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize);
uint32_t keytype;
const void *key;
@@ -2544,13 +2556,17 @@
if (!mDataSource->getUInt32(offset, &smplcnt)) {
return ERROR_MALFORMED;
}
+ mCurrentSampleInfoCount = smplcnt;
offset += 4;
+ if (mCurrentDefaultSampleInfoSize != 0) {
+ ALOGV("@@@@ using default sample info size of %d", mCurrentDefaultSampleInfoSize);
+ return OK;
+ }
if (smplcnt > mCurrentSampleInfoAllocSize) {
mCurrentSampleInfoSizes = (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt);
mCurrentSampleInfoAllocSize = smplcnt;
}
- mCurrentSampleInfoCount = smplcnt;
mDataSource->readAt(offset, mCurrentSampleInfoSizes, smplcnt);
return OK;
@@ -2608,7 +2624,8 @@
drmoffset += mCurrentMoofOffset;
int ivlength;
CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength));
- int foo = 1;
+
+ // read CencSampleAuxiliaryDataFormats
for (size_t i = 0; i < mCurrentSampleInfoCount; i++) {
Sample *smpl = &mCurrentSamples.editItemAt(i);
@@ -2619,24 +2636,33 @@
drmoffset += ivlength;
- uint16_t numsubsamples;
- if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) {
- return ERROR_IO;
+ int32_t smplinfosize = mCurrentDefaultSampleInfoSize;
+ if (smplinfosize == 0) {
+ smplinfosize = mCurrentSampleInfoSizes[i];
}
- drmoffset += 2;
- for (size_t j = 0; j < numsubsamples; j++) {
- uint16_t numclear;
- uint32_t numencrypted;
- if (!mDataSource->getUInt16(drmoffset, &numclear)) {
+ if (smplinfosize > ivlength) {
+ uint16_t numsubsamples;
+ if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) {
return ERROR_IO;
}
drmoffset += 2;
- if (!mDataSource->getUInt32(drmoffset, &numencrypted)) {
- return ERROR_IO;
+ for (size_t j = 0; j < numsubsamples; j++) {
+ uint16_t numclear;
+ uint32_t numencrypted;
+ if (!mDataSource->getUInt16(drmoffset, &numclear)) {
+ return ERROR_IO;
+ }
+ drmoffset += 2;
+ if (!mDataSource->getUInt32(drmoffset, &numencrypted)) {
+ return ERROR_IO;
+ }
+ drmoffset += 4;
+ smpl->clearsizes.add(numclear);
+ smpl->encryptedsizes.add(numencrypted);
}
- drmoffset += 4;
- smpl->clearsizes.add(numclear);
- smpl->encryptedsizes.add(numencrypted);
+ } else {
+ smpl->clearsizes.add(0);
+ smpl->encryptedsizes.add(smpl->size);
}
}
@@ -3293,6 +3319,21 @@
}
}
+ const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
+ const sp<MetaData> bufmeta = mBuffer->meta_data();
+ bufmeta->clear();
+ if (smpl->encryptedsizes.size()) {
+ // store clear/encrypted lengths in metadata
+ bufmeta->setData(kKeyPlainSizes, 0,
+ smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
+ bufmeta->setData(kKeyEncryptedSizes, 0,
+ smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
+ bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
+ bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
+ bufmeta->setInt32(kKeyCryptoMode, mCryptoMode);
+ bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
+ }
+
if (!mIsAVC || mWantsNALFragments) {
if (newBuffer) {
ssize_t num_bytes_read =
@@ -3308,7 +3349,6 @@
CHECK(mBuffer != NULL);
mBuffer->set_range(0, size);
- mBuffer->meta_data()->clear();
mBuffer->meta_data()->setInt64(
kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
@@ -3432,7 +3472,6 @@
mBuffer->set_range(0, dstOffset);
}
- mBuffer->meta_data()->clear();
mBuffer->meta_data()->setInt64(
kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
@@ -3445,20 +3484,6 @@
mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
}
- const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
- if (smpl->encryptedsizes.size()) {
- // store clear/encrypted lengths in metadata
- sp<MetaData> bufmeta = mBuffer->meta_data();
- bufmeta->setData(kKeyPlainSizes, 0,
- smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
- bufmeta->setData(kKeyEncryptedSizes, 0,
- smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
- bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
- bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
- bufmeta->setInt32(kKeyCryptoMode, mCryptoMode);
- bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
- }
-
++mCurrentSampleIndex;
*out = mBuffer;
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 316f669..a0f17b5 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -212,7 +212,6 @@
int64_t mTrackDurationUs;
int64_t mMaxChunkDurationUs;
- bool mIsRealTimeRecording;
int64_t mEstimatedTrackSizeBytes;
int64_t mMdatSizeBytes;
int32_t mTimeScale;
@@ -335,6 +334,7 @@
MPEG4Writer::MPEG4Writer(const char *filename)
: mFd(-1),
mInitCheck(NO_INIT),
+ mIsRealTimeRecording(true),
mUse4ByteNalLength(true),
mUse32BitOffset(true),
mIsFileSizeLimitExplicitlyRequested(false),
@@ -359,6 +359,7 @@
MPEG4Writer::MPEG4Writer(int fd)
: mFd(dup(fd)),
mInitCheck(mFd < 0? NO_INIT: OK),
+ mIsRealTimeRecording(true),
mUse4ByteNalLength(true),
mUse32BitOffset(true),
mIsFileSizeLimitExplicitlyRequested(false),
@@ -596,6 +597,11 @@
mUse4ByteNalLength = false;
}
+ int32_t isRealTimeRecording;
+ if (param && param->findInt32(kKeyRealTimeRecording, &isRealTimeRecording)) {
+ mIsRealTimeRecording = isRealTimeRecording;
+ }
+
mStartTimestampUs = -1;
if (mStarted) {
@@ -1640,12 +1646,18 @@
mChunkReadyCondition.wait(mLock);
}
- // Actual write without holding the lock in order to
- // reduce the blocking time for media track threads.
+ // In real time recording mode, write without holding the lock in order
+ // to reduce the blocking time for media track threads.
+ // Otherwise, hold the lock until the existing chunks get written to the
+ // file.
if (chunkFound) {
- mLock.unlock();
+ if (mIsRealTimeRecording) {
+ mLock.unlock();
+ }
writeChunkToFile(&chunk);
- mLock.lock();
+ if (mIsRealTimeRecording) {
+ mLock.lock();
+ }
}
}
@@ -1695,18 +1707,10 @@
mRotation = rotationDegrees;
}
- mIsRealTimeRecording = true;
- {
- int32_t isNotRealTime;
- if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) {
- mIsRealTimeRecording = (isNotRealTime == 0);
- }
- }
-
initTrackingProgressStatus(params);
sp<MetaData> meta = new MetaData;
- if (mIsRealTimeRecording && mOwner->numTracks() > 1) {
+ if (mOwner->isRealTimeRecording() && mOwner->numTracks() > 1) {
/*
* This extra delay of accepting incoming audio/video signals
* helps to align a/v start time at the beginning of a recording
@@ -2084,7 +2088,10 @@
} else {
prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
}
- androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
+
+ if (mOwner->isRealTimeRecording()) {
+ androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
+ }
sp<MetaData> meta_data;
@@ -2245,7 +2252,7 @@
}
- if (mIsRealTimeRecording) {
+ if (mOwner->isRealTimeRecording()) {
if (mIsAudio) {
updateDriftTime(meta_data);
}
@@ -2531,6 +2538,10 @@
return mDriftTimeUs;
}
+bool MPEG4Writer::isRealTimeRecording() const {
+ return mIsRealTimeRecording;
+}
+
bool MPEG4Writer::useNalLengthFour() {
return mUse4ByteNalLength;
}
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 0d89c0f..ae7bb17 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -506,6 +506,11 @@
"(omx error 0x%08x, internalError %d)",
omxError, internalError);
+ if (omxError == OMX_ErrorResourcesLost
+ && internalError == DEAD_OBJECT) {
+ mFlags |= kFlagSawMediaServerDie;
+ }
+
bool sendErrorReponse = true;
switch (mState) {
@@ -534,6 +539,19 @@
// the shutdown complete notification.
sendErrorReponse = false;
+
+ if (mFlags & kFlagSawMediaServerDie) {
+ // MediaServer died, there definitely won't
+ // be a shutdown complete notification after
+ // all.
+
+ // note that we're directly going from
+ // STOPPING->UNINITIALIZED, instead of the
+ // usual STOPPING->INITIALIZED state.
+ setState(UNINITIALIZED);
+
+ (new AMessage)->postReply(mReplyID);
+ }
break;
}
@@ -985,45 +1003,46 @@
}
case kWhatStop:
- {
- uint32_t replyID;
- CHECK(msg->senderAwaitsResponse(&replyID));
-
- if (mState != INITIALIZED
- && mState != CONFIGURED && mState != STARTED) {
- sp<AMessage> response = new AMessage;
- response->setInt32("err", INVALID_OPERATION);
-
- response->postReply(replyID);
- break;
- }
-
- mReplyID = replyID;
- setState(STOPPING);
-
- mCodec->initiateShutdown(true /* keepComponentAllocated */);
- returnBuffersToCodec();
- break;
- }
-
case kWhatRelease:
{
+ State targetState =
+ (msg->what() == kWhatStop) ? INITIALIZED : UNINITIALIZED;
+
uint32_t replyID;
CHECK(msg->senderAwaitsResponse(&replyID));
if (mState != INITIALIZED
&& mState != CONFIGURED && mState != STARTED) {
+ // We may be in "UNINITIALIZED" state already without the
+ // client being aware of this if media server died while
+ // we were being stopped. The client would assume that
+ // after stop() returned, it would be safe to call release()
+ // and it should be in this case, no harm to allow a release()
+ // if we're already uninitialized.
+ // Similarly stopping a stopped MediaCodec should be benign.
sp<AMessage> response = new AMessage;
- response->setInt32("err", INVALID_OPERATION);
+ response->setInt32(
+ "err",
+ mState == targetState ? OK : INVALID_OPERATION);
response->postReply(replyID);
break;
}
- mReplyID = replyID;
- setState(RELEASING);
+ if (mFlags & kFlagSawMediaServerDie) {
+ // It's dead, Jim. Don't expect initiateShutdown to yield
+ // any useful results now...
+ setState(UNINITIALIZED);
+ (new AMessage)->postReply(replyID);
+ break;
+ }
- mCodec->initiateShutdown();
+ mReplyID = replyID;
+ setState(msg->what() == kWhatStop ? STOPPING : RELEASING);
+
+ mCodec->initiateShutdown(
+ msg->what() == kWhatStop /* keepComponentAllocated */);
+
returnBuffersToCodec();
break;
}
@@ -1400,6 +1419,11 @@
if (newState == UNINITIALIZED) {
mComponentName.clear();
+
+ // The component is gone, mediaserver's probably back up already
+ // but should definitely be back up should we try to instantiate
+ // another component.. and the cycle continues.
+ mFlags &= ~kFlagSawMediaServerDie;
}
mState = newState;
diff --git a/media/libstagefright/MediaMuxer.cpp b/media/libstagefright/MediaMuxer.cpp
index b948fe2..388c65b 100644
--- a/media/libstagefright/MediaMuxer.cpp
+++ b/media/libstagefright/MediaMuxer.cpp
@@ -107,6 +107,7 @@
Mutex::Autolock autoLock(mMuxerLock);
if (mState == INITIALIZED) {
mState = STARTED;
+ mFileMeta->setInt32(kKeyRealTimeRecording, false);
return mWriter->start(mFileMeta.get());
} else {
ALOGE("start() is called in invalid state %d", mState);
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index ff72e0e..1822f07 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -32,7 +32,7 @@
MuxOMX(const sp<IOMX> &remoteOMX);
virtual ~MuxOMX();
- virtual IBinder *onAsBinder() { return NULL; }
+ virtual IBinder *onAsBinder() { return mRemoteOMX->asBinder().get(); }
virtual bool livesLocally(node_id node, pid_t pid);
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 22aefcc..9d349a1 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -522,6 +522,17 @@
CODEC_LOGE("setAACFormat() failed (err = %d)", err);
return err;
}
+ } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_MPEG, mMIME)) {
+ int32_t numChannels, sampleRate;
+ if (meta->findInt32(kKeyChannelCount, &numChannels)
+ && meta->findInt32(kKeySampleRate, &sampleRate)) {
+ // Since we did not always check for these, leave them optional
+ // and have the decoder figure it all out.
+ setRawAudioFormat(
+ mIsEncoder ? kPortIndexInput : kPortIndexOutput,
+ sampleRate,
+ numChannels);
+ }
} else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_G711_ALAW, mMIME)
|| !strcasecmp(MEDIA_MIMETYPE_AUDIO_G711_MLAW, mMIME)) {
// These are PCM-like formats with a fixed sample rate but
@@ -1213,13 +1224,6 @@
CHECK_EQ(err, (status_t)OK);
CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
- CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
- || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
- || format.eColorFormat == OMX_COLOR_FormatCbYCrY
- || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
- || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar
- || format.eColorFormat == OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka);
-
int32_t colorFormat;
if (meta->findInt32(kKeyColorFormat, &colorFormat)
&& colorFormat != OMX_COLOR_FormatUnused
diff --git a/media/libstagefright/chromium_http/Android.mk b/media/libstagefright/chromium_http/Android.mk
index 2c6d84c..f26f386 100644
--- a/media/libstagefright/chromium_http/Android.mk
+++ b/media/libstagefright/chromium_http/Android.mk
@@ -22,6 +22,7 @@
libchromium_net \
libutils \
libcutils \
+ liblog \
libstagefright_foundation \
libstagefright \
libdrmframework
diff --git a/media/libstagefright/codecs/aacdec/Android.mk b/media/libstagefright/codecs/aacdec/Android.mk
index 4dc38a8..ffa64f9 100644
--- a/media/libstagefright/codecs/aacdec/Android.mk
+++ b/media/libstagefright/codecs/aacdec/Android.mk
@@ -20,7 +20,7 @@
LOCAL_STATIC_LIBRARIES := libFraunhoferAAC
LOCAL_SHARED_LIBRARIES := \
- libstagefright_omx libstagefright_foundation libutils libcutils
+ libstagefright_omx libstagefright_foundation libutils libcutils liblog
LOCAL_MODULE := libstagefright_soft_aacdec
LOCAL_MODULE_TAGS := optional
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index a8ab2ac..cf50dc9 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -29,6 +29,7 @@
#define DRC_DEFAULT_MOBILE_REF_LEVEL 64 /* 64*-0.25dB = -16 dB below full scale for mobile conf */
#define DRC_DEFAULT_MOBILE_DRC_CUT 127 /* maximum compression of dynamic range for mobile conf */
+#define DRC_DEFAULT_MOBILE_DRC_BOOST 127 /* maximum compression of dynamic range for mobile conf */
#define MAX_CHANNEL_COUNT 6 /* maximum number of audio channels that can be decoded */
// names of properties that can be used to override the default DRC settings
#define PROP_DRC_OVERRIDE_REF_LEVEL "aac_drc_reference_level"
@@ -118,7 +119,7 @@
status = OK;
}
}
- mIsFirst = true;
+ mDecoderHasData = false;
// for streams that contain metadata, use the mobile profile DRC settings unless overridden
// by platform properties:
@@ -146,6 +147,8 @@
unsigned boost = atoi(value);
ALOGV("AAC decoder using AAC_DRC_BOOST_FACTOR of %d", boost);
aacDecoder_SetParam(mAACDecoder, AAC_DRC_BOOST_FACTOR, boost);
+ } else {
+ aacDecoder_SetParam(mAACDecoder, AAC_DRC_BOOST_FACTOR, DRC_DEFAULT_MOBILE_DRC_BOOST);
}
return status;
@@ -327,6 +330,7 @@
notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
return;
}
+
inQueue.erase(inQueue.begin());
info->mOwnedByUs = false;
notifyEmptyBufferDone(header);
@@ -358,7 +362,7 @@
inInfo->mOwnedByUs = false;
notifyEmptyBufferDone(inHeader);
- if (!mIsFirst) {
+ if (mDecoderHasData) {
// flush out the decoder's delayed data by calling DecodeFrame
// one more time, with the AACDEC_FLUSH flag set
INT_PCM *outBuffer =
@@ -370,6 +374,7 @@
outBuffer,
outHeader->nAllocLen,
AACDEC_FLUSH);
+ mDecoderHasData = false;
if (decoderErr != AAC_DEC_OK) {
mSignalledError = true;
@@ -385,9 +390,7 @@
* sizeof(int16_t)
* mStreamInfo->numChannels;
} else {
- // Since we never discarded frames from the start, we won't have
- // to add any padding at the end either.
-
+ // we never submitted any data to the decoder, so there's nothing to flush out
outHeader->nFilledLen = 0;
}
@@ -473,6 +476,7 @@
inBuffer,
inBufferLength,
bytesValid);
+ mDecoderHasData = true;
decoderErr = aacDecoder_DecodeFrame(mAACDecoder,
outBuffer,
@@ -484,45 +488,6 @@
}
}
- /*
- * AAC+/eAAC+ streams can be signalled in two ways: either explicitly
- * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual
- * rate system and the sampling rate in the final output is actually
- * doubled compared with the core AAC decoder sampling rate.
- *
- * Explicit signalling is done by explicitly defining SBR audio object
- * type in the bitstream. Implicit signalling is done by embedding
- * SBR content in AAC extension payload specific to SBR, and hence
- * requires an AAC decoder to perform pre-checks on actual audio frames.
- *
- * Thus, we could not say for sure whether a stream is
- * AAC+/eAAC+ until the first data frame is decoded.
- */
- if (mInputBufferCount <= 2) {
- if (mStreamInfo->sampleRate != prevSampleRate ||
- mStreamInfo->numChannels != prevNumChannels) {
- maybeConfigureDownmix();
- ALOGI("Reconfiguring decoder: %d Hz, %d channels",
- mStreamInfo->sampleRate,
- mStreamInfo->numChannels);
-
- // We're going to want to revisit this input buffer, but
- // may have already advanced the offset. Undo that if
- // necessary.
- inHeader->nOffset -= adtsHeaderSize;
- inHeader->nFilledLen += adtsHeaderSize;
-
- notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
- mOutputPortSettingsChange = AWAITING_DISABLED;
- return;
- }
- } else if (!mStreamInfo->sampleRate || !mStreamInfo->numChannels) {
- ALOGW("Invalid AAC stream");
- mSignalledError = true;
- notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
- return;
- }
-
size_t numOutBytes =
mStreamInfo->frameSize * sizeof(int16_t) * mStreamInfo->numChannels;
@@ -544,17 +509,51 @@
// fall through
}
+ if (inHeader->nFilledLen == 0) {
+ inInfo->mOwnedByUs = false;
+ inQueue.erase(inQueue.begin());
+ inInfo = NULL;
+ notifyEmptyBufferDone(inHeader);
+ inHeader = NULL;
+ }
+
+ /*
+ * AAC+/eAAC+ streams can be signalled in two ways: either explicitly
+ * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual
+ * rate system and the sampling rate in the final output is actually
+ * doubled compared with the core AAC decoder sampling rate.
+ *
+ * Explicit signalling is done by explicitly defining SBR audio object
+ * type in the bitstream. Implicit signalling is done by embedding
+ * SBR content in AAC extension payload specific to SBR, and hence
+ * requires an AAC decoder to perform pre-checks on actual audio frames.
+ *
+ * Thus, we could not say for sure whether a stream is
+ * AAC+/eAAC+ until the first data frame is decoded.
+ */
+ if (mInputBufferCount <= 2) {
+ if (mStreamInfo->sampleRate != prevSampleRate ||
+ mStreamInfo->numChannels != prevNumChannels) {
+ maybeConfigureDownmix();
+ ALOGI("Reconfiguring decoder: %d->%d Hz, %d->%d channels",
+ prevSampleRate, mStreamInfo->sampleRate,
+ prevNumChannels, mStreamInfo->numChannels);
+
+ notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
+ mOutputPortSettingsChange = AWAITING_DISABLED;
+ return;
+ }
+ } else if (!mStreamInfo->sampleRate || !mStreamInfo->numChannels) {
+ ALOGW("Invalid AAC stream");
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
+ return;
+ }
+
if (decoderErr == AAC_DEC_OK || mNumSamplesOutput > 0) {
// We'll only output data if we successfully decoded it or
// we've previously decoded valid data, in the latter case
// (decode failed) we'll output a silent frame.
- if (mIsFirst) {
- mIsFirst = false;
- // the first decoded frame should be discarded to account
- // for decoder delay
- numOutBytes = 0;
- }
-
outHeader->nFilledLen = numOutBytes;
outHeader->nFlags = 0;
@@ -571,14 +570,6 @@
outHeader = NULL;
}
- if (inHeader->nFilledLen == 0) {
- inInfo->mOwnedByUs = false;
- inQueue.erase(inQueue.begin());
- inInfo = NULL;
- notifyEmptyBufferDone(inHeader);
- inHeader = NULL;
- }
-
if (decoderErr == AAC_DEC_OK) {
++mInputBufferCount;
}
@@ -589,14 +580,30 @@
if (portIndex == 0) {
// Make sure that the next buffer output does not still
// depend on fragments from the last one decoded.
- aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1);
- mIsFirst = true;
+ // drain all existing data
+ drainDecoder();
}
}
-void SoftAAC2::onReset() {
+void SoftAAC2::drainDecoder() {
+ // a buffer big enough for 6 channels of decoded HE-AAC
+ short buf [2048*6];
+ aacDecoder_DecodeFrame(mAACDecoder,
+ buf, sizeof(buf), AACDEC_FLUSH | AACDEC_CLRHIST | AACDEC_INTR);
+ aacDecoder_DecodeFrame(mAACDecoder,
+ buf, sizeof(buf), AACDEC_FLUSH | AACDEC_CLRHIST | AACDEC_INTR);
aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1);
- mIsFirst = true;
+ mDecoderHasData = false;
+}
+
+void SoftAAC2::onReset() {
+ drainDecoder();
+ // reset the "configured" state
+ mInputBufferCount = 0;
+ mNumSamplesOutput = 0;
+ // To make the codec behave the same before and after a reset, we need to invalidate the
+ // streaminfo struct. This does that:
+ mStreamInfo->sampleRate = 0;
}
void SoftAAC2::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.h b/media/libstagefright/codecs/aacdec/SoftAAC2.h
index 6957ade..2d960ab 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.h
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.h
@@ -52,7 +52,7 @@
HANDLE_AACDECODER mAACDecoder;
CStreamInfo *mStreamInfo;
bool mIsADTS;
- bool mIsFirst;
+ bool mDecoderHasData;
size_t mInputBufferCount;
bool mSignalledError;
int64_t mAnchorTimeUs;
@@ -68,6 +68,7 @@
status_t initDecoder();
bool isConfigured() const;
void maybeConfigureDownmix() const;
+ void drainDecoder();
DISALLOW_EVIL_CONSTRUCTORS(SoftAAC2);
};
diff --git a/media/libstagefright/codecs/aacenc/Android.mk b/media/libstagefright/codecs/aacenc/Android.mk
index 820734d..057c69b 100644
--- a/media/libstagefright/codecs/aacenc/Android.mk
+++ b/media/libstagefright/codecs/aacenc/Android.mk
@@ -109,7 +109,7 @@
LOCAL_STATIC_LIBRARIES := libFraunhoferAAC
LOCAL_SHARED_LIBRARIES := \
- libstagefright_omx libstagefright_foundation libutils
+ libstagefright_omx libstagefright_foundation libutils liblog
LOCAL_MODULE := libstagefright_soft_aacenc
LOCAL_MODULE_TAGS := optional
@@ -132,7 +132,7 @@
libstagefright_aacenc
LOCAL_SHARED_LIBRARIES := \
- libstagefright_omx libstagefright_foundation libutils \
+ libstagefright_omx libstagefright_foundation libutils liblog \
libstagefright_enc_common
LOCAL_MODULE := libstagefright_soft_aacenc
diff --git a/media/libstagefright/codecs/amrnb/dec/Android.mk b/media/libstagefright/codecs/amrnb/dec/Android.mk
index b48a459..8d6c6f8 100644
--- a/media/libstagefright/codecs/amrnb/dec/Android.mk
+++ b/media/libstagefright/codecs/amrnb/dec/Android.mk
@@ -72,7 +72,7 @@
libstagefright_amrnbdec libstagefright_amrwbdec
LOCAL_SHARED_LIBRARIES := \
- libstagefright_omx libstagefright_foundation libutils \
+ libstagefright_omx libstagefright_foundation libutils liblog \
libstagefright_amrnb_common
LOCAL_MODULE := libstagefright_soft_amrdec
diff --git a/media/libstagefright/codecs/amrnb/enc/Android.mk b/media/libstagefright/codecs/amrnb/enc/Android.mk
index 457656a..f4e467a 100644
--- a/media/libstagefright/codecs/amrnb/enc/Android.mk
+++ b/media/libstagefright/codecs/amrnb/enc/Android.mk
@@ -92,7 +92,7 @@
libstagefright_amrnbenc
LOCAL_SHARED_LIBRARIES := \
- libstagefright_omx libstagefright_foundation libutils \
+ libstagefright_omx libstagefright_foundation libutils liblog \
libstagefright_amrnb_common
LOCAL_MODULE := libstagefright_soft_amrnbenc
diff --git a/media/libstagefright/codecs/amrwbenc/Android.mk b/media/libstagefright/codecs/amrwbenc/Android.mk
index edfd7b7..c5b8e0c 100644
--- a/media/libstagefright/codecs/amrwbenc/Android.mk
+++ b/media/libstagefright/codecs/amrwbenc/Android.mk
@@ -130,7 +130,7 @@
libstagefright_amrwbenc
LOCAL_SHARED_LIBRARIES := \
- libstagefright_omx libstagefright_foundation libutils \
+ libstagefright_omx libstagefright_foundation libutils liblog \
libstagefright_enc_common
LOCAL_MODULE := libstagefright_soft_amrwbenc
diff --git a/media/libstagefright/codecs/avc/enc/Android.mk b/media/libstagefright/codecs/avc/enc/Android.mk
index cffe469..7d17c2a 100644
--- a/media/libstagefright/codecs/avc/enc/Android.mk
+++ b/media/libstagefright/codecs/avc/enc/Android.mk
@@ -62,6 +62,7 @@
libstagefright_foundation \
libstagefright_omx \
libutils \
+ liblog \
libui
diff --git a/media/libstagefright/codecs/flac/enc/Android.mk b/media/libstagefright/codecs/flac/enc/Android.mk
index 546a357..f01d605 100644
--- a/media/libstagefright/codecs/flac/enc/Android.mk
+++ b/media/libstagefright/codecs/flac/enc/Android.mk
@@ -10,7 +10,7 @@
external/flac/include
LOCAL_SHARED_LIBRARIES := \
- libstagefright libstagefright_omx libstagefright_foundation libutils
+ libstagefright libstagefright_omx libstagefright_foundation libutils liblog
LOCAL_STATIC_LIBRARIES := \
libFLAC \
diff --git a/media/libstagefright/codecs/g711/dec/Android.mk b/media/libstagefright/codecs/g711/dec/Android.mk
index 28be646..4c80da6 100644
--- a/media/libstagefright/codecs/g711/dec/Android.mk
+++ b/media/libstagefright/codecs/g711/dec/Android.mk
@@ -9,7 +9,7 @@
frameworks/native/include/media/openmax
LOCAL_SHARED_LIBRARIES := \
- libstagefright libstagefright_omx libstagefright_foundation libutils
+ libstagefright libstagefright_omx libstagefright_foundation libutils liblog
LOCAL_MODULE := libstagefright_soft_g711dec
LOCAL_MODULE_TAGS := optional
diff --git a/media/libstagefright/codecs/gsm/dec/Android.mk b/media/libstagefright/codecs/gsm/dec/Android.mk
index 9c0c6ae..71613d2 100644
--- a/media/libstagefright/codecs/gsm/dec/Android.mk
+++ b/media/libstagefright/codecs/gsm/dec/Android.mk
@@ -10,7 +10,7 @@
external/libgsm/inc
LOCAL_SHARED_LIBRARIES := \
- libstagefright libstagefright_omx libstagefright_foundation libutils
+ libstagefright libstagefright_omx libstagefright_foundation libutils liblog
LOCAL_STATIC_LIBRARIES := \
libgsm
diff --git a/media/libstagefright/codecs/m4v_h263/dec/Android.mk b/media/libstagefright/codecs/m4v_h263/dec/Android.mk
index a6b1edc..a3d5779 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/Android.mk
+++ b/media/libstagefright/codecs/m4v_h263/dec/Android.mk
@@ -67,7 +67,7 @@
libstagefright_m4vh263dec
LOCAL_SHARED_LIBRARIES := \
- libstagefright libstagefright_omx libstagefright_foundation libutils
+ libstagefright libstagefright_omx libstagefright_foundation libutils liblog
LOCAL_MODULE := libstagefright_soft_mpeg4dec
LOCAL_MODULE_TAGS := optional
diff --git a/media/libstagefright/codecs/m4v_h263/enc/Android.mk b/media/libstagefright/codecs/m4v_h263/enc/Android.mk
index 865cc9c..83a2dd2 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/Android.mk
+++ b/media/libstagefright/codecs/m4v_h263/enc/Android.mk
@@ -65,6 +65,7 @@
libstagefright_foundation \
libstagefright_omx \
libutils \
+ liblog \
libui
diff --git a/media/libstagefright/codecs/mp3dec/Android.mk b/media/libstagefright/codecs/mp3dec/Android.mk
index ec8d7ec..135c715 100644
--- a/media/libstagefright/codecs/mp3dec/Android.mk
+++ b/media/libstagefright/codecs/mp3dec/Android.mk
@@ -70,7 +70,7 @@
$(LOCAL_PATH)/include
LOCAL_SHARED_LIBRARIES := \
- libstagefright libstagefright_omx libstagefright_foundation libutils
+ libstagefright libstagefright_omx libstagefright_foundation libutils liblog
LOCAL_STATIC_LIBRARIES := \
libstagefright_mp3dec
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
index 849be87..9f25536 100644
--- a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
@@ -166,6 +166,21 @@
return OMX_ErrorNone;
}
+ case OMX_IndexParamAudioPcm:
+ {
+ const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
+ (const OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+
+ if (pcmParams->nPortIndex != 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ mNumChannels = pcmParams->nChannels;
+ mSamplingRate = pcmParams->nSamplingRate;
+
+ return OMX_ErrorNone;
+ }
+
default:
return SimpleSoftOMXComponent::internalSetParameter(index, params);
}
diff --git a/media/libstagefright/codecs/on2/dec/Android.mk b/media/libstagefright/codecs/on2/dec/Android.mk
index 0082d7c..7f2c46d 100644
--- a/media/libstagefright/codecs/on2/dec/Android.mk
+++ b/media/libstagefright/codecs/on2/dec/Android.mk
@@ -15,7 +15,7 @@
libvpx
LOCAL_SHARED_LIBRARIES := \
- libstagefright libstagefright_omx libstagefright_foundation libutils
+ libstagefright libstagefright_omx libstagefright_foundation libutils liblog
LOCAL_MODULE := libstagefright_soft_vpxdec
LOCAL_MODULE_TAGS := optional
diff --git a/media/libstagefright/codecs/on2/enc/Android.mk b/media/libstagefright/codecs/on2/enc/Android.mk
index 5d3317c..a92d376 100644
--- a/media/libstagefright/codecs/on2/enc/Android.mk
+++ b/media/libstagefright/codecs/on2/enc/Android.mk
@@ -16,7 +16,7 @@
libvpx
LOCAL_SHARED_LIBRARIES := \
- libstagefright libstagefright_omx libstagefright_foundation libutils \
+ libstagefright libstagefright_omx libstagefright_foundation libutils liblog \
LOCAL_MODULE := libstagefright_soft_vpxenc
LOCAL_MODULE_TAGS := optional
diff --git a/media/libstagefright/codecs/on2/h264dec/Android.mk b/media/libstagefright/codecs/on2/h264dec/Android.mk
index 772fd60..2539f98 100644
--- a/media/libstagefright/codecs/on2/h264dec/Android.mk
+++ b/media/libstagefright/codecs/on2/h264dec/Android.mk
@@ -97,7 +97,7 @@
endif
LOCAL_SHARED_LIBRARIES := \
- libstagefright libstagefright_omx libstagefright_foundation libutils \
+ libstagefright libstagefright_omx libstagefright_foundation libutils liblog \
LOCAL_MODULE := libstagefright_soft_h264dec
@@ -124,4 +124,3 @@
LOCAL_MODULE := decoder
include $(BUILD_EXECUTABLE)
-
diff --git a/media/libstagefright/codecs/raw/Android.mk b/media/libstagefright/codecs/raw/Android.mk
index 285c747..fe90a03 100644
--- a/media/libstagefright/codecs/raw/Android.mk
+++ b/media/libstagefright/codecs/raw/Android.mk
@@ -9,7 +9,7 @@
frameworks/native/include/media/openmax
LOCAL_SHARED_LIBRARIES := \
- libstagefright_omx libstagefright_foundation libutils
+ libstagefright_omx libstagefright_foundation libutils liblog
LOCAL_MODULE := libstagefright_soft_rawdec
LOCAL_MODULE_TAGS := optional
diff --git a/media/libstagefright/codecs/vorbis/dec/Android.mk b/media/libstagefright/codecs/vorbis/dec/Android.mk
index 395dd6b..2232353 100644
--- a/media/libstagefright/codecs/vorbis/dec/Android.mk
+++ b/media/libstagefright/codecs/vorbis/dec/Android.mk
@@ -11,10 +11,9 @@
LOCAL_SHARED_LIBRARIES := \
libvorbisidec libstagefright libstagefright_omx \
- libstagefright_foundation libutils
+ libstagefright_foundation libutils liblog
LOCAL_MODULE := libstagefright_soft_vorbisdec
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
-
diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
index 922ac61..4115324 100644
--- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
@@ -411,8 +411,19 @@
}
void SoftVorbis::onReset() {
+ mInputBufferCount = 0;
mNumFramesOutput = 0;
- vorbis_dsp_restart(mState);
+ if (mState != NULL) {
+ vorbis_dsp_clear(mState);
+ delete mState;
+ mState = NULL;
+ }
+
+ if (mVi != NULL) {
+ vorbis_info_clear(mVi);
+ delete mVi;
+ mVi = NULL;
+ }
}
void SoftVorbis::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
diff --git a/media/libstagefright/foundation/Android.mk b/media/libstagefright/foundation/Android.mk
index b7577d6..d65e213 100644
--- a/media/libstagefright/foundation/Android.mk
+++ b/media/libstagefright/foundation/Android.mk
@@ -20,6 +20,7 @@
LOCAL_SHARED_LIBRARIES := \
libbinder \
libutils \
+ liblog
LOCAL_CFLAGS += -Wno-multichar
diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp
index 44e03dc..68bbca2 100644
--- a/media/libstagefright/httplive/M3UParser.cpp
+++ b/media/libstagefright/httplive/M3UParser.cpp
@@ -163,9 +163,6 @@
while (offsetLF < size && data[offsetLF] != '\n') {
++offsetLF;
}
- if (offsetLF >= size) {
- break;
- }
AString line;
if (offsetLF > offset && data[offsetLF - 1] == '\r') {
diff --git a/media/libstagefright/id3/Android.mk b/media/libstagefright/id3/Android.mk
index ff35d4a..80a1a3a 100644
--- a/media/libstagefright/id3/Android.mk
+++ b/media/libstagefright/id3/Android.mk
@@ -16,7 +16,7 @@
testid3.cpp
LOCAL_SHARED_LIBRARIES := \
- libstagefright libutils libbinder libstagefright_foundation
+ libstagefright libutils liblog libbinder libstagefright_foundation
LOCAL_STATIC_LIBRARIES := \
libstagefright_id3
diff --git a/media/libstagefright/omx/Android.mk b/media/libstagefright/omx/Android.mk
index 9129f08..a8b4939 100644
--- a/media/libstagefright/omx/Android.mk
+++ b/media/libstagefright/omx/Android.mk
@@ -19,6 +19,7 @@
libbinder \
libmedia \
libutils \
+ liblog \
libui \
libgui \
libcutils \
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 46ff22f..e7d5e74 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -292,15 +292,16 @@
status_t OMXNodeInstance::enableGraphicBuffers(
OMX_U32 portIndex, OMX_BOOL enable) {
Mutex::Autolock autoLock(mLock);
+ OMX_STRING name = const_cast<OMX_STRING>(
+ "OMX.google.android.index.enableAndroidNativeBuffers");
OMX_INDEXTYPE index;
- OMX_ERRORTYPE err = OMX_GetExtensionIndex(
- mHandle,
- const_cast<OMX_STRING>("OMX.google.android.index.enableAndroidNativeBuffers"),
- &index);
+ OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
if (err != OMX_ErrorNone) {
- ALOGE("OMX_GetExtensionIndex failed");
+ if (enable) {
+ ALOGE("OMX_GetExtensionIndex %s failed", name);
+ }
return StatusFromOMXError(err);
}
@@ -331,14 +332,12 @@
Mutex::Autolock autoLock(mLock);
OMX_INDEXTYPE index;
- OMX_ERRORTYPE err = OMX_GetExtensionIndex(
- mHandle,
- const_cast<OMX_STRING>(
- "OMX.google.android.index.getAndroidNativeBufferUsage"),
- &index);
+ OMX_STRING name = const_cast<OMX_STRING>(
+ "OMX.google.android.index.getAndroidNativeBufferUsage");
+ OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
if (err != OMX_ErrorNone) {
- ALOGE("OMX_GetExtensionIndex failed");
+ ALOGE("OMX_GetExtensionIndex %s failed", name);
return StatusFromOMXError(err);
}
@@ -382,6 +381,7 @@
OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
if (err != OMX_ErrorNone) {
ALOGE("OMX_GetExtensionIndex %s failed", name);
+
return StatusFromOMXError(err);
}
@@ -507,13 +507,12 @@
return useGraphicBuffer2_l(portIndex, graphicBuffer, buffer);
}
- OMX_ERRORTYPE err = OMX_GetExtensionIndex(
- mHandle,
- const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer"),
- &index);
+ OMX_STRING name = const_cast<OMX_STRING>(
+ "OMX.google.android.index.useAndroidNativeBuffer");
+ OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
if (err != OMX_ErrorNone) {
- ALOGE("OMX_GetExtensionIndex failed");
+ ALOGE("OMX_GetExtensionIndex %s failed", name);
return StatusFromOMXError(err);
}
diff --git a/media/libstagefright/omx/tests/Android.mk b/media/libstagefright/omx/tests/Android.mk
index 04441ca..1061c39 100644
--- a/media/libstagefright/omx/tests/Android.mk
+++ b/media/libstagefright/omx/tests/Android.mk
@@ -5,7 +5,7 @@
OMXHarness.cpp \
LOCAL_SHARED_LIBRARIES := \
- libstagefright libbinder libmedia libutils libstagefright_foundation
+ libstagefright libbinder libmedia libutils liblog libstagefright_foundation
LOCAL_C_INCLUDES := \
$(TOP)/frameworks/av/media/libstagefright \
diff --git a/media/libstagefright/tests/Android.mk b/media/libstagefright/tests/Android.mk
index 57fff0b..06ce16b 100644
--- a/media/libstagefright/tests/Android.mk
+++ b/media/libstagefright/tests/Android.mk
@@ -26,6 +26,7 @@
libsync \
libui \
libutils \
+ liblog
LOCAL_STATIC_LIBRARIES := \
libgtest \
diff --git a/media/libstagefright/wifi-display/Android.mk b/media/libstagefright/wifi-display/Android.mk
index 1578c21..061ae89 100644
--- a/media/libstagefright/wifi-display/Android.mk
+++ b/media/libstagefright/wifi-display/Android.mk
@@ -4,17 +4,10 @@
LOCAL_SRC_FILES:= \
ANetworkSession.cpp \
- MediaReceiver.cpp \
MediaSender.cpp \
Parameters.cpp \
ParsedMessage.cpp \
- rtp/RTPAssembler.cpp \
- rtp/RTPReceiver.cpp \
rtp/RTPSender.cpp \
- sink/DirectRenderer.cpp \
- sink/WifiDisplaySink.cpp \
- SNTPClient.cpp \
- TimeSyncer.cpp \
source/Converter.cpp \
source/MediaPuller.cpp \
source/PlaybackSession.cpp \
@@ -31,6 +24,7 @@
LOCAL_SHARED_LIBRARIES:= \
libbinder \
libcutils \
+ liblog \
libgui \
libmedia \
libstagefright \
@@ -59,75 +53,10 @@
libstagefright_foundation \
libstagefright_wfd \
libutils \
+ liblog \
LOCAL_MODULE:= wfd
LOCAL_MODULE_TAGS := debug
include $(BUILD_EXECUTABLE)
-
-################################################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- udptest.cpp \
-
-LOCAL_SHARED_LIBRARIES:= \
- libbinder \
- libgui \
- libmedia \
- libstagefright \
- libstagefright_foundation \
- libstagefright_wfd \
- libutils \
-
-LOCAL_MODULE:= udptest
-
-LOCAL_MODULE_TAGS := debug
-
-include $(BUILD_EXECUTABLE)
-
-################################################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- rtptest.cpp \
-
-LOCAL_SHARED_LIBRARIES:= \
- libbinder \
- libgui \
- libmedia \
- libstagefright \
- libstagefright_foundation \
- libstagefright_wfd \
- libutils \
-
-LOCAL_MODULE:= rtptest
-
-LOCAL_MODULE_TAGS := debug
-
-include $(BUILD_EXECUTABLE)
-
-################################################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- nettest.cpp \
-
-LOCAL_SHARED_LIBRARIES:= \
- libbinder \
- libgui \
- libmedia \
- libstagefright \
- libstagefright_foundation \
- libstagefright_wfd \
- libutils \
-
-LOCAL_MODULE:= nettest
-
-LOCAL_MODULE_TAGS := debug
-
-include $(BUILD_EXECUTABLE)
diff --git a/media/libstagefright/wifi-display/MediaReceiver.cpp b/media/libstagefright/wifi-display/MediaReceiver.cpp
deleted file mode 100644
index 364acb9..0000000
--- a/media/libstagefright/wifi-display/MediaReceiver.cpp
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * Copyright 2013, 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 "MediaReceiver"
-#include <utils/Log.h>
-
-#include "MediaReceiver.h"
-
-#include "ANetworkSession.h"
-#include "AnotherPacketSource.h"
-#include "rtp/RTPReceiver.h"
-
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/Utils.h>
-
-namespace android {
-
-MediaReceiver::MediaReceiver(
- const sp<ANetworkSession> &netSession,
- const sp<AMessage> ¬ify)
- : mNetSession(netSession),
- mNotify(notify),
- mMode(MODE_UNDEFINED),
- mGeneration(0),
- mInitStatus(OK),
- mInitDoneCount(0) {
-}
-
-MediaReceiver::~MediaReceiver() {
-}
-
-ssize_t MediaReceiver::addTrack(
- RTPReceiver::TransportMode rtpMode,
- RTPReceiver::TransportMode rtcpMode,
- int32_t *localRTPPort) {
- if (mMode != MODE_UNDEFINED) {
- return INVALID_OPERATION;
- }
-
- size_t trackIndex = mTrackInfos.size();
-
- TrackInfo info;
-
- sp<AMessage> notify = new AMessage(kWhatReceiverNotify, id());
- notify->setInt32("generation", mGeneration);
- notify->setSize("trackIndex", trackIndex);
-
- info.mReceiver = new RTPReceiver(mNetSession, notify);
- looper()->registerHandler(info.mReceiver);
-
- info.mReceiver->registerPacketType(
- 33, RTPReceiver::PACKETIZATION_TRANSPORT_STREAM);
-
- info.mReceiver->registerPacketType(
- 96, RTPReceiver::PACKETIZATION_AAC);
-
- info.mReceiver->registerPacketType(
- 97, RTPReceiver::PACKETIZATION_H264);
-
- status_t err = info.mReceiver->initAsync(
- rtpMode,
- rtcpMode,
- localRTPPort);
-
- if (err != OK) {
- looper()->unregisterHandler(info.mReceiver->id());
- info.mReceiver.clear();
-
- return err;
- }
-
- mTrackInfos.push_back(info);
-
- return trackIndex;
-}
-
-status_t MediaReceiver::connectTrack(
- size_t trackIndex,
- const char *remoteHost,
- int32_t remoteRTPPort,
- int32_t remoteRTCPPort) {
- if (trackIndex >= mTrackInfos.size()) {
- return -ERANGE;
- }
-
- TrackInfo *info = &mTrackInfos.editItemAt(trackIndex);
- return info->mReceiver->connect(remoteHost, remoteRTPPort, remoteRTCPPort);
-}
-
-status_t MediaReceiver::initAsync(Mode mode) {
- if ((mode == MODE_TRANSPORT_STREAM || mode == MODE_TRANSPORT_STREAM_RAW)
- && mTrackInfos.size() > 1) {
- return INVALID_OPERATION;
- }
-
- sp<AMessage> msg = new AMessage(kWhatInit, id());
- msg->setInt32("mode", mode);
- msg->post();
-
- return OK;
-}
-
-void MediaReceiver::onMessageReceived(const sp<AMessage> &msg) {
- switch (msg->what()) {
- case kWhatInit:
- {
- int32_t mode;
- CHECK(msg->findInt32("mode", &mode));
-
- CHECK_EQ(mMode, MODE_UNDEFINED);
- mMode = (Mode)mode;
-
- if (mInitStatus != OK || mInitDoneCount == mTrackInfos.size()) {
- notifyInitDone(mInitStatus);
- }
-
- mTSParser = new ATSParser(
- ATSParser::ALIGNED_VIDEO_DATA
- | ATSParser::TS_TIMESTAMPS_ARE_ABSOLUTE);
-
- mFormatKnownMask = 0;
- break;
- }
-
- case kWhatReceiverNotify:
- {
- int32_t generation;
- CHECK(msg->findInt32("generation", &generation));
- if (generation != mGeneration) {
- break;
- }
-
- onReceiverNotify(msg);
- break;
- }
-
- default:
- TRESPASS();
- }
-}
-
-void MediaReceiver::onReceiverNotify(const sp<AMessage> &msg) {
- int32_t what;
- CHECK(msg->findInt32("what", &what));
-
- switch (what) {
- case RTPReceiver::kWhatInitDone:
- {
- ++mInitDoneCount;
-
- int32_t err;
- CHECK(msg->findInt32("err", &err));
-
- if (err != OK) {
- mInitStatus = err;
- ++mGeneration;
- }
-
- if (mMode != MODE_UNDEFINED) {
- if (mInitStatus != OK || mInitDoneCount == mTrackInfos.size()) {
- notifyInitDone(mInitStatus);
- }
- }
- break;
- }
-
- case RTPReceiver::kWhatError:
- {
- int32_t err;
- CHECK(msg->findInt32("err", &err));
-
- notifyError(err);
- break;
- }
-
- case RTPReceiver::kWhatAccessUnit:
- {
- size_t trackIndex;
- CHECK(msg->findSize("trackIndex", &trackIndex));
-
- sp<ABuffer> accessUnit;
- CHECK(msg->findBuffer("accessUnit", &accessUnit));
-
- int32_t followsDiscontinuity;
- if (!msg->findInt32(
- "followsDiscontinuity", &followsDiscontinuity)) {
- followsDiscontinuity = 0;
- }
-
- if (mMode == MODE_TRANSPORT_STREAM) {
- if (followsDiscontinuity) {
- mTSParser->signalDiscontinuity(
- ATSParser::DISCONTINUITY_TIME, NULL /* extra */);
- }
-
- for (size_t offset = 0;
- offset < accessUnit->size(); offset += 188) {
- status_t err = mTSParser->feedTSPacket(
- accessUnit->data() + offset, 188);
-
- if (err != OK) {
- notifyError(err);
- break;
- }
- }
-
- drainPackets(0 /* trackIndex */, ATSParser::VIDEO);
- drainPackets(1 /* trackIndex */, ATSParser::AUDIO);
- } else {
- postAccessUnit(trackIndex, accessUnit, NULL);
- }
- break;
- }
-
- case RTPReceiver::kWhatPacketLost:
- {
- notifyPacketLost();
- break;
- }
-
- default:
- TRESPASS();
- }
-}
-
-void MediaReceiver::drainPackets(
- size_t trackIndex, ATSParser::SourceType type) {
- sp<AnotherPacketSource> source =
- static_cast<AnotherPacketSource *>(
- mTSParser->getSource(type).get());
-
- if (source == NULL) {
- return;
- }
-
- sp<AMessage> format;
- if (!(mFormatKnownMask & (1ul << trackIndex))) {
- sp<MetaData> meta = source->getFormat();
- CHECK(meta != NULL);
-
- CHECK_EQ((status_t)OK, convertMetaDataToMessage(meta, &format));
-
- mFormatKnownMask |= 1ul << trackIndex;
- }
-
- status_t finalResult;
- while (source->hasBufferAvailable(&finalResult)) {
- sp<ABuffer> accessUnit;
- status_t err = source->dequeueAccessUnit(&accessUnit);
- if (err == OK) {
- postAccessUnit(trackIndex, accessUnit, format);
- format.clear();
- } else if (err != INFO_DISCONTINUITY) {
- notifyError(err);
- }
- }
-
- if (finalResult != OK) {
- notifyError(finalResult);
- }
-}
-
-void MediaReceiver::notifyInitDone(status_t err) {
- sp<AMessage> notify = mNotify->dup();
- notify->setInt32("what", kWhatInitDone);
- notify->setInt32("err", err);
- notify->post();
-}
-
-void MediaReceiver::notifyError(status_t err) {
- sp<AMessage> notify = mNotify->dup();
- notify->setInt32("what", kWhatError);
- notify->setInt32("err", err);
- notify->post();
-}
-
-void MediaReceiver::notifyPacketLost() {
- sp<AMessage> notify = mNotify->dup();
- notify->setInt32("what", kWhatPacketLost);
- notify->post();
-}
-
-void MediaReceiver::postAccessUnit(
- size_t trackIndex,
- const sp<ABuffer> &accessUnit,
- const sp<AMessage> &format) {
- sp<AMessage> notify = mNotify->dup();
- notify->setInt32("what", kWhatAccessUnit);
- notify->setSize("trackIndex", trackIndex);
- notify->setBuffer("accessUnit", accessUnit);
-
- if (format != NULL) {
- notify->setMessage("format", format);
- }
-
- notify->post();
-}
-
-status_t MediaReceiver::informSender(
- size_t trackIndex, const sp<AMessage> ¶ms) {
- if (trackIndex >= mTrackInfos.size()) {
- return -ERANGE;
- }
-
- TrackInfo *info = &mTrackInfos.editItemAt(trackIndex);
- return info->mReceiver->informSender(params);
-}
-
-} // namespace android
-
-
diff --git a/media/libstagefright/wifi-display/MediaReceiver.h b/media/libstagefright/wifi-display/MediaReceiver.h
deleted file mode 100644
index afbb407..0000000
--- a/media/libstagefright/wifi-display/MediaReceiver.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2013, 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.
- */
-
-#include <media/stagefright/foundation/AHandler.h>
-
-#include "ATSParser.h"
-#include "rtp/RTPReceiver.h"
-
-namespace android {
-
-struct ABuffer;
-struct ANetworkSession;
-struct AMessage;
-struct ATSParser;
-
-// This class facilitates receiving of media data for one or more tracks
-// over RTP. Either a 1:1 track to RTP channel mapping is used or a single
-// RTP channel provides the data for a transport stream that is consequently
-// demuxed and its track's data provided to the observer.
-struct MediaReceiver : public AHandler {
- enum {
- kWhatInitDone,
- kWhatError,
- kWhatAccessUnit,
- kWhatPacketLost,
- };
-
- MediaReceiver(
- const sp<ANetworkSession> &netSession,
- const sp<AMessage> ¬ify);
-
- ssize_t addTrack(
- RTPReceiver::TransportMode rtpMode,
- RTPReceiver::TransportMode rtcpMode,
- int32_t *localRTPPort);
-
- status_t connectTrack(
- size_t trackIndex,
- const char *remoteHost,
- int32_t remoteRTPPort,
- int32_t remoteRTCPPort);
-
- enum Mode {
- MODE_UNDEFINED,
- MODE_TRANSPORT_STREAM,
- MODE_TRANSPORT_STREAM_RAW,
- MODE_ELEMENTARY_STREAMS,
- };
- status_t initAsync(Mode mode);
-
- status_t informSender(size_t trackIndex, const sp<AMessage> ¶ms);
-
-protected:
- virtual void onMessageReceived(const sp<AMessage> &msg);
- virtual ~MediaReceiver();
-
-private:
- enum {
- kWhatInit,
- kWhatReceiverNotify,
- };
-
- struct TrackInfo {
- sp<RTPReceiver> mReceiver;
- };
-
- sp<ANetworkSession> mNetSession;
- sp<AMessage> mNotify;
-
- Mode mMode;
- int32_t mGeneration;
-
- Vector<TrackInfo> mTrackInfos;
-
- status_t mInitStatus;
- size_t mInitDoneCount;
-
- sp<ATSParser> mTSParser;
- uint32_t mFormatKnownMask;
-
- void onReceiverNotify(const sp<AMessage> &msg);
-
- void drainPackets(size_t trackIndex, ATSParser::SourceType type);
-
- void notifyInitDone(status_t err);
- void notifyError(status_t err);
- void notifyPacketLost();
-
- void postAccessUnit(
- size_t trackIndex,
- const sp<ABuffer> &accessUnit,
- const sp<AMessage> &format);
-
- DISALLOW_EVIL_CONSTRUCTORS(MediaReceiver);
-};
-
-} // namespace android
-
diff --git a/media/libstagefright/wifi-display/MediaSender.cpp b/media/libstagefright/wifi-display/MediaSender.cpp
index 33af66d..8a3566f 100644
--- a/media/libstagefright/wifi-display/MediaSender.cpp
+++ b/media/libstagefright/wifi-display/MediaSender.cpp
@@ -341,22 +341,6 @@
break;
}
- case kWhatInformSender:
- {
- int64_t avgLatencyUs;
- CHECK(msg->findInt64("avgLatencyUs", &avgLatencyUs));
-
- int64_t maxLatencyUs;
- CHECK(msg->findInt64("maxLatencyUs", &maxLatencyUs));
-
- sp<AMessage> notify = mNotify->dup();
- notify->setInt32("what", kWhatInformSender);
- notify->setInt64("avgLatencyUs", avgLatencyUs);
- notify->setInt64("maxLatencyUs", maxLatencyUs);
- notify->post();
- break;
- }
-
default:
TRESPASS();
}
diff --git a/media/libstagefright/wifi-display/MediaSender.h b/media/libstagefright/wifi-display/MediaSender.h
index 04538ea..64722c5 100644
--- a/media/libstagefright/wifi-display/MediaSender.h
+++ b/media/libstagefright/wifi-display/MediaSender.h
@@ -43,7 +43,6 @@
kWhatInitDone,
kWhatError,
kWhatNetworkStall,
- kWhatInformSender,
};
MediaSender(
diff --git a/media/libstagefright/wifi-display/SNTPClient.cpp b/media/libstagefright/wifi-display/SNTPClient.cpp
deleted file mode 100644
index 5c0af6a..0000000
--- a/media/libstagefright/wifi-display/SNTPClient.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright 2013, 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.
- */
-
-#include "SNTPClient.h"
-
-#include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/Utils.h>
-
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <unistd.h>
-
-namespace android {
-
-SNTPClient::SNTPClient() {
-}
-
-status_t SNTPClient::requestTime(const char *host) {
- struct hostent *ent;
- int64_t requestTimeNTP, requestTimeUs;
- ssize_t n;
- int64_t responseTimeUs, responseTimeNTP;
- int64_t originateTimeNTP, receiveTimeNTP, transmitTimeNTP;
- int64_t roundTripTimeNTP, clockOffsetNTP;
-
- status_t err = UNKNOWN_ERROR;
-
- int s = socket(AF_INET, SOCK_DGRAM, 0);
-
- if (s < 0) {
- err = -errno;
-
- goto bail;
- }
-
- ent = gethostbyname(host);
-
- if (ent == NULL) {
- err = -ENOENT;
- goto bail2;
- }
-
- struct sockaddr_in hostAddr;
- memset(hostAddr.sin_zero, 0, sizeof(hostAddr.sin_zero));
- hostAddr.sin_family = AF_INET;
- hostAddr.sin_port = htons(kNTPPort);
- hostAddr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
-
- uint8_t packet[kNTPPacketSize];
- memset(packet, 0, sizeof(packet));
-
- packet[0] = kNTPModeClient | (kNTPVersion << 3);
-
- requestTimeNTP = getNowNTP();
- requestTimeUs = ALooper::GetNowUs();
- writeTimeStamp(&packet[kNTPTransmitTimeOffset], requestTimeNTP);
-
- n = sendto(
- s, packet, sizeof(packet), 0,
- (const struct sockaddr *)&hostAddr, sizeof(hostAddr));
-
- if (n < 0) {
- err = -errno;
- goto bail2;
- }
-
- memset(packet, 0, sizeof(packet));
-
- do {
- n = recv(s, packet, sizeof(packet), 0);
- } while (n < 0 && errno == EINTR);
-
- if (n < 0) {
- err = -errno;
- goto bail2;
- }
-
- responseTimeUs = ALooper::GetNowUs();
-
- responseTimeNTP = requestTimeNTP + makeNTP(responseTimeUs - requestTimeUs);
-
- originateTimeNTP = readTimeStamp(&packet[kNTPOriginateTimeOffset]);
- receiveTimeNTP = readTimeStamp(&packet[kNTPReceiveTimeOffset]);
- transmitTimeNTP = readTimeStamp(&packet[kNTPTransmitTimeOffset]);
-
- roundTripTimeNTP =
- makeNTP(responseTimeUs - requestTimeUs)
- - (transmitTimeNTP - receiveTimeNTP);
-
- clockOffsetNTP =
- ((receiveTimeNTP - originateTimeNTP)
- + (transmitTimeNTP - responseTimeNTP)) / 2;
-
- mTimeReferenceNTP = responseTimeNTP + clockOffsetNTP;
- mTimeReferenceUs = responseTimeUs;
- mRoundTripTimeNTP = roundTripTimeNTP;
-
- err = OK;
-
-bail2:
- close(s);
- s = -1;
-
-bail:
- return err;
-}
-
-int64_t SNTPClient::adjustTimeUs(int64_t timeUs) const {
- uint64_t nowNTP =
- mTimeReferenceNTP + makeNTP(timeUs - mTimeReferenceUs);
-
- int64_t nowUs =
- (nowNTP >> 32) * 1000000ll
- + ((nowNTP & 0xffffffff) * 1000000ll) / (1ll << 32);
-
- nowUs -= ((70ll * 365 + 17) * 24) * 60 * 60 * 1000000ll;
-
- return nowUs;
-}
-
-// static
-void SNTPClient::writeTimeStamp(uint8_t *dst, uint64_t ntpTime) {
- *dst++ = (ntpTime >> 56) & 0xff;
- *dst++ = (ntpTime >> 48) & 0xff;
- *dst++ = (ntpTime >> 40) & 0xff;
- *dst++ = (ntpTime >> 32) & 0xff;
- *dst++ = (ntpTime >> 24) & 0xff;
- *dst++ = (ntpTime >> 16) & 0xff;
- *dst++ = (ntpTime >> 8) & 0xff;
- *dst++ = ntpTime & 0xff;
-}
-
-// static
-uint64_t SNTPClient::readTimeStamp(const uint8_t *dst) {
- return U64_AT(dst);
-}
-
-// static
-uint64_t SNTPClient::getNowNTP() {
- struct timeval tv;
- gettimeofday(&tv, NULL /* time zone */);
-
- uint64_t nowUs = tv.tv_sec * 1000000ll + tv.tv_usec;
-
- nowUs += ((70ll * 365 + 17) * 24) * 60 * 60 * 1000000ll;
-
- return makeNTP(nowUs);
-}
-
-// static
-uint64_t SNTPClient::makeNTP(uint64_t deltaUs) {
- uint64_t hi = deltaUs / 1000000ll;
- uint64_t lo = ((1ll << 32) * (deltaUs % 1000000ll)) / 1000000ll;
-
- return (hi << 32) | lo;
-}
-
-} // namespace android
-
diff --git a/media/libstagefright/wifi-display/SNTPClient.h b/media/libstagefright/wifi-display/SNTPClient.h
deleted file mode 100644
index 967d1fc..0000000
--- a/media/libstagefright/wifi-display/SNTPClient.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2013, 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 SNTP_CLIENT_H_
-
-#define SNTP_CLIENT_H_
-
-#include <media/stagefright/foundation/ABase.h>
-#include <utils/Errors.h>
-
-namespace android {
-
-// Implementation of the SNTP (Simple Network Time Protocol)
-struct SNTPClient {
- SNTPClient();
-
- status_t requestTime(const char *host);
-
- // given a time obtained from ALooper::GetNowUs()
- // return the number of us elapsed since Jan 1 1970 00:00:00 (UTC).
- int64_t adjustTimeUs(int64_t timeUs) const;
-
-private:
- enum {
- kNTPPort = 123,
- kNTPPacketSize = 48,
- kNTPModeClient = 3,
- kNTPVersion = 3,
- kNTPTransmitTimeOffset = 40,
- kNTPOriginateTimeOffset = 24,
- kNTPReceiveTimeOffset = 32,
- };
-
- uint64_t mTimeReferenceNTP;
- int64_t mTimeReferenceUs;
- int64_t mRoundTripTimeNTP;
-
- static void writeTimeStamp(uint8_t *dst, uint64_t ntpTime);
- static uint64_t readTimeStamp(const uint8_t *dst);
-
- static uint64_t getNowNTP();
- static uint64_t makeNTP(uint64_t deltaUs);
-
- DISALLOW_EVIL_CONSTRUCTORS(SNTPClient);
-};
-
-} // namespace android
-
-#endif // SNTP_CLIENT_H_
diff --git a/media/libstagefright/wifi-display/TimeSyncer.cpp b/media/libstagefright/wifi-display/TimeSyncer.cpp
deleted file mode 100644
index cb429bc..0000000
--- a/media/libstagefright/wifi-display/TimeSyncer.cpp
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * Copyright 2013, 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_NEBUG 0
-#define LOG_TAG "TimeSyncer"
-#include <utils/Log.h>
-
-#include "TimeSyncer.h"
-
-#include "ANetworkSession.h"
-
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AHandler.h>
-#include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/Utils.h>
-
-namespace android {
-
-TimeSyncer::TimeSyncer(
- const sp<ANetworkSession> &netSession, const sp<AMessage> ¬ify)
- : mNetSession(netSession),
- mNotify(notify),
- mIsServer(false),
- mConnected(false),
- mUDPSession(0),
- mSeqNo(0),
- mTotalTimeUs(0.0),
- mPendingT1(0ll),
- mTimeoutGeneration(0) {
-}
-
-TimeSyncer::~TimeSyncer() {
-}
-
-void TimeSyncer::startServer(unsigned localPort) {
- sp<AMessage> msg = new AMessage(kWhatStartServer, id());
- msg->setInt32("localPort", localPort);
- msg->post();
-}
-
-void TimeSyncer::startClient(const char *remoteHost, unsigned remotePort) {
- sp<AMessage> msg = new AMessage(kWhatStartClient, id());
- msg->setString("remoteHost", remoteHost);
- msg->setInt32("remotePort", remotePort);
- msg->post();
-}
-
-void TimeSyncer::onMessageReceived(const sp<AMessage> &msg) {
- switch (msg->what()) {
- case kWhatStartClient:
- {
- AString remoteHost;
- CHECK(msg->findString("remoteHost", &remoteHost));
-
- int32_t remotePort;
- CHECK(msg->findInt32("remotePort", &remotePort));
-
- sp<AMessage> notify = new AMessage(kWhatUDPNotify, id());
-
- CHECK_EQ((status_t)OK,
- mNetSession->createUDPSession(
- 0 /* localPort */,
- remoteHost.c_str(),
- remotePort,
- notify,
- &mUDPSession));
-
- postSendPacket();
- break;
- }
-
- case kWhatStartServer:
- {
- mIsServer = true;
-
- int32_t localPort;
- CHECK(msg->findInt32("localPort", &localPort));
-
- sp<AMessage> notify = new AMessage(kWhatUDPNotify, id());
-
- CHECK_EQ((status_t)OK,
- mNetSession->createUDPSession(
- localPort, notify, &mUDPSession));
-
- break;
- }
-
- case kWhatSendPacket:
- {
- if (mHistory.size() == 0) {
- ALOGI("starting batch");
- }
-
- TimeInfo ti;
- memset(&ti, 0, sizeof(ti));
-
- ti.mT1 = ALooper::GetNowUs();
-
- CHECK_EQ((status_t)OK,
- mNetSession->sendRequest(
- mUDPSession, &ti, sizeof(ti)));
-
- mPendingT1 = ti.mT1;
- postTimeout();
- break;
- }
-
- case kWhatTimedOut:
- {
- int32_t generation;
- CHECK(msg->findInt32("generation", &generation));
-
- if (generation != mTimeoutGeneration) {
- break;
- }
-
- ALOGI("timed out, sending another request");
- postSendPacket();
- break;
- }
-
- case kWhatUDPNotify:
- {
- int32_t reason;
- CHECK(msg->findInt32("reason", &reason));
-
- switch (reason) {
- case ANetworkSession::kWhatError:
- {
- int32_t sessionID;
- CHECK(msg->findInt32("sessionID", &sessionID));
-
- int32_t err;
- CHECK(msg->findInt32("err", &err));
-
- AString detail;
- CHECK(msg->findString("detail", &detail));
-
- ALOGE("An error occurred in session %d (%d, '%s/%s').",
- sessionID,
- err,
- detail.c_str(),
- strerror(-err));
-
- mNetSession->destroySession(sessionID);
-
- cancelTimeout();
-
- notifyError(err);
- break;
- }
-
- case ANetworkSession::kWhatDatagram:
- {
- int32_t sessionID;
- CHECK(msg->findInt32("sessionID", &sessionID));
-
- sp<ABuffer> packet;
- CHECK(msg->findBuffer("data", &packet));
-
- int64_t arrivalTimeUs;
- CHECK(packet->meta()->findInt64(
- "arrivalTimeUs", &arrivalTimeUs));
-
- CHECK_EQ(packet->size(), sizeof(TimeInfo));
-
- TimeInfo *ti = (TimeInfo *)packet->data();
-
- if (mIsServer) {
- if (!mConnected) {
- AString fromAddr;
- CHECK(msg->findString("fromAddr", &fromAddr));
-
- int32_t fromPort;
- CHECK(msg->findInt32("fromPort", &fromPort));
-
- CHECK_EQ((status_t)OK,
- mNetSession->connectUDPSession(
- mUDPSession, fromAddr.c_str(), fromPort));
-
- mConnected = true;
- }
-
- ti->mT2 = arrivalTimeUs;
- ti->mT3 = ALooper::GetNowUs();
-
- CHECK_EQ((status_t)OK,
- mNetSession->sendRequest(
- mUDPSession, ti, sizeof(*ti)));
- } else {
- if (ti->mT1 != mPendingT1) {
- break;
- }
-
- cancelTimeout();
- mPendingT1 = 0;
-
- ti->mT4 = arrivalTimeUs;
-
- // One way delay for a packet to travel from client
- // to server or back (assumed to be the same either way).
- int64_t delay =
- (ti->mT2 - ti->mT1 + ti->mT4 - ti->mT3) / 2;
-
- // Offset between the client clock (T1, T4) and the
- // server clock (T2, T3) timestamps.
- int64_t offset =
- (ti->mT2 - ti->mT1 - ti->mT4 + ti->mT3) / 2;
-
- mHistory.push_back(*ti);
-
- ALOGV("delay = %lld us,\toffset %lld us",
- delay,
- offset);
-
- if (mHistory.size() < kNumPacketsPerBatch) {
- postSendPacket(1000000ll / 30);
- } else {
- notifyOffset();
-
- ALOGI("batch done");
-
- mHistory.clear();
- postSendPacket(kBatchDelayUs);
- }
- }
- break;
- }
-
- default:
- TRESPASS();
- }
-
- break;
- }
-
- default:
- TRESPASS();
- }
-}
-
-void TimeSyncer::postSendPacket(int64_t delayUs) {
- (new AMessage(kWhatSendPacket, id()))->post(delayUs);
-}
-
-void TimeSyncer::postTimeout() {
- sp<AMessage> msg = new AMessage(kWhatTimedOut, id());
- msg->setInt32("generation", mTimeoutGeneration);
- msg->post(kTimeoutDelayUs);
-}
-
-void TimeSyncer::cancelTimeout() {
- ++mTimeoutGeneration;
-}
-
-void TimeSyncer::notifyError(status_t err) {
- if (mNotify == NULL) {
- looper()->stop();
- return;
- }
-
- sp<AMessage> notify = mNotify->dup();
- notify->setInt32("what", kWhatError);
- notify->setInt32("err", err);
- notify->post();
-}
-
-// static
-int TimeSyncer::CompareRountripTime(const TimeInfo *ti1, const TimeInfo *ti2) {
- int64_t rt1 = ti1->mT4 - ti1->mT1;
- int64_t rt2 = ti2->mT4 - ti2->mT1;
-
- if (rt1 < rt2) {
- return -1;
- } else if (rt1 > rt2) {
- return 1;
- }
-
- return 0;
-}
-
-void TimeSyncer::notifyOffset() {
- mHistory.sort(CompareRountripTime);
-
- int64_t sum = 0ll;
- size_t count = 0;
-
- // Only consider the third of the information associated with the best
- // (smallest) roundtrip times.
- for (size_t i = 0; i < mHistory.size() / 3; ++i) {
- const TimeInfo *ti = &mHistory[i];
-
-#if 0
- // One way delay for a packet to travel from client
- // to server or back (assumed to be the same either way).
- int64_t delay =
- (ti->mT2 - ti->mT1 + ti->mT4 - ti->mT3) / 2;
-#endif
-
- // Offset between the client clock (T1, T4) and the
- // server clock (T2, T3) timestamps.
- int64_t offset =
- (ti->mT2 - ti->mT1 - ti->mT4 + ti->mT3) / 2;
-
- ALOGV("(%d) RT: %lld us, offset: %lld us",
- i, ti->mT4 - ti->mT1, offset);
-
- sum += offset;
- ++count;
- }
-
- if (mNotify == NULL) {
- ALOGI("avg. offset is %lld", sum / count);
- return;
- }
-
- sp<AMessage> notify = mNotify->dup();
- notify->setInt32("what", kWhatTimeOffset);
- notify->setInt64("offset", sum / count);
- notify->post();
-}
-
-} // namespace android
diff --git a/media/libstagefright/wifi-display/TimeSyncer.h b/media/libstagefright/wifi-display/TimeSyncer.h
deleted file mode 100644
index 4e7571f..0000000
--- a/media/libstagefright/wifi-display/TimeSyncer.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright 2013, 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 TIME_SYNCER_H_
-
-#define TIME_SYNCER_H_
-
-#include <media/stagefright/foundation/AHandler.h>
-
-namespace android {
-
-struct ANetworkSession;
-
-/*
- TimeSyncer allows us to synchronize time between a client and a server.
- The client sends a UDP packet containing its send-time to the server,
- the server sends that packet back to the client amended with information
- about when it was received as well as the time the reply was sent back.
- Finally the client receives the reply and has now enough information to
- compute the clock offset between client and server assuming that packet
- exchange is symmetric, i.e. time for a packet client->server and
- server->client is roughly equal.
- This exchange is repeated a number of times and the average offset computed
- over the 30% of packets that had the lowest roundtrip times.
- The offset is determined every 10 secs to account for slight differences in
- clock frequency.
-*/
-struct TimeSyncer : public AHandler {
- enum {
- kWhatError,
- kWhatTimeOffset,
- };
- TimeSyncer(
- const sp<ANetworkSession> &netSession,
- const sp<AMessage> ¬ify);
-
- void startServer(unsigned localPort);
- void startClient(const char *remoteHost, unsigned remotePort);
-
-protected:
- virtual ~TimeSyncer();
-
- virtual void onMessageReceived(const sp<AMessage> &msg);
-
-private:
- enum {
- kWhatStartServer,
- kWhatStartClient,
- kWhatUDPNotify,
- kWhatSendPacket,
- kWhatTimedOut,
- };
-
- struct TimeInfo {
- int64_t mT1; // client timestamp at send
- int64_t mT2; // server timestamp at receive
- int64_t mT3; // server timestamp at send
- int64_t mT4; // client timestamp at receive
- };
-
- enum {
- kNumPacketsPerBatch = 30,
- };
- static const int64_t kTimeoutDelayUs = 500000ll;
- static const int64_t kBatchDelayUs = 60000000ll; // every minute
-
- sp<ANetworkSession> mNetSession;
- sp<AMessage> mNotify;
-
- bool mIsServer;
- bool mConnected;
- int32_t mUDPSession;
- uint32_t mSeqNo;
- double mTotalTimeUs;
-
- Vector<TimeInfo> mHistory;
-
- int64_t mPendingT1;
- int32_t mTimeoutGeneration;
-
- void postSendPacket(int64_t delayUs = 0ll);
-
- void postTimeout();
- void cancelTimeout();
-
- void notifyError(status_t err);
- void notifyOffset();
-
- static int CompareRountripTime(const TimeInfo *ti1, const TimeInfo *ti2);
-
- DISALLOW_EVIL_CONSTRUCTORS(TimeSyncer);
-};
-
-} // namespace android
-
-#endif // TIME_SYNCER_H_
diff --git a/media/libstagefright/wifi-display/nettest.cpp b/media/libstagefright/wifi-display/nettest.cpp
deleted file mode 100644
index 0779bf5..0000000
--- a/media/libstagefright/wifi-display/nettest.cpp
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * Copyright 2013, 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_NEBUG 0
-#define LOG_TAG "nettest"
-#include <utils/Log.h>
-
-#include "ANetworkSession.h"
-#include "TimeSyncer.h"
-
-#include <binder/ProcessState.h>
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AHandler.h>
-#include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/foundation/hexdump.h>
-#include <media/stagefright/DataSource.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/NuMediaExtractor.h>
-#include <media/stagefright/Utils.h>
-
-namespace android {
-
-struct TestHandler : public AHandler {
- TestHandler(const sp<ANetworkSession> &netSession);
-
- void listen(int32_t port);
- void connect(const char *host, int32_t port);
-
-protected:
- virtual ~TestHandler();
- virtual void onMessageReceived(const sp<AMessage> &msg);
-
-private:
- enum {
- kTimeSyncerPort = 8123,
- };
-
- enum {
- kWhatListen,
- kWhatConnect,
- kWhatTimeSyncerNotify,
- kWhatNetNotify,
- kWhatSendMore,
- kWhatStop,
- };
-
- sp<ANetworkSession> mNetSession;
- sp<TimeSyncer> mTimeSyncer;
-
- int32_t mServerSessionID;
- int32_t mSessionID;
-
- int64_t mTimeOffsetUs;
- bool mTimeOffsetValid;
-
- int32_t mCounter;
-
- int64_t mMaxDelayMs;
-
- void dumpDelay(int32_t counter, int64_t delayMs);
-
- DISALLOW_EVIL_CONSTRUCTORS(TestHandler);
-};
-
-TestHandler::TestHandler(const sp<ANetworkSession> &netSession)
- : mNetSession(netSession),
- mServerSessionID(0),
- mSessionID(0),
- mTimeOffsetUs(-1ll),
- mTimeOffsetValid(false),
- mCounter(0),
- mMaxDelayMs(-1ll) {
-}
-
-TestHandler::~TestHandler() {
-}
-
-void TestHandler::listen(int32_t port) {
- sp<AMessage> msg = new AMessage(kWhatListen, id());
- msg->setInt32("port", port);
- msg->post();
-}
-
-void TestHandler::connect(const char *host, int32_t port) {
- sp<AMessage> msg = new AMessage(kWhatConnect, id());
- msg->setString("host", host);
- msg->setInt32("port", port);
- msg->post();
-}
-
-void TestHandler::dumpDelay(int32_t counter, int64_t delayMs) {
- static const int64_t kMinDelayMs = 0;
- static const int64_t kMaxDelayMs = 300;
-
- const char *kPattern = "########################################";
- size_t kPatternSize = strlen(kPattern);
-
- int n = (kPatternSize * (delayMs - kMinDelayMs))
- / (kMaxDelayMs - kMinDelayMs);
-
- if (n < 0) {
- n = 0;
- } else if ((size_t)n > kPatternSize) {
- n = kPatternSize;
- }
-
- if (delayMs > mMaxDelayMs) {
- mMaxDelayMs = delayMs;
- }
-
- ALOGI("[%d] (%4lld ms / %4lld ms) %s",
- counter,
- delayMs,
- mMaxDelayMs,
- kPattern + kPatternSize - n);
-}
-
-void TestHandler::onMessageReceived(const sp<AMessage> &msg) {
- switch (msg->what()) {
- case kWhatListen:
- {
- sp<AMessage> notify = new AMessage(kWhatTimeSyncerNotify, id());
- mTimeSyncer = new TimeSyncer(mNetSession, notify);
- looper()->registerHandler(mTimeSyncer);
-
- notify = new AMessage(kWhatNetNotify, id());
-
- int32_t port;
- CHECK(msg->findInt32("port", &port));
-
- struct in_addr ifaceAddr;
- ifaceAddr.s_addr = INADDR_ANY;
-
- CHECK_EQ((status_t)OK,
- mNetSession->createTCPDatagramSession(
- ifaceAddr,
- port,
- notify,
- &mServerSessionID));
- break;
- }
-
- case kWhatConnect:
- {
- sp<AMessage> notify = new AMessage(kWhatTimeSyncerNotify, id());
- mTimeSyncer = new TimeSyncer(mNetSession, notify);
- looper()->registerHandler(mTimeSyncer);
- mTimeSyncer->startServer(kTimeSyncerPort);
-
- AString host;
- CHECK(msg->findString("host", &host));
-
- int32_t port;
- CHECK(msg->findInt32("port", &port));
-
- notify = new AMessage(kWhatNetNotify, id());
-
- CHECK_EQ((status_t)OK,
- mNetSession->createTCPDatagramSession(
- 0 /* localPort */,
- host.c_str(),
- port,
- notify,
- &mSessionID));
- break;
- }
-
- case kWhatNetNotify:
- {
- int32_t reason;
- CHECK(msg->findInt32("reason", &reason));
-
- switch (reason) {
- case ANetworkSession::kWhatConnected:
- {
- ALOGI("kWhatConnected");
-
- (new AMessage(kWhatSendMore, id()))->post();
- break;
- }
-
- case ANetworkSession::kWhatClientConnected:
- {
- ALOGI("kWhatClientConnected");
-
- CHECK_EQ(mSessionID, 0);
- CHECK(msg->findInt32("sessionID", &mSessionID));
-
- AString clientIP;
- CHECK(msg->findString("client-ip", &clientIP));
-
- mTimeSyncer->startClient(clientIP.c_str(), kTimeSyncerPort);
- break;
- }
-
- case ANetworkSession::kWhatDatagram:
- {
- sp<ABuffer> packet;
- CHECK(msg->findBuffer("data", &packet));
-
- CHECK_EQ(packet->size(), 12u);
-
- int32_t counter = U32_AT(packet->data());
- int64_t timeUs = U64_AT(packet->data() + 4);
-
- if (mTimeOffsetValid) {
- timeUs -= mTimeOffsetUs;
- int64_t nowUs = ALooper::GetNowUs();
- int64_t delayMs = (nowUs - timeUs) / 1000ll;
-
- dumpDelay(counter, delayMs);
- } else {
- ALOGI("received %d", counter);
- }
- break;
- }
-
- case ANetworkSession::kWhatError:
- {
- ALOGE("kWhatError");
- break;
- }
-
- default:
- TRESPASS();
- }
- break;
- }
-
- case kWhatTimeSyncerNotify:
- {
- CHECK(msg->findInt64("offset", &mTimeOffsetUs));
- mTimeOffsetValid = true;
- break;
- }
-
- case kWhatSendMore:
- {
- uint8_t buffer[4 + 8];
- buffer[0] = mCounter >> 24;
- buffer[1] = (mCounter >> 16) & 0xff;
- buffer[2] = (mCounter >> 8) & 0xff;
- buffer[3] = mCounter & 0xff;
-
- int64_t nowUs = ALooper::GetNowUs();
-
- buffer[4] = nowUs >> 56;
- buffer[5] = (nowUs >> 48) & 0xff;
- buffer[6] = (nowUs >> 40) & 0xff;
- buffer[7] = (nowUs >> 32) & 0xff;
- buffer[8] = (nowUs >> 24) & 0xff;
- buffer[9] = (nowUs >> 16) & 0xff;
- buffer[10] = (nowUs >> 8) & 0xff;
- buffer[11] = nowUs & 0xff;
-
- ++mCounter;
-
- CHECK_EQ((status_t)OK,
- mNetSession->sendRequest(
- mSessionID,
- buffer,
- sizeof(buffer),
- true /* timeValid */,
- nowUs));
-
- msg->post(100000ll);
- break;
- }
-
- case kWhatStop:
- {
- if (mSessionID != 0) {
- mNetSession->destroySession(mSessionID);
- mSessionID = 0;
- }
-
- if (mServerSessionID != 0) {
- mNetSession->destroySession(mServerSessionID);
- mServerSessionID = 0;
- }
-
- looper()->stop();
- break;
- }
-
- default:
- TRESPASS();
- }
-}
-
-} // namespace android
-
-static void usage(const char *me) {
- fprintf(stderr,
- "usage: %s -c host:port\tconnect to remote host\n"
- " -l port \tlisten\n",
- me);
-}
-
-int main(int argc, char **argv) {
- using namespace android;
-
- // srand(time(NULL));
-
- ProcessState::self()->startThreadPool();
-
- DataSource::RegisterDefaultSniffers();
-
- int32_t connectToPort = -1;
- AString connectToHost;
-
- int32_t listenOnPort = -1;
-
- int res;
- while ((res = getopt(argc, argv, "hc:l:")) >= 0) {
- switch (res) {
- case 'c':
- {
- const char *colonPos = strrchr(optarg, ':');
-
- if (colonPos == NULL) {
- usage(argv[0]);
- exit(1);
- }
-
- connectToHost.setTo(optarg, colonPos - optarg);
-
- char *end;
- connectToPort = strtol(colonPos + 1, &end, 10);
-
- if (*end != '\0' || end == colonPos + 1
- || connectToPort < 0 || connectToPort > 65535) {
- fprintf(stderr, "Illegal port specified.\n");
- exit(1);
- }
- break;
- }
-
- case 'l':
- {
- char *end;
- listenOnPort = strtol(optarg, &end, 10);
-
- if (*end != '\0' || end == optarg
- || listenOnPort < 0 || listenOnPort > 65535) {
- fprintf(stderr, "Illegal port specified.\n");
- exit(1);
- }
- break;
- }
-
- case '?':
- case 'h':
- usage(argv[0]);
- exit(1);
- }
- }
-
- if ((listenOnPort < 0 && connectToPort < 0)
- || (listenOnPort >= 0 && connectToPort >= 0)) {
- fprintf(stderr,
- "You need to select either client or server mode.\n");
- exit(1);
- }
-
- sp<ANetworkSession> netSession = new ANetworkSession;
- netSession->start();
-
- sp<ALooper> looper = new ALooper;
-
- sp<TestHandler> handler = new TestHandler(netSession);
- looper->registerHandler(handler);
-
- if (listenOnPort) {
- handler->listen(listenOnPort);
- }
-
- if (connectToPort >= 0) {
- handler->connect(connectToHost.c_str(), connectToPort);
- }
-
- looper->start(true /* runOnCallingThread */);
-
- return 0;
-}
diff --git a/media/libstagefright/wifi-display/rtp/RTPAssembler.cpp b/media/libstagefright/wifi-display/rtp/RTPAssembler.cpp
deleted file mode 100644
index 7a96081..0000000
--- a/media/libstagefright/wifi-display/rtp/RTPAssembler.cpp
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * Copyright 2013, 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 "RTPAssembler"
-#include <utils/Log.h>
-
-#include "RTPAssembler.h"
-
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/foundation/hexdump.h>
-#include <media/stagefright/MediaErrors.h>
-
-namespace android {
-
-RTPReceiver::Assembler::Assembler(const sp<AMessage> ¬ify)
- : mNotify(notify) {
-}
-
-void RTPReceiver::Assembler::postAccessUnit(
- const sp<ABuffer> &accessUnit, bool followsDiscontinuity) {
- sp<AMessage> notify = mNotify->dup();
- notify->setInt32("what", RTPReceiver::kWhatAccessUnit);
- notify->setBuffer("accessUnit", accessUnit);
- notify->setInt32("followsDiscontinuity", followsDiscontinuity);
- notify->post();
-}
-////////////////////////////////////////////////////////////////////////////////
-
-RTPReceiver::TSAssembler::TSAssembler(const sp<AMessage> ¬ify)
- : Assembler(notify),
- mSawDiscontinuity(false) {
-}
-
-void RTPReceiver::TSAssembler::signalDiscontinuity() {
- mSawDiscontinuity = true;
-}
-
-status_t RTPReceiver::TSAssembler::processPacket(const sp<ABuffer> &packet) {
- int32_t rtpTime;
- CHECK(packet->meta()->findInt32("rtp-time", &rtpTime));
-
- packet->meta()->setInt64("timeUs", (rtpTime * 100ll) / 9);
-
- postAccessUnit(packet, mSawDiscontinuity);
-
- if (mSawDiscontinuity) {
- mSawDiscontinuity = false;
- }
-
- return OK;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-RTPReceiver::H264Assembler::H264Assembler(const sp<AMessage> ¬ify)
- : Assembler(notify),
- mState(0),
- mIndicator(0),
- mNALType(0),
- mAccessUnitRTPTime(0) {
-}
-
-void RTPReceiver::H264Assembler::signalDiscontinuity() {
- reset();
-}
-
-status_t RTPReceiver::H264Assembler::processPacket(const sp<ABuffer> &packet) {
- status_t err = internalProcessPacket(packet);
-
- if (err != OK) {
- reset();
- }
-
- return err;
-}
-
-status_t RTPReceiver::H264Assembler::internalProcessPacket(
- const sp<ABuffer> &packet) {
- const uint8_t *data = packet->data();
- size_t size = packet->size();
-
- switch (mState) {
- case 0:
- {
- if (size < 1 || (data[0] & 0x80)) {
- ALOGV("Malformed H264 RTP packet (empty or F-bit set)");
- return ERROR_MALFORMED;
- }
-
- unsigned nalType = data[0] & 0x1f;
- if (nalType >= 1 && nalType <= 23) {
- addSingleNALUnit(packet);
- ALOGV("added single NAL packet");
- } else if (nalType == 28) {
- // FU-A
- unsigned indicator = data[0];
- CHECK((indicator & 0x1f) == 28);
-
- if (size < 2) {
- ALOGV("Malformed H264 FU-A packet (single byte)");
- return ERROR_MALFORMED;
- }
-
- if (!(data[1] & 0x80)) {
- ALOGV("Malformed H264 FU-A packet (no start bit)");
- return ERROR_MALFORMED;
- }
-
- mIndicator = data[0];
- mNALType = data[1] & 0x1f;
- uint32_t nri = (data[0] >> 5) & 3;
-
- clearAccumulator();
-
- uint8_t byte = mNALType | (nri << 5);
- appendToAccumulator(&byte, 1);
- appendToAccumulator(data + 2, size - 2);
-
- int32_t rtpTime;
- CHECK(packet->meta()->findInt32("rtp-time", &rtpTime));
- mAccumulator->meta()->setInt32("rtp-time", rtpTime);
-
- if (data[1] & 0x40) {
- // Huh? End bit also set on the first buffer.
- addSingleNALUnit(mAccumulator);
- clearAccumulator();
-
- ALOGV("added FU-A");
- break;
- }
-
- mState = 1;
- } else if (nalType == 24) {
- // STAP-A
-
- status_t err = addSingleTimeAggregationPacket(packet);
- if (err != OK) {
- return err;
- }
- } else {
- ALOGV("Malformed H264 packet (unknown type %d)", nalType);
- return ERROR_UNSUPPORTED;
- }
- break;
- }
-
- case 1:
- {
- if (size < 2
- || data[0] != mIndicator
- || (data[1] & 0x1f) != mNALType
- || (data[1] & 0x80)) {
- ALOGV("Malformed H264 FU-A packet (indicator, "
- "type or start bit mismatch)");
-
- return ERROR_MALFORMED;
- }
-
- appendToAccumulator(data + 2, size - 2);
-
- if (data[1] & 0x40) {
- addSingleNALUnit(mAccumulator);
-
- clearAccumulator();
- mState = 0;
-
- ALOGV("added FU-A");
- }
- break;
- }
-
- default:
- TRESPASS();
- }
-
- int32_t marker;
- CHECK(packet->meta()->findInt32("M", &marker));
-
- if (marker) {
- flushAccessUnit();
- }
-
- return OK;
-}
-
-void RTPReceiver::H264Assembler::reset() {
- mNALUnits.clear();
-
- clearAccumulator();
- mState = 0;
-}
-
-void RTPReceiver::H264Assembler::clearAccumulator() {
- if (mAccumulator != NULL) {
- // XXX Too expensive.
- mAccumulator.clear();
- }
-}
-
-void RTPReceiver::H264Assembler::appendToAccumulator(
- const void *data, size_t size) {
- if (mAccumulator == NULL) {
- mAccumulator = new ABuffer(size);
- memcpy(mAccumulator->data(), data, size);
- return;
- }
-
- if (mAccumulator->size() + size > mAccumulator->capacity()) {
- sp<ABuffer> buf = new ABuffer(mAccumulator->size() + size);
- memcpy(buf->data(), mAccumulator->data(), mAccumulator->size());
- buf->setRange(0, mAccumulator->size());
-
- int32_t rtpTime;
- if (mAccumulator->meta()->findInt32("rtp-time", &rtpTime)) {
- buf->meta()->setInt32("rtp-time", rtpTime);
- }
-
- mAccumulator = buf;
- }
-
- memcpy(mAccumulator->data() + mAccumulator->size(), data, size);
- mAccumulator->setRange(0, mAccumulator->size() + size);
-}
-
-void RTPReceiver::H264Assembler::addSingleNALUnit(const sp<ABuffer> &packet) {
- if (mNALUnits.empty()) {
- int32_t rtpTime;
- CHECK(packet->meta()->findInt32("rtp-time", &rtpTime));
-
- mAccessUnitRTPTime = rtpTime;
- }
-
- mNALUnits.push_back(packet);
-}
-
-void RTPReceiver::H264Assembler::flushAccessUnit() {
- if (mNALUnits.empty()) {
- return;
- }
-
- size_t totalSize = 0;
- for (List<sp<ABuffer> >::iterator it = mNALUnits.begin();
- it != mNALUnits.end(); ++it) {
- totalSize += 4 + (*it)->size();
- }
-
- sp<ABuffer> accessUnit = new ABuffer(totalSize);
- size_t offset = 0;
- for (List<sp<ABuffer> >::iterator it = mNALUnits.begin();
- it != mNALUnits.end(); ++it) {
- const sp<ABuffer> nalUnit = *it;
-
- memcpy(accessUnit->data() + offset, "\x00\x00\x00\x01", 4);
-
- memcpy(accessUnit->data() + offset + 4,
- nalUnit->data(),
- nalUnit->size());
-
- offset += 4 + nalUnit->size();
- }
-
- mNALUnits.clear();
-
- accessUnit->meta()->setInt64("timeUs", mAccessUnitRTPTime * 100ll / 9ll);
- postAccessUnit(accessUnit, false /* followsDiscontinuity */);
-}
-
-status_t RTPReceiver::H264Assembler::addSingleTimeAggregationPacket(
- const sp<ABuffer> &packet) {
- const uint8_t *data = packet->data();
- size_t size = packet->size();
-
- if (size < 3) {
- ALOGV("Malformed H264 STAP-A packet (too small)");
- return ERROR_MALFORMED;
- }
-
- int32_t rtpTime;
- CHECK(packet->meta()->findInt32("rtp-time", &rtpTime));
-
- ++data;
- --size;
- while (size >= 2) {
- size_t nalSize = (data[0] << 8) | data[1];
-
- if (size < nalSize + 2) {
- ALOGV("Malformed H264 STAP-A packet (incomplete NAL unit)");
- return ERROR_MALFORMED;
- }
-
- sp<ABuffer> unit = new ABuffer(nalSize);
- memcpy(unit->data(), &data[2], nalSize);
-
- unit->meta()->setInt32("rtp-time", rtpTime);
-
- addSingleNALUnit(unit);
-
- data += 2 + nalSize;
- size -= 2 + nalSize;
- }
-
- if (size != 0) {
- ALOGV("Unexpected padding at end of STAP-A packet.");
- }
-
- ALOGV("added STAP-A");
-
- return OK;
-}
-
-} // namespace android
-
diff --git a/media/libstagefright/wifi-display/rtp/RTPAssembler.h b/media/libstagefright/wifi-display/rtp/RTPAssembler.h
deleted file mode 100644
index e456d32..0000000
--- a/media/libstagefright/wifi-display/rtp/RTPAssembler.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2013, 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 RTP_ASSEMBLER_H_
-
-#define RTP_ASSEMBLER_H_
-
-#include "RTPReceiver.h"
-
-namespace android {
-
-// A helper class to reassemble the payload of RTP packets into access
-// units depending on the packetization scheme.
-struct RTPReceiver::Assembler : public RefBase {
- Assembler(const sp<AMessage> ¬ify);
-
- virtual void signalDiscontinuity() = 0;
- virtual status_t processPacket(const sp<ABuffer> &packet) = 0;
-
-protected:
- virtual ~Assembler() {}
-
- void postAccessUnit(
- const sp<ABuffer> &accessUnit, bool followsDiscontinuity);
-
-private:
- sp<AMessage> mNotify;
-
- DISALLOW_EVIL_CONSTRUCTORS(Assembler);
-};
-
-struct RTPReceiver::TSAssembler : public RTPReceiver::Assembler {
- TSAssembler(const sp<AMessage> ¬ify);
-
- virtual void signalDiscontinuity();
- virtual status_t processPacket(const sp<ABuffer> &packet);
-
-private:
- bool mSawDiscontinuity;
-
- DISALLOW_EVIL_CONSTRUCTORS(TSAssembler);
-};
-
-struct RTPReceiver::H264Assembler : public RTPReceiver::Assembler {
- H264Assembler(const sp<AMessage> ¬ify);
-
- virtual void signalDiscontinuity();
- virtual status_t processPacket(const sp<ABuffer> &packet);
-
-private:
- int32_t mState;
-
- uint8_t mIndicator;
- uint8_t mNALType;
-
- sp<ABuffer> mAccumulator;
-
- List<sp<ABuffer> > mNALUnits;
- int32_t mAccessUnitRTPTime;
-
- status_t internalProcessPacket(const sp<ABuffer> &packet);
-
- void addSingleNALUnit(const sp<ABuffer> &packet);
- status_t addSingleTimeAggregationPacket(const sp<ABuffer> &packet);
-
- void flushAccessUnit();
-
- void clearAccumulator();
- void appendToAccumulator(const void *data, size_t size);
-
- void reset();
-
- DISALLOW_EVIL_CONSTRUCTORS(H264Assembler);
-};
-
-} // namespace android
-
-#endif // RTP_ASSEMBLER_H_
-
diff --git a/media/libstagefright/wifi-display/rtp/RTPReceiver.cpp b/media/libstagefright/wifi-display/rtp/RTPReceiver.cpp
deleted file mode 100644
index 8fa1dae..0000000
--- a/media/libstagefright/wifi-display/rtp/RTPReceiver.cpp
+++ /dev/null
@@ -1,1153 +0,0 @@
-/*
- * Copyright 2013, 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 "RTPReceiver"
-#include <utils/Log.h>
-
-#include "RTPAssembler.h"
-#include "RTPReceiver.h"
-
-#include "ANetworkSession.h"
-
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/foundation/hexdump.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/Utils.h>
-
-#define TRACK_PACKET_LOSS 0
-
-namespace android {
-
-////////////////////////////////////////////////////////////////////////////////
-
-struct RTPReceiver::Source : public AHandler {
- Source(RTPReceiver *receiver, uint32_t ssrc);
-
- void onPacketReceived(uint16_t seq, const sp<ABuffer> &buffer);
-
- void addReportBlock(uint32_t ssrc, const sp<ABuffer> &buf);
-
-protected:
- virtual ~Source();
-
- virtual void onMessageReceived(const sp<AMessage> &msg);
-
-private:
- enum {
- kWhatRetransmit,
- kWhatDeclareLost,
- };
-
- static const uint32_t kMinSequential = 2;
- static const uint32_t kMaxDropout = 3000;
- static const uint32_t kMaxMisorder = 100;
- static const uint32_t kRTPSeqMod = 1u << 16;
- static const int64_t kReportIntervalUs = 10000000ll;
-
- RTPReceiver *mReceiver;
- uint32_t mSSRC;
- bool mFirst;
- uint16_t mMaxSeq;
- uint32_t mCycles;
- uint32_t mBaseSeq;
- uint32_t mReceived;
- uint32_t mExpectedPrior;
- uint32_t mReceivedPrior;
-
- int64_t mFirstArrivalTimeUs;
- int64_t mFirstRTPTimeUs;
-
- // Ordered by extended seq number.
- List<sp<ABuffer> > mPackets;
-
- enum StatusBits {
- STATUS_DECLARED_LOST = 1,
- STATUS_REQUESTED_RETRANSMISSION = 2,
- STATUS_ARRIVED_LATE = 4,
- };
-#if TRACK_PACKET_LOSS
- KeyedVector<int32_t, uint32_t> mLostPackets;
-#endif
-
- void modifyPacketStatus(int32_t extSeqNo, uint32_t mask);
-
- int32_t mAwaitingExtSeqNo;
- bool mRequestedRetransmission;
-
- int32_t mActivePacketType;
- sp<Assembler> mActiveAssembler;
-
- int64_t mNextReportTimeUs;
-
- int32_t mNumDeclaredLost;
- int32_t mNumDeclaredLostPrior;
-
- int32_t mRetransmitGeneration;
- int32_t mDeclareLostGeneration;
- bool mDeclareLostTimerPending;
-
- void queuePacket(const sp<ABuffer> &packet);
- void dequeueMore();
-
- sp<ABuffer> getNextPacket();
- void resync();
-
- void postRetransmitTimer(int64_t delayUs);
- void postDeclareLostTimer(int64_t delayUs);
- void cancelTimers();
-
- DISALLOW_EVIL_CONSTRUCTORS(Source);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-RTPReceiver::Source::Source(RTPReceiver *receiver, uint32_t ssrc)
- : mReceiver(receiver),
- mSSRC(ssrc),
- mFirst(true),
- mMaxSeq(0),
- mCycles(0),
- mBaseSeq(0),
- mReceived(0),
- mExpectedPrior(0),
- mReceivedPrior(0),
- mFirstArrivalTimeUs(-1ll),
- mFirstRTPTimeUs(-1ll),
- mAwaitingExtSeqNo(-1),
- mRequestedRetransmission(false),
- mActivePacketType(-1),
- mNextReportTimeUs(-1ll),
- mNumDeclaredLost(0),
- mNumDeclaredLostPrior(0),
- mRetransmitGeneration(0),
- mDeclareLostGeneration(0),
- mDeclareLostTimerPending(false) {
-}
-
-RTPReceiver::Source::~Source() {
-}
-
-void RTPReceiver::Source::onMessageReceived(const sp<AMessage> &msg) {
- switch (msg->what()) {
- case kWhatRetransmit:
- {
- int32_t generation;
- CHECK(msg->findInt32("generation", &generation));
-
- if (generation != mRetransmitGeneration) {
- break;
- }
-
- mRequestedRetransmission = true;
- mReceiver->requestRetransmission(mSSRC, mAwaitingExtSeqNo);
-
- modifyPacketStatus(
- mAwaitingExtSeqNo, STATUS_REQUESTED_RETRANSMISSION);
- break;
- }
-
- case kWhatDeclareLost:
- {
- int32_t generation;
- CHECK(msg->findInt32("generation", &generation));
-
- if (generation != mDeclareLostGeneration) {
- break;
- }
-
- cancelTimers();
-
- ALOGV("Lost packet extSeqNo %d %s",
- mAwaitingExtSeqNo,
- mRequestedRetransmission ? "*" : "");
-
- mRequestedRetransmission = false;
- if (mActiveAssembler != NULL) {
- mActiveAssembler->signalDiscontinuity();
- }
-
- modifyPacketStatus(mAwaitingExtSeqNo, STATUS_DECLARED_LOST);
-
- // resync();
- ++mAwaitingExtSeqNo;
- ++mNumDeclaredLost;
-
- mReceiver->notifyPacketLost();
-
- dequeueMore();
- break;
- }
-
- default:
- TRESPASS();
- }
-}
-
-void RTPReceiver::Source::onPacketReceived(
- uint16_t seq, const sp<ABuffer> &buffer) {
- if (mFirst) {
- buffer->setInt32Data(mCycles | seq);
- queuePacket(buffer);
-
- mFirst = false;
- mBaseSeq = seq;
- mMaxSeq = seq;
- ++mReceived;
- return;
- }
-
- uint16_t udelta = seq - mMaxSeq;
-
- if (udelta < kMaxDropout) {
- // In order, with permissible gap.
-
- if (seq < mMaxSeq) {
- // Sequence number wrapped - count another 64K cycle
- mCycles += kRTPSeqMod;
- }
-
- mMaxSeq = seq;
-
- ++mReceived;
- } else if (udelta <= kRTPSeqMod - kMaxMisorder) {
- // The sequence number made a very large jump
- return;
- } else {
- // Duplicate or reordered packet.
- }
-
- buffer->setInt32Data(mCycles | seq);
- queuePacket(buffer);
-}
-
-void RTPReceiver::Source::queuePacket(const sp<ABuffer> &packet) {
- int32_t newExtendedSeqNo = packet->int32Data();
-
- if (mFirstArrivalTimeUs < 0ll) {
- mFirstArrivalTimeUs = ALooper::GetNowUs();
-
- uint32_t rtpTime;
- CHECK(packet->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
-
- mFirstRTPTimeUs = (rtpTime * 100ll) / 9ll;
- }
-
- if (mAwaitingExtSeqNo >= 0 && newExtendedSeqNo < mAwaitingExtSeqNo) {
- // We're no longer interested in these. They're old.
- ALOGV("dropping stale extSeqNo %d", newExtendedSeqNo);
-
- modifyPacketStatus(newExtendedSeqNo, STATUS_ARRIVED_LATE);
- return;
- }
-
- if (mPackets.empty()) {
- mPackets.push_back(packet);
- dequeueMore();
- return;
- }
-
- List<sp<ABuffer> >::iterator firstIt = mPackets.begin();
- List<sp<ABuffer> >::iterator it = --mPackets.end();
- for (;;) {
- int32_t extendedSeqNo = (*it)->int32Data();
-
- if (extendedSeqNo == newExtendedSeqNo) {
- // Duplicate packet.
- return;
- }
-
- if (extendedSeqNo < newExtendedSeqNo) {
- // Insert new packet after the one at "it".
- mPackets.insert(++it, packet);
- break;
- }
-
- if (it == firstIt) {
- // Insert new packet before the first existing one.
- mPackets.insert(it, packet);
- break;
- }
-
- --it;
- }
-
- dequeueMore();
-}
-
-void RTPReceiver::Source::dequeueMore() {
- int64_t nowUs = ALooper::GetNowUs();
- if (mNextReportTimeUs < 0ll || nowUs >= mNextReportTimeUs) {
- if (mNextReportTimeUs >= 0ll) {
- uint32_t expected = (mMaxSeq | mCycles) - mBaseSeq + 1;
-
- uint32_t expectedInterval = expected - mExpectedPrior;
- mExpectedPrior = expected;
-
- uint32_t receivedInterval = mReceived - mReceivedPrior;
- mReceivedPrior = mReceived;
-
- int64_t lostInterval =
- (int64_t)expectedInterval - (int64_t)receivedInterval;
-
- int32_t declaredLostInterval =
- mNumDeclaredLost - mNumDeclaredLostPrior;
-
- mNumDeclaredLostPrior = mNumDeclaredLost;
-
- if (declaredLostInterval > 0) {
- ALOGI("lost %lld packets (%.2f %%), declared %d lost\n",
- lostInterval,
- 100.0f * lostInterval / expectedInterval,
- declaredLostInterval);
- }
- }
-
- mNextReportTimeUs = nowUs + kReportIntervalUs;
-
-#if TRACK_PACKET_LOSS
- for (size_t i = 0; i < mLostPackets.size(); ++i) {
- int32_t key = mLostPackets.keyAt(i);
- uint32_t value = mLostPackets.valueAt(i);
-
- AString status;
- if (value & STATUS_REQUESTED_RETRANSMISSION) {
- status.append("retrans ");
- }
- if (value & STATUS_ARRIVED_LATE) {
- status.append("arrived-late ");
- }
- ALOGI("Packet %d declared lost %s", key, status.c_str());
- }
-#endif
- }
-
- sp<ABuffer> packet;
- while ((packet = getNextPacket()) != NULL) {
- if (mDeclareLostTimerPending) {
- cancelTimers();
- }
-
- CHECK_GE(mAwaitingExtSeqNo, 0);
-#if TRACK_PACKET_LOSS
- mLostPackets.removeItem(mAwaitingExtSeqNo);
-#endif
-
- int32_t packetType;
- CHECK(packet->meta()->findInt32("PT", &packetType));
-
- if (packetType != mActivePacketType) {
- mActiveAssembler = mReceiver->makeAssembler(packetType);
- mActivePacketType = packetType;
- }
-
- if (mActiveAssembler != NULL) {
- status_t err = mActiveAssembler->processPacket(packet);
- if (err != OK) {
- ALOGV("assembler returned error %d", err);
- }
- }
-
- ++mAwaitingExtSeqNo;
- }
-
- if (mDeclareLostTimerPending) {
- return;
- }
-
- if (mPackets.empty()) {
- return;
- }
-
- CHECK_GE(mAwaitingExtSeqNo, 0);
-
- const sp<ABuffer> &firstPacket = *mPackets.begin();
-
- uint32_t rtpTime;
- CHECK(firstPacket->meta()->findInt32(
- "rtp-time", (int32_t *)&rtpTime));
-
-
- int64_t rtpUs = (rtpTime * 100ll) / 9ll;
-
- int64_t maxArrivalTimeUs =
- mFirstArrivalTimeUs + rtpUs - mFirstRTPTimeUs;
-
- nowUs = ALooper::GetNowUs();
-
- CHECK_LT(mAwaitingExtSeqNo, firstPacket->int32Data());
-
- ALOGV("waiting for %d, comparing against %d, %lld us left",
- mAwaitingExtSeqNo,
- firstPacket->int32Data(),
- maxArrivalTimeUs - nowUs);
-
- postDeclareLostTimer(maxArrivalTimeUs + kPacketLostAfterUs);
-
- if (kRequestRetransmissionAfterUs > 0ll) {
- postRetransmitTimer(
- maxArrivalTimeUs + kRequestRetransmissionAfterUs);
- }
-}
-
-sp<ABuffer> RTPReceiver::Source::getNextPacket() {
- if (mPackets.empty()) {
- return NULL;
- }
-
- int32_t extSeqNo = (*mPackets.begin())->int32Data();
-
- if (mAwaitingExtSeqNo < 0) {
- mAwaitingExtSeqNo = extSeqNo;
- } else if (extSeqNo != mAwaitingExtSeqNo) {
- return NULL;
- }
-
- sp<ABuffer> packet = *mPackets.begin();
- mPackets.erase(mPackets.begin());
-
- return packet;
-}
-
-void RTPReceiver::Source::resync() {
- mAwaitingExtSeqNo = -1;
-}
-
-void RTPReceiver::Source::addReportBlock(
- uint32_t ssrc, const sp<ABuffer> &buf) {
- uint32_t extMaxSeq = mMaxSeq | mCycles;
- uint32_t expected = extMaxSeq - mBaseSeq + 1;
-
- int64_t lost = (int64_t)expected - (int64_t)mReceived;
- if (lost > 0x7fffff) {
- lost = 0x7fffff;
- } else if (lost < -0x800000) {
- lost = -0x800000;
- }
-
- uint32_t expectedInterval = expected - mExpectedPrior;
- mExpectedPrior = expected;
-
- uint32_t receivedInterval = mReceived - mReceivedPrior;
- mReceivedPrior = mReceived;
-
- int64_t lostInterval = expectedInterval - receivedInterval;
-
- uint8_t fractionLost;
- if (expectedInterval == 0 || lostInterval <=0) {
- fractionLost = 0;
- } else {
- fractionLost = (lostInterval << 8) / expectedInterval;
- }
-
- uint8_t *ptr = buf->data() + buf->size();
-
- ptr[0] = ssrc >> 24;
- ptr[1] = (ssrc >> 16) & 0xff;
- ptr[2] = (ssrc >> 8) & 0xff;
- ptr[3] = ssrc & 0xff;
-
- ptr[4] = fractionLost;
-
- ptr[5] = (lost >> 16) & 0xff;
- ptr[6] = (lost >> 8) & 0xff;
- ptr[7] = lost & 0xff;
-
- ptr[8] = extMaxSeq >> 24;
- ptr[9] = (extMaxSeq >> 16) & 0xff;
- ptr[10] = (extMaxSeq >> 8) & 0xff;
- ptr[11] = extMaxSeq & 0xff;
-
- // XXX TODO:
-
- ptr[12] = 0x00; // interarrival jitter
- ptr[13] = 0x00;
- ptr[14] = 0x00;
- ptr[15] = 0x00;
-
- ptr[16] = 0x00; // last SR
- ptr[17] = 0x00;
- ptr[18] = 0x00;
- ptr[19] = 0x00;
-
- ptr[20] = 0x00; // delay since last SR
- ptr[21] = 0x00;
- ptr[22] = 0x00;
- ptr[23] = 0x00;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-RTPReceiver::RTPReceiver(
- const sp<ANetworkSession> &netSession,
- const sp<AMessage> ¬ify,
- uint32_t flags)
- : mNetSession(netSession),
- mNotify(notify),
- mFlags(flags),
- mRTPMode(TRANSPORT_UNDEFINED),
- mRTCPMode(TRANSPORT_UNDEFINED),
- mRTPSessionID(0),
- mRTCPSessionID(0),
- mRTPConnected(false),
- mRTCPConnected(false),
- mRTPClientSessionID(0),
- mRTCPClientSessionID(0) {
-}
-
-RTPReceiver::~RTPReceiver() {
- if (mRTCPClientSessionID != 0) {
- mNetSession->destroySession(mRTCPClientSessionID);
- mRTCPClientSessionID = 0;
- }
-
- if (mRTPClientSessionID != 0) {
- mNetSession->destroySession(mRTPClientSessionID);
- mRTPClientSessionID = 0;
- }
-
- if (mRTCPSessionID != 0) {
- mNetSession->destroySession(mRTCPSessionID);
- mRTCPSessionID = 0;
- }
-
- if (mRTPSessionID != 0) {
- mNetSession->destroySession(mRTPSessionID);
- mRTPSessionID = 0;
- }
-}
-
-status_t RTPReceiver::initAsync(
- TransportMode rtpMode,
- TransportMode rtcpMode,
- int32_t *outLocalRTPPort) {
- if (mRTPMode != TRANSPORT_UNDEFINED
- || rtpMode == TRANSPORT_UNDEFINED
- || rtpMode == TRANSPORT_NONE
- || rtcpMode == TRANSPORT_UNDEFINED) {
- return INVALID_OPERATION;
- }
-
- CHECK_NE(rtpMode, TRANSPORT_TCP_INTERLEAVED);
- CHECK_NE(rtcpMode, TRANSPORT_TCP_INTERLEAVED);
-
- sp<AMessage> rtpNotify = new AMessage(kWhatRTPNotify, id());
-
- sp<AMessage> rtcpNotify;
- if (rtcpMode != TRANSPORT_NONE) {
- rtcpNotify = new AMessage(kWhatRTCPNotify, id());
- }
-
- CHECK_EQ(mRTPSessionID, 0);
- CHECK_EQ(mRTCPSessionID, 0);
-
- int32_t localRTPPort;
-
- struct in_addr ifaceAddr;
- ifaceAddr.s_addr = INADDR_ANY;
-
- for (;;) {
- localRTPPort = PickRandomRTPPort();
-
- status_t err;
- if (rtpMode == TRANSPORT_UDP) {
- err = mNetSession->createUDPSession(
- localRTPPort,
- rtpNotify,
- &mRTPSessionID);
- } else {
- CHECK_EQ(rtpMode, TRANSPORT_TCP);
- err = mNetSession->createTCPDatagramSession(
- ifaceAddr,
- localRTPPort,
- rtpNotify,
- &mRTPSessionID);
- }
-
- if (err != OK) {
- continue;
- }
-
- if (rtcpMode == TRANSPORT_NONE) {
- break;
- } else if (rtcpMode == TRANSPORT_UDP) {
- err = mNetSession->createUDPSession(
- localRTPPort + 1,
- rtcpNotify,
- &mRTCPSessionID);
- } else {
- CHECK_EQ(rtpMode, TRANSPORT_TCP);
- err = mNetSession->createTCPDatagramSession(
- ifaceAddr,
- localRTPPort + 1,
- rtcpNotify,
- &mRTCPSessionID);
- }
-
- if (err == OK) {
- break;
- }
-
- mNetSession->destroySession(mRTPSessionID);
- mRTPSessionID = 0;
- }
-
- mRTPMode = rtpMode;
- mRTCPMode = rtcpMode;
- *outLocalRTPPort = localRTPPort;
-
- return OK;
-}
-
-status_t RTPReceiver::connect(
- const char *remoteHost, int32_t remoteRTPPort, int32_t remoteRTCPPort) {
- status_t err;
-
- if (mRTPMode == TRANSPORT_UDP) {
- CHECK(!mRTPConnected);
-
- err = mNetSession->connectUDPSession(
- mRTPSessionID, remoteHost, remoteRTPPort);
-
- if (err != OK) {
- notifyInitDone(err);
- return err;
- }
-
- ALOGI("connectUDPSession RTP successful.");
-
- mRTPConnected = true;
- }
-
- if (mRTCPMode == TRANSPORT_UDP) {
- CHECK(!mRTCPConnected);
-
- err = mNetSession->connectUDPSession(
- mRTCPSessionID, remoteHost, remoteRTCPPort);
-
- if (err != OK) {
- notifyInitDone(err);
- return err;
- }
-
- scheduleSendRR();
-
- ALOGI("connectUDPSession RTCP successful.");
-
- mRTCPConnected = true;
- }
-
- if (mRTPConnected
- && (mRTCPConnected || mRTCPMode == TRANSPORT_NONE)) {
- notifyInitDone(OK);
- }
-
- return OK;
-}
-
-status_t RTPReceiver::informSender(const sp<AMessage> ¶ms) {
- if (!mRTCPConnected) {
- return INVALID_OPERATION;
- }
-
- int64_t avgLatencyUs;
- CHECK(params->findInt64("avgLatencyUs", &avgLatencyUs));
-
- int64_t maxLatencyUs;
- CHECK(params->findInt64("maxLatencyUs", &maxLatencyUs));
-
- sp<ABuffer> buf = new ABuffer(28);
-
- uint8_t *ptr = buf->data();
- ptr[0] = 0x80 | 0;
- ptr[1] = 204; // APP
- ptr[2] = 0;
-
- CHECK((buf->size() % 4) == 0u);
- ptr[3] = (buf->size() / 4) - 1;
-
- ptr[4] = kSourceID >> 24; // SSRC
- ptr[5] = (kSourceID >> 16) & 0xff;
- ptr[6] = (kSourceID >> 8) & 0xff;
- ptr[7] = kSourceID & 0xff;
- ptr[8] = 'l';
- ptr[9] = 'a';
- ptr[10] = 't';
- ptr[11] = 'e';
-
- ptr[12] = avgLatencyUs >> 56;
- ptr[13] = (avgLatencyUs >> 48) & 0xff;
- ptr[14] = (avgLatencyUs >> 40) & 0xff;
- ptr[15] = (avgLatencyUs >> 32) & 0xff;
- ptr[16] = (avgLatencyUs >> 24) & 0xff;
- ptr[17] = (avgLatencyUs >> 16) & 0xff;
- ptr[18] = (avgLatencyUs >> 8) & 0xff;
- ptr[19] = avgLatencyUs & 0xff;
-
- ptr[20] = maxLatencyUs >> 56;
- ptr[21] = (maxLatencyUs >> 48) & 0xff;
- ptr[22] = (maxLatencyUs >> 40) & 0xff;
- ptr[23] = (maxLatencyUs >> 32) & 0xff;
- ptr[24] = (maxLatencyUs >> 24) & 0xff;
- ptr[25] = (maxLatencyUs >> 16) & 0xff;
- ptr[26] = (maxLatencyUs >> 8) & 0xff;
- ptr[27] = maxLatencyUs & 0xff;
-
- mNetSession->sendRequest(mRTCPSessionID, buf->data(), buf->size());
-
- return OK;
-}
-
-void RTPReceiver::onMessageReceived(const sp<AMessage> &msg) {
- switch (msg->what()) {
- case kWhatRTPNotify:
- case kWhatRTCPNotify:
- onNetNotify(msg->what() == kWhatRTPNotify, msg);
- break;
-
- case kWhatSendRR:
- {
- onSendRR();
- break;
- }
-
- default:
- TRESPASS();
- }
-}
-
-void RTPReceiver::onNetNotify(bool isRTP, const sp<AMessage> &msg) {
- int32_t reason;
- CHECK(msg->findInt32("reason", &reason));
-
- switch (reason) {
- case ANetworkSession::kWhatError:
- {
- int32_t sessionID;
- CHECK(msg->findInt32("sessionID", &sessionID));
-
- int32_t err;
- CHECK(msg->findInt32("err", &err));
-
- int32_t errorOccuredDuringSend;
- CHECK(msg->findInt32("send", &errorOccuredDuringSend));
-
- AString detail;
- CHECK(msg->findString("detail", &detail));
-
- ALOGE("An error occurred during %s in session %d "
- "(%d, '%s' (%s)).",
- errorOccuredDuringSend ? "send" : "receive",
- sessionID,
- err,
- detail.c_str(),
- strerror(-err));
-
- mNetSession->destroySession(sessionID);
-
- if (sessionID == mRTPSessionID) {
- mRTPSessionID = 0;
- } else if (sessionID == mRTCPSessionID) {
- mRTCPSessionID = 0;
- } else if (sessionID == mRTPClientSessionID) {
- mRTPClientSessionID = 0;
- } else if (sessionID == mRTCPClientSessionID) {
- mRTCPClientSessionID = 0;
- }
-
- if (!mRTPConnected
- || (mRTCPMode != TRANSPORT_NONE && !mRTCPConnected)) {
- notifyInitDone(err);
- break;
- }
-
- notifyError(err);
- break;
- }
-
- case ANetworkSession::kWhatDatagram:
- {
- sp<ABuffer> data;
- CHECK(msg->findBuffer("data", &data));
-
- if (isRTP) {
- if (mFlags & FLAG_AUTO_CONNECT) {
- AString fromAddr;
- CHECK(msg->findString("fromAddr", &fromAddr));
-
- int32_t fromPort;
- CHECK(msg->findInt32("fromPort", &fromPort));
-
- CHECK_EQ((status_t)OK,
- connect(
- fromAddr.c_str(), fromPort, fromPort + 1));
-
- mFlags &= ~FLAG_AUTO_CONNECT;
- }
-
- onRTPData(data);
- } else {
- onRTCPData(data);
- }
- break;
- }
-
- case ANetworkSession::kWhatClientConnected:
- {
- int32_t sessionID;
- CHECK(msg->findInt32("sessionID", &sessionID));
-
- if (isRTP) {
- CHECK_EQ(mRTPMode, TRANSPORT_TCP);
-
- if (mRTPClientSessionID != 0) {
- // We only allow a single client connection.
- mNetSession->destroySession(sessionID);
- sessionID = 0;
- break;
- }
-
- mRTPClientSessionID = sessionID;
- mRTPConnected = true;
- } else {
- CHECK_EQ(mRTCPMode, TRANSPORT_TCP);
-
- if (mRTCPClientSessionID != 0) {
- // We only allow a single client connection.
- mNetSession->destroySession(sessionID);
- sessionID = 0;
- break;
- }
-
- mRTCPClientSessionID = sessionID;
- mRTCPConnected = true;
- }
-
- if (mRTPConnected
- && (mRTCPConnected || mRTCPMode == TRANSPORT_NONE)) {
- notifyInitDone(OK);
- }
- break;
- }
- }
-}
-
-void RTPReceiver::notifyInitDone(status_t err) {
- sp<AMessage> notify = mNotify->dup();
- notify->setInt32("what", kWhatInitDone);
- notify->setInt32("err", err);
- notify->post();
-}
-
-void RTPReceiver::notifyError(status_t err) {
- sp<AMessage> notify = mNotify->dup();
- notify->setInt32("what", kWhatError);
- notify->setInt32("err", err);
- notify->post();
-}
-
-void RTPReceiver::notifyPacketLost() {
- sp<AMessage> notify = mNotify->dup();
- notify->setInt32("what", kWhatPacketLost);
- notify->post();
-}
-
-status_t RTPReceiver::onRTPData(const sp<ABuffer> &buffer) {
- size_t size = buffer->size();
- if (size < 12) {
- // Too short to be a valid RTP header.
- return ERROR_MALFORMED;
- }
-
- const uint8_t *data = buffer->data();
-
- if ((data[0] >> 6) != 2) {
- // Unsupported version.
- return ERROR_UNSUPPORTED;
- }
-
- if (data[0] & 0x20) {
- // Padding present.
-
- size_t paddingLength = data[size - 1];
-
- if (paddingLength + 12 > size) {
- // If we removed this much padding we'd end up with something
- // that's too short to be a valid RTP header.
- return ERROR_MALFORMED;
- }
-
- size -= paddingLength;
- }
-
- int numCSRCs = data[0] & 0x0f;
-
- size_t payloadOffset = 12 + 4 * numCSRCs;
-
- if (size < payloadOffset) {
- // Not enough data to fit the basic header and all the CSRC entries.
- return ERROR_MALFORMED;
- }
-
- if (data[0] & 0x10) {
- // Header eXtension present.
-
- if (size < payloadOffset + 4) {
- // Not enough data to fit the basic header, all CSRC entries
- // and the first 4 bytes of the extension header.
-
- return ERROR_MALFORMED;
- }
-
- const uint8_t *extensionData = &data[payloadOffset];
-
- size_t extensionLength =
- 4 * (extensionData[2] << 8 | extensionData[3]);
-
- if (size < payloadOffset + 4 + extensionLength) {
- return ERROR_MALFORMED;
- }
-
- payloadOffset += 4 + extensionLength;
- }
-
- uint32_t srcId = U32_AT(&data[8]);
- uint32_t rtpTime = U32_AT(&data[4]);
- uint16_t seqNo = U16_AT(&data[2]);
-
- sp<AMessage> meta = buffer->meta();
- meta->setInt32("ssrc", srcId);
- meta->setInt32("rtp-time", rtpTime);
- meta->setInt32("PT", data[1] & 0x7f);
- meta->setInt32("M", data[1] >> 7);
-
- buffer->setRange(payloadOffset, size - payloadOffset);
-
- ssize_t index = mSources.indexOfKey(srcId);
- sp<Source> source;
- if (index < 0) {
- source = new Source(this, srcId);
- looper()->registerHandler(source);
-
- mSources.add(srcId, source);
- } else {
- source = mSources.valueAt(index);
- }
-
- source->onPacketReceived(seqNo, buffer);
-
- return OK;
-}
-
-status_t RTPReceiver::onRTCPData(const sp<ABuffer> &data) {
- ALOGI("onRTCPData");
- return OK;
-}
-
-void RTPReceiver::addSDES(const sp<ABuffer> &buffer) {
- uint8_t *data = buffer->data() + buffer->size();
- data[0] = 0x80 | 1;
- data[1] = 202; // SDES
- data[4] = kSourceID >> 24; // SSRC
- data[5] = (kSourceID >> 16) & 0xff;
- data[6] = (kSourceID >> 8) & 0xff;
- data[7] = kSourceID & 0xff;
-
- size_t offset = 8;
-
- data[offset++] = 1; // CNAME
-
- AString cname = "stagefright@somewhere";
- data[offset++] = cname.size();
-
- memcpy(&data[offset], cname.c_str(), cname.size());
- offset += cname.size();
-
- data[offset++] = 6; // TOOL
-
- AString tool = "stagefright/1.0";
- data[offset++] = tool.size();
-
- memcpy(&data[offset], tool.c_str(), tool.size());
- offset += tool.size();
-
- data[offset++] = 0;
-
- if ((offset % 4) > 0) {
- size_t count = 4 - (offset % 4);
- switch (count) {
- case 3:
- data[offset++] = 0;
- case 2:
- data[offset++] = 0;
- case 1:
- data[offset++] = 0;
- }
- }
-
- size_t numWords = (offset / 4) - 1;
- data[2] = numWords >> 8;
- data[3] = numWords & 0xff;
-
- buffer->setRange(buffer->offset(), buffer->size() + offset);
-}
-
-void RTPReceiver::scheduleSendRR() {
- (new AMessage(kWhatSendRR, id()))->post(5000000ll);
-}
-
-void RTPReceiver::onSendRR() {
-#if 0
- sp<ABuffer> buf = new ABuffer(kMaxUDPPacketSize);
- buf->setRange(0, 0);
-
- uint8_t *ptr = buf->data();
- ptr[0] = 0x80 | 0;
- ptr[1] = 201; // RR
- ptr[2] = 0;
- ptr[3] = 1;
- ptr[4] = kSourceID >> 24; // SSRC
- ptr[5] = (kSourceID >> 16) & 0xff;
- ptr[6] = (kSourceID >> 8) & 0xff;
- ptr[7] = kSourceID & 0xff;
-
- buf->setRange(0, 8);
-
- size_t numReportBlocks = 0;
- for (size_t i = 0; i < mSources.size(); ++i) {
- uint32_t ssrc = mSources.keyAt(i);
- sp<Source> source = mSources.valueAt(i);
-
- if (numReportBlocks > 31 || buf->size() + 24 > buf->capacity()) {
- // Cannot fit another report block.
- break;
- }
-
- source->addReportBlock(ssrc, buf);
- ++numReportBlocks;
- }
-
- ptr[0] |= numReportBlocks; // 5 bit
-
- size_t sizeInWordsMinus1 = 1 + 6 * numReportBlocks;
- ptr[2] = sizeInWordsMinus1 >> 8;
- ptr[3] = sizeInWordsMinus1 & 0xff;
-
- buf->setRange(0, (sizeInWordsMinus1 + 1) * 4);
-
- addSDES(buf);
-
- mNetSession->sendRequest(mRTCPSessionID, buf->data(), buf->size());
-#endif
-
- scheduleSendRR();
-}
-
-status_t RTPReceiver::registerPacketType(
- uint8_t packetType, PacketizationMode mode) {
- mPacketTypes.add(packetType, mode);
-
- return OK;
-}
-
-sp<RTPReceiver::Assembler> RTPReceiver::makeAssembler(uint8_t packetType) {
- ssize_t index = mPacketTypes.indexOfKey(packetType);
- if (index < 0) {
- return NULL;
- }
-
- PacketizationMode mode = mPacketTypes.valueAt(index);
-
- switch (mode) {
- case PACKETIZATION_NONE:
- case PACKETIZATION_TRANSPORT_STREAM:
- return new TSAssembler(mNotify);
-
- case PACKETIZATION_H264:
- return new H264Assembler(mNotify);
-
- default:
- return NULL;
- }
-}
-
-void RTPReceiver::requestRetransmission(uint32_t senderSSRC, int32_t extSeqNo) {
- int32_t blp = 0;
-
- sp<ABuffer> buf = new ABuffer(16);
- buf->setRange(0, 0);
-
- uint8_t *ptr = buf->data();
- ptr[0] = 0x80 | 1; // generic NACK
- ptr[1] = 205; // TSFB
- ptr[2] = 0;
- ptr[3] = 3;
- ptr[8] = (senderSSRC >> 24) & 0xff;
- ptr[9] = (senderSSRC >> 16) & 0xff;
- ptr[10] = (senderSSRC >> 8) & 0xff;
- ptr[11] = (senderSSRC & 0xff);
- ptr[8] = (kSourceID >> 24) & 0xff;
- ptr[9] = (kSourceID >> 16) & 0xff;
- ptr[10] = (kSourceID >> 8) & 0xff;
- ptr[11] = (kSourceID & 0xff);
- ptr[12] = (extSeqNo >> 8) & 0xff;
- ptr[13] = (extSeqNo & 0xff);
- ptr[14] = (blp >> 8) & 0xff;
- ptr[15] = (blp & 0xff);
-
- buf->setRange(0, 16);
-
- mNetSession->sendRequest(mRTCPSessionID, buf->data(), buf->size());
-}
-
-void RTPReceiver::Source::modifyPacketStatus(int32_t extSeqNo, uint32_t mask) {
-#if TRACK_PACKET_LOSS
- ssize_t index = mLostPackets.indexOfKey(extSeqNo);
- if (index < 0) {
- mLostPackets.add(extSeqNo, mask);
- } else {
- mLostPackets.editValueAt(index) |= mask;
- }
-#endif
-}
-
-void RTPReceiver::Source::postRetransmitTimer(int64_t timeUs) {
- int64_t delayUs = timeUs - ALooper::GetNowUs();
- sp<AMessage> msg = new AMessage(kWhatRetransmit, id());
- msg->setInt32("generation", mRetransmitGeneration);
- msg->post(delayUs);
-}
-
-void RTPReceiver::Source::postDeclareLostTimer(int64_t timeUs) {
- CHECK(!mDeclareLostTimerPending);
- mDeclareLostTimerPending = true;
-
- int64_t delayUs = timeUs - ALooper::GetNowUs();
- sp<AMessage> msg = new AMessage(kWhatDeclareLost, id());
- msg->setInt32("generation", mDeclareLostGeneration);
- msg->post(delayUs);
-}
-
-void RTPReceiver::Source::cancelTimers() {
- ++mRetransmitGeneration;
- ++mDeclareLostGeneration;
- mDeclareLostTimerPending = false;
-}
-
-} // namespace android
-
diff --git a/media/libstagefright/wifi-display/rtp/RTPReceiver.h b/media/libstagefright/wifi-display/rtp/RTPReceiver.h
deleted file mode 100644
index 240ab2e..0000000
--- a/media/libstagefright/wifi-display/rtp/RTPReceiver.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright 2013, 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 RTP_RECEIVER_H_
-
-#define RTP_RECEIVER_H_
-
-#include "RTPBase.h"
-
-#include <media/stagefright/foundation/AHandler.h>
-
-namespace android {
-
-struct ABuffer;
-struct ANetworkSession;
-
-// An object of this class facilitates receiving of media data on an RTP
-// channel. The channel is established over a UDP or TCP connection depending
-// on which "TransportMode" was chosen. In addition different RTP packetization
-// schemes are supported such as "Transport Stream Packets over RTP",
-// or "AVC/H.264 encapsulation as specified in RFC 3984 (non-interleaved mode)"
-struct RTPReceiver : public RTPBase, public AHandler {
- enum {
- kWhatInitDone,
- kWhatError,
- kWhatAccessUnit,
- kWhatPacketLost,
- };
-
- enum Flags {
- FLAG_AUTO_CONNECT = 1,
- };
- RTPReceiver(
- const sp<ANetworkSession> &netSession,
- const sp<AMessage> ¬ify,
- uint32_t flags = 0);
-
- status_t registerPacketType(
- uint8_t packetType, PacketizationMode mode);
-
- status_t initAsync(
- TransportMode rtpMode,
- TransportMode rtcpMode,
- int32_t *outLocalRTPPort);
-
- status_t connect(
- const char *remoteHost,
- int32_t remoteRTPPort,
- int32_t remoteRTCPPort);
-
- status_t informSender(const sp<AMessage> ¶ms);
-
-protected:
- virtual ~RTPReceiver();
- virtual void onMessageReceived(const sp<AMessage> &msg);
-
-private:
- enum {
- kWhatRTPNotify,
- kWhatRTCPNotify,
- kWhatSendRR,
- };
-
- enum {
- kSourceID = 0xdeadbeef,
- kPacketLostAfterUs = 100000,
- kRequestRetransmissionAfterUs = -1,
- };
-
- struct Assembler;
- struct H264Assembler;
- struct Source;
- struct TSAssembler;
-
- sp<ANetworkSession> mNetSession;
- sp<AMessage> mNotify;
- uint32_t mFlags;
- TransportMode mRTPMode;
- TransportMode mRTCPMode;
- int32_t mRTPSessionID;
- int32_t mRTCPSessionID;
- bool mRTPConnected;
- bool mRTCPConnected;
-
- int32_t mRTPClientSessionID; // in TRANSPORT_TCP mode.
- int32_t mRTCPClientSessionID; // in TRANSPORT_TCP mode.
-
- KeyedVector<uint8_t, PacketizationMode> mPacketTypes;
- KeyedVector<uint32_t, sp<Source> > mSources;
-
- void onNetNotify(bool isRTP, const sp<AMessage> &msg);
- status_t onRTPData(const sp<ABuffer> &data);
- status_t onRTCPData(const sp<ABuffer> &data);
- void onSendRR();
-
- void scheduleSendRR();
- void addSDES(const sp<ABuffer> &buffer);
-
- void notifyInitDone(status_t err);
- void notifyError(status_t err);
- void notifyPacketLost();
-
- sp<Assembler> makeAssembler(uint8_t packetType);
-
- void requestRetransmission(uint32_t senderSSRC, int32_t extSeqNo);
-
- DISALLOW_EVIL_CONSTRUCTORS(RTPReceiver);
-};
-
-} // namespace android
-
-#endif // RTP_RECEIVER_H_
diff --git a/media/libstagefright/wifi-display/rtp/RTPSender.cpp b/media/libstagefright/wifi-display/rtp/RTPSender.cpp
index 6bbe650..095fd97 100644
--- a/media/libstagefright/wifi-display/rtp/RTPSender.cpp
+++ b/media/libstagefright/wifi-display/rtp/RTPSender.cpp
@@ -767,17 +767,6 @@
}
status_t RTPSender::parseAPP(const uint8_t *data, size_t size) {
- if (!memcmp("late", &data[8], 4)) {
- int64_t avgLatencyUs = (int64_t)U64_AT(&data[12]);
- int64_t maxLatencyUs = (int64_t)U64_AT(&data[20]);
-
- sp<AMessage> notify = mNotify->dup();
- notify->setInt32("what", kWhatInformSender);
- notify->setInt64("avgLatencyUs", avgLatencyUs);
- notify->setInt64("maxLatencyUs", maxLatencyUs);
- notify->post();
- }
-
return OK;
}
diff --git a/media/libstagefright/wifi-display/rtp/RTPSender.h b/media/libstagefright/wifi-display/rtp/RTPSender.h
index fefcab7..7dc138a 100644
--- a/media/libstagefright/wifi-display/rtp/RTPSender.h
+++ b/media/libstagefright/wifi-display/rtp/RTPSender.h
@@ -37,7 +37,6 @@
kWhatInitDone,
kWhatError,
kWhatNetworkStall,
- kWhatInformSender,
};
RTPSender(
const sp<ANetworkSession> &netSession,
diff --git a/media/libstagefright/wifi-display/rtptest.cpp b/media/libstagefright/wifi-display/rtptest.cpp
deleted file mode 100644
index 764a38b..0000000
--- a/media/libstagefright/wifi-display/rtptest.cpp
+++ /dev/null
@@ -1,565 +0,0 @@
-/*
- * Copyright 2013, 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_NEBUG 0
-#define LOG_TAG "rtptest"
-#include <utils/Log.h>
-
-#include "ANetworkSession.h"
-#include "rtp/RTPSender.h"
-#include "rtp/RTPReceiver.h"
-#include "TimeSyncer.h"
-
-#include <binder/ProcessState.h>
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AHandler.h>
-#include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/foundation/hexdump.h>
-#include <media/stagefright/DataSource.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/NuMediaExtractor.h>
-#include <media/stagefright/Utils.h>
-
-#define MEDIA_FILENAME "/sdcard/Frame Counter HD 30FPS_1080p.mp4"
-
-namespace android {
-
-struct PacketSource : public RefBase {
- PacketSource() {}
-
- virtual sp<ABuffer> getNextAccessUnit() = 0;
-
-protected:
- virtual ~PacketSource() {}
-
-private:
- DISALLOW_EVIL_CONSTRUCTORS(PacketSource);
-};
-
-struct MediaPacketSource : public PacketSource {
- MediaPacketSource()
- : mMaxSampleSize(1024 * 1024) {
- mExtractor = new NuMediaExtractor;
- CHECK_EQ((status_t)OK,
- mExtractor->setDataSource(MEDIA_FILENAME));
-
- bool haveVideo = false;
- for (size_t i = 0; i < mExtractor->countTracks(); ++i) {
- sp<AMessage> format;
- CHECK_EQ((status_t)OK, mExtractor->getTrackFormat(i, &format));
-
- AString mime;
- CHECK(format->findString("mime", &mime));
-
- if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str())) {
- mExtractor->selectTrack(i);
- haveVideo = true;
- break;
- }
- }
-
- CHECK(haveVideo);
- }
-
- virtual sp<ABuffer> getNextAccessUnit() {
- int64_t timeUs;
- status_t err = mExtractor->getSampleTime(&timeUs);
-
- if (err != OK) {
- return NULL;
- }
-
- sp<ABuffer> accessUnit = new ABuffer(mMaxSampleSize);
- CHECK_EQ((status_t)OK, mExtractor->readSampleData(accessUnit));
-
- accessUnit->meta()->setInt64("timeUs", timeUs);
-
- CHECK_EQ((status_t)OK, mExtractor->advance());
-
- return accessUnit;
- }
-
-protected:
- virtual ~MediaPacketSource() {
- }
-
-private:
- sp<NuMediaExtractor> mExtractor;
- size_t mMaxSampleSize;
-
- DISALLOW_EVIL_CONSTRUCTORS(MediaPacketSource);
-};
-
-struct SimplePacketSource : public PacketSource {
- SimplePacketSource()
- : mCounter(0) {
- }
-
- virtual sp<ABuffer> getNextAccessUnit() {
- sp<ABuffer> buffer = new ABuffer(4);
- uint8_t *dst = buffer->data();
- dst[0] = mCounter >> 24;
- dst[1] = (mCounter >> 16) & 0xff;
- dst[2] = (mCounter >> 8) & 0xff;
- dst[3] = mCounter & 0xff;
-
- buffer->meta()->setInt64("timeUs", mCounter * 1000000ll / kFrameRate);
-
- ++mCounter;
-
- return buffer;
- }
-
-protected:
- virtual ~SimplePacketSource() {
- }
-
-private:
- enum {
- kFrameRate = 30
- };
-
- uint32_t mCounter;
-
- DISALLOW_EVIL_CONSTRUCTORS(SimplePacketSource);
-};
-
-struct TestHandler : public AHandler {
- TestHandler(const sp<ANetworkSession> &netSession);
-
- void listen();
- void connect(const char *host, int32_t port);
-
-protected:
- virtual ~TestHandler();
- virtual void onMessageReceived(const sp<AMessage> &msg);
-
-private:
- enum {
- kWhatListen,
- kWhatConnect,
- kWhatReceiverNotify,
- kWhatSenderNotify,
- kWhatSendMore,
- kWhatStop,
- kWhatTimeSyncerNotify,
- };
-
-#if 1
- static const RTPBase::TransportMode kRTPMode = RTPBase::TRANSPORT_UDP;
- static const RTPBase::TransportMode kRTCPMode = RTPBase::TRANSPORT_UDP;
-#else
- static const RTPBase::TransportMode kRTPMode = RTPBase::TRANSPORT_TCP;
- static const RTPBase::TransportMode kRTCPMode = RTPBase::TRANSPORT_NONE;
-#endif
-
-#if 1
- static const RTPBase::PacketizationMode kPacketizationMode
- = RTPBase::PACKETIZATION_H264;
-#else
- static const RTPBase::PacketizationMode kPacketizationMode
- = RTPBase::PACKETIZATION_NONE;
-#endif
-
- sp<ANetworkSession> mNetSession;
- sp<PacketSource> mSource;
- sp<RTPSender> mSender;
- sp<RTPReceiver> mReceiver;
-
- sp<TimeSyncer> mTimeSyncer;
- bool mTimeSyncerStarted;
-
- int64_t mFirstTimeRealUs;
- int64_t mFirstTimeMediaUs;
-
- int64_t mTimeOffsetUs;
- bool mTimeOffsetValid;
-
- status_t readMore();
-
- DISALLOW_EVIL_CONSTRUCTORS(TestHandler);
-};
-
-TestHandler::TestHandler(const sp<ANetworkSession> &netSession)
- : mNetSession(netSession),
- mTimeSyncerStarted(false),
- mFirstTimeRealUs(-1ll),
- mFirstTimeMediaUs(-1ll),
- mTimeOffsetUs(-1ll),
- mTimeOffsetValid(false) {
-}
-
-TestHandler::~TestHandler() {
-}
-
-void TestHandler::listen() {
- sp<AMessage> msg = new AMessage(kWhatListen, id());
- msg->post();
-}
-
-void TestHandler::connect(const char *host, int32_t port) {
- sp<AMessage> msg = new AMessage(kWhatConnect, id());
- msg->setString("host", host);
- msg->setInt32("port", port);
- msg->post();
-}
-
-static void dumpDelay(int64_t delayMs) {
- static const int64_t kMinDelayMs = 0;
- static const int64_t kMaxDelayMs = 300;
-
- const char *kPattern = "########################################";
- size_t kPatternSize = strlen(kPattern);
-
- int n = (kPatternSize * (delayMs - kMinDelayMs))
- / (kMaxDelayMs - kMinDelayMs);
-
- if (n < 0) {
- n = 0;
- } else if ((size_t)n > kPatternSize) {
- n = kPatternSize;
- }
-
- ALOGI("(%4lld ms) %s\n",
- delayMs,
- kPattern + kPatternSize - n);
-}
-
-void TestHandler::onMessageReceived(const sp<AMessage> &msg) {
- switch (msg->what()) {
- case kWhatListen:
- {
- sp<AMessage> notify = new AMessage(kWhatTimeSyncerNotify, id());
- mTimeSyncer = new TimeSyncer(mNetSession, notify);
- looper()->registerHandler(mTimeSyncer);
-
- notify = new AMessage(kWhatReceiverNotify, id());
- mReceiver = new RTPReceiver(
- mNetSession, notify, RTPReceiver::FLAG_AUTO_CONNECT);
- looper()->registerHandler(mReceiver);
-
- CHECK_EQ((status_t)OK,
- mReceiver->registerPacketType(33, kPacketizationMode));
-
- int32_t receiverRTPPort;
- CHECK_EQ((status_t)OK,
- mReceiver->initAsync(
- kRTPMode,
- kRTCPMode,
- &receiverRTPPort));
-
- printf("picked receiverRTPPort %d\n", receiverRTPPort);
-
-#if 0
- CHECK_EQ((status_t)OK,
- mReceiver->connect(
- "127.0.0.1", senderRTPPort, senderRTPPort + 1));
-#endif
- break;
- }
-
- case kWhatConnect:
- {
- AString host;
- CHECK(msg->findString("host", &host));
-
- sp<AMessage> notify = new AMessage(kWhatTimeSyncerNotify, id());
- mTimeSyncer = new TimeSyncer(mNetSession, notify);
- looper()->registerHandler(mTimeSyncer);
- mTimeSyncer->startServer(8123);
-
- int32_t receiverRTPPort;
- CHECK(msg->findInt32("port", &receiverRTPPort));
-
-#if 1
- mSource = new MediaPacketSource;
-#else
- mSource = new SimplePacketSource;
-#endif
-
- notify = new AMessage(kWhatSenderNotify, id());
- mSender = new RTPSender(mNetSession, notify);
-
- looper()->registerHandler(mSender);
-
- int32_t senderRTPPort;
- CHECK_EQ((status_t)OK,
- mSender->initAsync(
- host.c_str(),
- receiverRTPPort,
- kRTPMode,
- kRTCPMode == RTPBase::TRANSPORT_NONE
- ? -1 : receiverRTPPort + 1,
- kRTCPMode,
- &senderRTPPort));
-
- printf("picked senderRTPPort %d\n", senderRTPPort);
- break;
- }
-
- case kWhatSenderNotify:
- {
- ALOGI("kWhatSenderNotify");
-
- int32_t what;
- CHECK(msg->findInt32("what", &what));
-
- switch (what) {
- case RTPSender::kWhatInitDone:
- {
- int32_t err;
- CHECK(msg->findInt32("err", &err));
-
- ALOGI("RTPSender::initAsync completed w/ err %d", err);
-
- if (err == OK) {
- err = readMore();
-
- if (err != OK) {
- (new AMessage(kWhatStop, id()))->post();
- }
- }
- break;
- }
-
- case RTPSender::kWhatError:
- break;
- }
- break;
- }
-
- case kWhatReceiverNotify:
- {
- ALOGV("kWhatReceiverNotify");
-
- int32_t what;
- CHECK(msg->findInt32("what", &what));
-
- switch (what) {
- case RTPReceiver::kWhatInitDone:
- {
- int32_t err;
- CHECK(msg->findInt32("err", &err));
-
- ALOGI("RTPReceiver::initAsync completed w/ err %d", err);
- break;
- }
-
- case RTPReceiver::kWhatError:
- break;
-
- case RTPReceiver::kWhatAccessUnit:
- {
-#if 0
- if (!mTimeSyncerStarted) {
- mTimeSyncer->startClient("172.18.41.216", 8123);
- mTimeSyncerStarted = true;
- }
-
- sp<ABuffer> accessUnit;
- CHECK(msg->findBuffer("accessUnit", &accessUnit));
-
- int64_t timeUs;
- CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
-
- if (mTimeOffsetValid) {
- timeUs -= mTimeOffsetUs;
- int64_t nowUs = ALooper::GetNowUs();
- int64_t delayMs = (nowUs - timeUs) / 1000ll;
-
- dumpDelay(delayMs);
- }
-#endif
- break;
- }
-
- case RTPReceiver::kWhatPacketLost:
- ALOGV("kWhatPacketLost");
- break;
-
- default:
- TRESPASS();
- }
- break;
- }
-
- case kWhatSendMore:
- {
- sp<ABuffer> accessUnit;
- CHECK(msg->findBuffer("accessUnit", &accessUnit));
-
- CHECK_EQ((status_t)OK,
- mSender->queueBuffer(
- accessUnit,
- 33,
- kPacketizationMode));
-
- status_t err = readMore();
-
- if (err != OK) {
- (new AMessage(kWhatStop, id()))->post();
- }
- break;
- }
-
- case kWhatStop:
- {
- if (mReceiver != NULL) {
- looper()->unregisterHandler(mReceiver->id());
- mReceiver.clear();
- }
-
- if (mSender != NULL) {
- looper()->unregisterHandler(mSender->id());
- mSender.clear();
- }
-
- mSource.clear();
-
- looper()->stop();
- break;
- }
-
- case kWhatTimeSyncerNotify:
- {
- CHECK(msg->findInt64("offset", &mTimeOffsetUs));
- mTimeOffsetValid = true;
- break;
- }
-
- default:
- TRESPASS();
- }
-}
-
-status_t TestHandler::readMore() {
- sp<ABuffer> accessUnit = mSource->getNextAccessUnit();
-
- if (accessUnit == NULL) {
- return ERROR_END_OF_STREAM;
- }
-
- int64_t timeUs;
- CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
-
- int64_t nowUs = ALooper::GetNowUs();
- int64_t whenUs;
-
- if (mFirstTimeRealUs < 0ll) {
- mFirstTimeRealUs = whenUs = nowUs;
- mFirstTimeMediaUs = timeUs;
- } else {
- whenUs = mFirstTimeRealUs + timeUs - mFirstTimeMediaUs;
- }
-
- accessUnit->meta()->setInt64("timeUs", whenUs);
-
- sp<AMessage> msg = new AMessage(kWhatSendMore, id());
- msg->setBuffer("accessUnit", accessUnit);
- msg->post(whenUs - nowUs);
-
- return OK;
-}
-
-} // namespace android
-
-static void usage(const char *me) {
- fprintf(stderr,
- "usage: %s -c host:port\tconnect to remote host\n"
- " -l \tlisten\n",
- me);
-}
-
-int main(int argc, char **argv) {
- using namespace android;
-
- // srand(time(NULL));
-
- ProcessState::self()->startThreadPool();
-
- DataSource::RegisterDefaultSniffers();
-
- bool listen = false;
- int32_t connectToPort = -1;
- AString connectToHost;
-
- int res;
- while ((res = getopt(argc, argv, "hc:l")) >= 0) {
- switch (res) {
- case 'c':
- {
- const char *colonPos = strrchr(optarg, ':');
-
- if (colonPos == NULL) {
- usage(argv[0]);
- exit(1);
- }
-
- connectToHost.setTo(optarg, colonPos - optarg);
-
- char *end;
- connectToPort = strtol(colonPos + 1, &end, 10);
-
- if (*end != '\0' || end == colonPos + 1
- || connectToPort < 1 || connectToPort > 65535) {
- fprintf(stderr, "Illegal port specified.\n");
- exit(1);
- }
- break;
- }
-
- case 'l':
- {
- listen = true;
- break;
- }
-
- case '?':
- case 'h':
- usage(argv[0]);
- exit(1);
- }
- }
-
- if (!listen && connectToPort < 0) {
- fprintf(stderr,
- "You need to select either client or server mode.\n");
- exit(1);
- }
-
- sp<ANetworkSession> netSession = new ANetworkSession;
- netSession->start();
-
- sp<ALooper> looper = new ALooper;
-
- sp<TestHandler> handler = new TestHandler(netSession);
- looper->registerHandler(handler);
-
- if (listen) {
- handler->listen();
- }
-
- if (connectToPort >= 0) {
- handler->connect(connectToHost.c_str(), connectToPort);
- }
-
- looper->start(true /* runOnCallingThread */);
-
- return 0;
-}
-
diff --git a/media/libstagefright/wifi-display/sink/DirectRenderer.cpp b/media/libstagefright/wifi-display/sink/DirectRenderer.cpp
deleted file mode 100644
index 15f9c88..0000000
--- a/media/libstagefright/wifi-display/sink/DirectRenderer.cpp
+++ /dev/null
@@ -1,625 +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 "DirectRenderer"
-#include <utils/Log.h>
-
-#include "DirectRenderer.h"
-
-#include <gui/SurfaceComposerClient.h>
-#include <gui/Surface.h>
-#include <media/AudioTrack.h>
-#include <media/ICrypto.h>
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/foundation/hexdump.h>
-#include <media/stagefright/MediaCodec.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/Utils.h>
-
-namespace android {
-
-/*
- Drives the decoding process using a MediaCodec instance. Input buffers
- queued by calls to "queueInputBuffer" are fed to the decoder as soon
- as the decoder is ready for them, the client is notified about output
- buffers as the decoder spits them out.
-*/
-struct DirectRenderer::DecoderContext : public AHandler {
- enum {
- kWhatOutputBufferReady,
- };
- DecoderContext(const sp<AMessage> ¬ify);
-
- status_t init(
- const sp<AMessage> &format,
- const sp<IGraphicBufferProducer> &surfaceTex);
-
- void queueInputBuffer(const sp<ABuffer> &accessUnit);
-
- status_t renderOutputBufferAndRelease(size_t index);
- status_t releaseOutputBuffer(size_t index);
-
-protected:
- virtual ~DecoderContext();
-
- virtual void onMessageReceived(const sp<AMessage> &msg);
-
-private:
- enum {
- kWhatDecoderNotify,
- };
-
- sp<AMessage> mNotify;
- sp<ALooper> mDecoderLooper;
- sp<MediaCodec> mDecoder;
- Vector<sp<ABuffer> > mDecoderInputBuffers;
- Vector<sp<ABuffer> > mDecoderOutputBuffers;
- List<size_t> mDecoderInputBuffersAvailable;
- bool mDecoderNotificationPending;
-
- List<sp<ABuffer> > mAccessUnits;
-
- void onDecoderNotify();
- void scheduleDecoderNotification();
- void queueDecoderInputBuffers();
-
- void queueOutputBuffer(
- size_t index, int64_t timeUs, const sp<ABuffer> &buffer);
-
- DISALLOW_EVIL_CONSTRUCTORS(DecoderContext);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-/*
- A "push" audio renderer. The primary function of this renderer is to use
- an AudioTrack in push mode and making sure not to block the event loop
- be ensuring that calls to AudioTrack::write never block. This is done by
- estimating an upper bound of data that can be written to the AudioTrack
- buffer without delay.
-*/
-struct DirectRenderer::AudioRenderer : public AHandler {
- AudioRenderer(const sp<DecoderContext> &decoderContext);
-
- void queueInputBuffer(
- size_t index, int64_t timeUs, const sp<ABuffer> &buffer);
-
-protected:
- virtual ~AudioRenderer();
- virtual void onMessageReceived(const sp<AMessage> &msg);
-
-private:
- enum {
- kWhatPushAudio,
- };
-
- struct BufferInfo {
- size_t mIndex;
- int64_t mTimeUs;
- sp<ABuffer> mBuffer;
- };
-
- sp<DecoderContext> mDecoderContext;
- sp<AudioTrack> mAudioTrack;
-
- List<BufferInfo> mInputBuffers;
- bool mPushPending;
-
- size_t mNumFramesWritten;
-
- void schedulePushIfNecessary();
- void onPushAudio();
-
- ssize_t writeNonBlocking(const uint8_t *data, size_t size);
-
- DISALLOW_EVIL_CONSTRUCTORS(AudioRenderer);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-DirectRenderer::DecoderContext::DecoderContext(const sp<AMessage> ¬ify)
- : mNotify(notify),
- mDecoderNotificationPending(false) {
-}
-
-DirectRenderer::DecoderContext::~DecoderContext() {
- if (mDecoder != NULL) {
- mDecoder->release();
- mDecoder.clear();
-
- mDecoderLooper->stop();
- mDecoderLooper.clear();
- }
-}
-
-status_t DirectRenderer::DecoderContext::init(
- const sp<AMessage> &format,
- const sp<IGraphicBufferProducer> &surfaceTex) {
- CHECK(mDecoder == NULL);
-
- AString mime;
- CHECK(format->findString("mime", &mime));
-
- mDecoderLooper = new ALooper;
- mDecoderLooper->setName("video codec looper");
-
- mDecoderLooper->start(
- false /* runOnCallingThread */,
- false /* canCallJava */,
- PRIORITY_DEFAULT);
-
- mDecoder = MediaCodec::CreateByType(
- mDecoderLooper, mime.c_str(), false /* encoder */);
-
- CHECK(mDecoder != NULL);
-
- status_t err = mDecoder->configure(
- format,
- surfaceTex == NULL
- ? NULL : new Surface(surfaceTex),
- NULL /* crypto */,
- 0 /* flags */);
- CHECK_EQ(err, (status_t)OK);
-
- err = mDecoder->start();
- CHECK_EQ(err, (status_t)OK);
-
- err = mDecoder->getInputBuffers(
- &mDecoderInputBuffers);
- CHECK_EQ(err, (status_t)OK);
-
- err = mDecoder->getOutputBuffers(
- &mDecoderOutputBuffers);
- CHECK_EQ(err, (status_t)OK);
-
- scheduleDecoderNotification();
-
- return OK;
-}
-
-void DirectRenderer::DecoderContext::queueInputBuffer(
- const sp<ABuffer> &accessUnit) {
- CHECK(mDecoder != NULL);
-
- mAccessUnits.push_back(accessUnit);
- queueDecoderInputBuffers();
-}
-
-status_t DirectRenderer::DecoderContext::renderOutputBufferAndRelease(
- size_t index) {
- return mDecoder->renderOutputBufferAndRelease(index);
-}
-
-status_t DirectRenderer::DecoderContext::releaseOutputBuffer(size_t index) {
- return mDecoder->releaseOutputBuffer(index);
-}
-
-void DirectRenderer::DecoderContext::queueDecoderInputBuffers() {
- if (mDecoder == NULL) {
- return;
- }
-
- bool submittedMore = false;
-
- while (!mAccessUnits.empty()
- && !mDecoderInputBuffersAvailable.empty()) {
- size_t index = *mDecoderInputBuffersAvailable.begin();
-
- mDecoderInputBuffersAvailable.erase(
- mDecoderInputBuffersAvailable.begin());
-
- sp<ABuffer> srcBuffer = *mAccessUnits.begin();
- mAccessUnits.erase(mAccessUnits.begin());
-
- const sp<ABuffer> &dstBuffer =
- mDecoderInputBuffers.itemAt(index);
-
- memcpy(dstBuffer->data(), srcBuffer->data(), srcBuffer->size());
-
- int64_t timeUs;
- CHECK(srcBuffer->meta()->findInt64("timeUs", &timeUs));
-
- status_t err = mDecoder->queueInputBuffer(
- index,
- 0 /* offset */,
- srcBuffer->size(),
- timeUs,
- 0 /* flags */);
- CHECK_EQ(err, (status_t)OK);
-
- submittedMore = true;
- }
-
- if (submittedMore) {
- scheduleDecoderNotification();
- }
-}
-
-void DirectRenderer::DecoderContext::onMessageReceived(
- const sp<AMessage> &msg) {
- switch (msg->what()) {
- case kWhatDecoderNotify:
- {
- onDecoderNotify();
- break;
- }
-
- default:
- TRESPASS();
- }
-}
-
-void DirectRenderer::DecoderContext::onDecoderNotify() {
- mDecoderNotificationPending = false;
-
- for (;;) {
- size_t index;
- status_t err = mDecoder->dequeueInputBuffer(&index);
-
- if (err == OK) {
- mDecoderInputBuffersAvailable.push_back(index);
- } else if (err == -EAGAIN) {
- break;
- } else {
- TRESPASS();
- }
- }
-
- queueDecoderInputBuffers();
-
- for (;;) {
- size_t index;
- size_t offset;
- size_t size;
- int64_t timeUs;
- uint32_t flags;
- status_t err = mDecoder->dequeueOutputBuffer(
- &index,
- &offset,
- &size,
- &timeUs,
- &flags);
-
- if (err == OK) {
- queueOutputBuffer(
- index, timeUs, mDecoderOutputBuffers.itemAt(index));
- } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) {
- err = mDecoder->getOutputBuffers(
- &mDecoderOutputBuffers);
- CHECK_EQ(err, (status_t)OK);
- } else if (err == INFO_FORMAT_CHANGED) {
- // We don't care.
- } else if (err == -EAGAIN) {
- break;
- } else {
- TRESPASS();
- }
- }
-
- scheduleDecoderNotification();
-}
-
-void DirectRenderer::DecoderContext::scheduleDecoderNotification() {
- if (mDecoderNotificationPending) {
- return;
- }
-
- sp<AMessage> notify =
- new AMessage(kWhatDecoderNotify, id());
-
- mDecoder->requestActivityNotification(notify);
- mDecoderNotificationPending = true;
-}
-
-void DirectRenderer::DecoderContext::queueOutputBuffer(
- size_t index, int64_t timeUs, const sp<ABuffer> &buffer) {
- sp<AMessage> msg = mNotify->dup();
- msg->setInt32("what", kWhatOutputBufferReady);
- msg->setSize("index", index);
- msg->setInt64("timeUs", timeUs);
- msg->setBuffer("buffer", buffer);
- msg->post();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-DirectRenderer::AudioRenderer::AudioRenderer(
- const sp<DecoderContext> &decoderContext)
- : mDecoderContext(decoderContext),
- mPushPending(false),
- mNumFramesWritten(0) {
- mAudioTrack = new AudioTrack(
- AUDIO_STREAM_DEFAULT,
- 48000.0f,
- AUDIO_FORMAT_PCM,
- AUDIO_CHANNEL_OUT_STEREO,
- (int)0 /* frameCount */);
-
- CHECK_EQ((status_t)OK, mAudioTrack->initCheck());
-
- mAudioTrack->start();
-}
-
-DirectRenderer::AudioRenderer::~AudioRenderer() {
-}
-
-void DirectRenderer::AudioRenderer::queueInputBuffer(
- size_t index, int64_t timeUs, const sp<ABuffer> &buffer) {
- BufferInfo info;
- info.mIndex = index;
- info.mTimeUs = timeUs;
- info.mBuffer = buffer;
-
- mInputBuffers.push_back(info);
- schedulePushIfNecessary();
-}
-
-void DirectRenderer::AudioRenderer::onMessageReceived(
- const sp<AMessage> &msg) {
- switch (msg->what()) {
- case kWhatPushAudio:
- {
- onPushAudio();
- break;
- }
-
- default:
- break;
- }
-}
-
-void DirectRenderer::AudioRenderer::schedulePushIfNecessary() {
- if (mPushPending || mInputBuffers.empty()) {
- return;
- }
-
- mPushPending = true;
-
- uint32_t numFramesPlayed;
- CHECK_EQ(mAudioTrack->getPosition(&numFramesPlayed),
- (status_t)OK);
-
- uint32_t numFramesPendingPlayout = mNumFramesWritten - numFramesPlayed;
-
- // This is how long the audio sink will have data to
- // play back.
- const float msecsPerFrame = 1000.0f / mAudioTrack->getSampleRate();
-
- int64_t delayUs =
- msecsPerFrame * numFramesPendingPlayout * 1000ll;
-
- // Let's give it more data after about half that time
- // has elapsed.
- (new AMessage(kWhatPushAudio, id()))->post(delayUs / 2);
-}
-
-void DirectRenderer::AudioRenderer::onPushAudio() {
- mPushPending = false;
-
- while (!mInputBuffers.empty()) {
- const BufferInfo &info = *mInputBuffers.begin();
-
- ssize_t n = writeNonBlocking(
- info.mBuffer->data(), info.mBuffer->size());
-
- if (n < (ssize_t)info.mBuffer->size()) {
- CHECK_GE(n, 0);
-
- info.mBuffer->setRange(
- info.mBuffer->offset() + n, info.mBuffer->size() - n);
- break;
- }
-
- mDecoderContext->releaseOutputBuffer(info.mIndex);
-
- mInputBuffers.erase(mInputBuffers.begin());
- }
-
- schedulePushIfNecessary();
-}
-
-ssize_t DirectRenderer::AudioRenderer::writeNonBlocking(
- const uint8_t *data, size_t size) {
- uint32_t numFramesPlayed;
- status_t err = mAudioTrack->getPosition(&numFramesPlayed);
- if (err != OK) {
- return err;
- }
-
- ssize_t numFramesAvailableToWrite =
- mAudioTrack->frameCount() - (mNumFramesWritten - numFramesPlayed);
-
- size_t numBytesAvailableToWrite =
- numFramesAvailableToWrite * mAudioTrack->frameSize();
-
- if (size > numBytesAvailableToWrite) {
- size = numBytesAvailableToWrite;
- }
-
- CHECK_EQ(mAudioTrack->write(data, size), (ssize_t)size);
-
- size_t numFramesWritten = size / mAudioTrack->frameSize();
- mNumFramesWritten += numFramesWritten;
-
- return size;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-DirectRenderer::DirectRenderer(
- const sp<IGraphicBufferProducer> &bufferProducer)
- : mSurfaceTex(bufferProducer),
- mVideoRenderPending(false),
- mNumFramesLate(0),
- mNumFrames(0) {
-}
-
-DirectRenderer::~DirectRenderer() {
-}
-
-void DirectRenderer::onMessageReceived(const sp<AMessage> &msg) {
- switch (msg->what()) {
- case kWhatDecoderNotify:
- {
- onDecoderNotify(msg);
- break;
- }
-
- case kWhatRenderVideo:
- {
- onRenderVideo();
- break;
- }
-
- default:
- TRESPASS();
- }
-}
-
-void DirectRenderer::setFormat(size_t trackIndex, const sp<AMessage> &format) {
- CHECK_LT(trackIndex, 2u);
-
- CHECK(mDecoderContext[trackIndex] == NULL);
-
- sp<AMessage> notify = new AMessage(kWhatDecoderNotify, id());
- notify->setSize("trackIndex", trackIndex);
-
- mDecoderContext[trackIndex] = new DecoderContext(notify);
- looper()->registerHandler(mDecoderContext[trackIndex]);
-
- CHECK_EQ((status_t)OK,
- mDecoderContext[trackIndex]->init(
- format, trackIndex == 0 ? mSurfaceTex : NULL));
-
- if (trackIndex == 1) {
- // Audio
- mAudioRenderer = new AudioRenderer(mDecoderContext[1]);
- looper()->registerHandler(mAudioRenderer);
- }
-}
-
-void DirectRenderer::queueAccessUnit(
- size_t trackIndex, const sp<ABuffer> &accessUnit) {
- CHECK_LT(trackIndex, 2u);
-
- if (mDecoderContext[trackIndex] == NULL) {
- CHECK_EQ(trackIndex, 0u);
-
- sp<AMessage> format = new AMessage;
- format->setString("mime", "video/avc");
- format->setInt32("width", 640);
- format->setInt32("height", 360);
-
- setFormat(trackIndex, format);
- }
-
- mDecoderContext[trackIndex]->queueInputBuffer(accessUnit);
-}
-
-void DirectRenderer::onDecoderNotify(const sp<AMessage> &msg) {
- size_t trackIndex;
- CHECK(msg->findSize("trackIndex", &trackIndex));
-
- int32_t what;
- CHECK(msg->findInt32("what", &what));
-
- switch (what) {
- case DecoderContext::kWhatOutputBufferReady:
- {
- size_t index;
- CHECK(msg->findSize("index", &index));
-
- int64_t timeUs;
- CHECK(msg->findInt64("timeUs", &timeUs));
-
- sp<ABuffer> buffer;
- CHECK(msg->findBuffer("buffer", &buffer));
-
- queueOutputBuffer(trackIndex, index, timeUs, buffer);
- break;
- }
-
- default:
- TRESPASS();
- }
-}
-
-void DirectRenderer::queueOutputBuffer(
- size_t trackIndex,
- size_t index, int64_t timeUs, const sp<ABuffer> &buffer) {
- if (trackIndex == 1) {
- // Audio
- mAudioRenderer->queueInputBuffer(index, timeUs, buffer);
- return;
- }
-
- OutputInfo info;
- info.mIndex = index;
- info.mTimeUs = timeUs;
- info.mBuffer = buffer;
- mVideoOutputBuffers.push_back(info);
-
- scheduleVideoRenderIfNecessary();
-}
-
-void DirectRenderer::scheduleVideoRenderIfNecessary() {
- if (mVideoRenderPending || mVideoOutputBuffers.empty()) {
- return;
- }
-
- mVideoRenderPending = true;
-
- int64_t timeUs = (*mVideoOutputBuffers.begin()).mTimeUs;
- int64_t nowUs = ALooper::GetNowUs();
-
- int64_t delayUs = timeUs - nowUs;
-
- (new AMessage(kWhatRenderVideo, id()))->post(delayUs);
-}
-
-void DirectRenderer::onRenderVideo() {
- mVideoRenderPending = false;
-
- int64_t nowUs = ALooper::GetNowUs();
-
- while (!mVideoOutputBuffers.empty()) {
- const OutputInfo &info = *mVideoOutputBuffers.begin();
-
- if (info.mTimeUs > nowUs) {
- break;
- }
-
- if (info.mTimeUs + 15000ll < nowUs) {
- ++mNumFramesLate;
- }
- ++mNumFrames;
-
- status_t err =
- mDecoderContext[0]->renderOutputBufferAndRelease(info.mIndex);
- CHECK_EQ(err, (status_t)OK);
-
- mVideoOutputBuffers.erase(mVideoOutputBuffers.begin());
- }
-
- scheduleVideoRenderIfNecessary();
-}
-
-} // namespace android
-
diff --git a/media/libstagefright/wifi-display/sink/DirectRenderer.h b/media/libstagefright/wifi-display/sink/DirectRenderer.h
deleted file mode 100644
index c5a4a83..0000000
--- a/media/libstagefright/wifi-display/sink/DirectRenderer.h
+++ /dev/null
@@ -1,82 +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 DIRECT_RENDERER_H_
-
-#define DIRECT_RENDERER_H_
-
-#include <media/stagefright/foundation/AHandler.h>
-
-namespace android {
-
-struct ABuffer;
-struct AudioTrack;
-struct IGraphicBufferProducer;
-struct MediaCodec;
-
-// Renders audio and video data queued by calls to "queueAccessUnit".
-struct DirectRenderer : public AHandler {
- DirectRenderer(const sp<IGraphicBufferProducer> &bufferProducer);
-
- void setFormat(size_t trackIndex, const sp<AMessage> &format);
- void queueAccessUnit(size_t trackIndex, const sp<ABuffer> &accessUnit);
-
-protected:
- virtual void onMessageReceived(const sp<AMessage> &msg);
- virtual ~DirectRenderer();
-
-private:
- struct DecoderContext;
- struct AudioRenderer;
-
- enum {
- kWhatDecoderNotify,
- kWhatRenderVideo,
- };
-
- struct OutputInfo {
- size_t mIndex;
- int64_t mTimeUs;
- sp<ABuffer> mBuffer;
- };
-
- sp<IGraphicBufferProducer> mSurfaceTex;
-
- sp<DecoderContext> mDecoderContext[2];
- List<OutputInfo> mVideoOutputBuffers;
-
- bool mVideoRenderPending;
-
- sp<AudioRenderer> mAudioRenderer;
-
- int32_t mNumFramesLate;
- int32_t mNumFrames;
-
- void onDecoderNotify(const sp<AMessage> &msg);
-
- void queueOutputBuffer(
- size_t trackIndex,
- size_t index, int64_t timeUs, const sp<ABuffer> &buffer);
-
- void scheduleVideoRenderIfNecessary();
- void onRenderVideo();
-
- DISALLOW_EVIL_CONSTRUCTORS(DirectRenderer);
-};
-
-} // namespace android
-
-#endif // DIRECT_RENDERER_H_
diff --git a/media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp b/media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp
deleted file mode 100644
index 5db2099..0000000
--- a/media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp
+++ /dev/null
@@ -1,917 +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 "WifiDisplaySink"
-#include <utils/Log.h>
-
-#include "WifiDisplaySink.h"
-
-#include "DirectRenderer.h"
-#include "MediaReceiver.h"
-#include "ParsedMessage.h"
-#include "TimeSyncer.h"
-
-#include <cutils/properties.h>
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/Utils.h>
-
-namespace android {
-
-// static
-const AString WifiDisplaySink::sUserAgent = MakeUserAgent();
-
-WifiDisplaySink::WifiDisplaySink(
- uint32_t flags,
- const sp<ANetworkSession> &netSession,
- const sp<IGraphicBufferProducer> &bufferProducer,
- const sp<AMessage> ¬ify)
- : mState(UNDEFINED),
- mFlags(flags),
- mNetSession(netSession),
- mSurfaceTex(bufferProducer),
- mNotify(notify),
- mUsingTCPTransport(false),
- mUsingTCPInterleaving(false),
- mSessionID(0),
- mNextCSeq(1),
- mIDRFrameRequestPending(false),
- mTimeOffsetUs(0ll),
- mTimeOffsetValid(false),
- mSetupDeferred(false),
- mLatencyCount(0),
- mLatencySumUs(0ll),
- mLatencyMaxUs(0ll),
- mMaxDelayMs(-1ll) {
- // We support any and all resolutions, but prefer 720p30
- mSinkSupportedVideoFormats.setNativeResolution(
- VideoFormats::RESOLUTION_CEA, 5); // 1280 x 720 p30
-
- mSinkSupportedVideoFormats.enableAll();
-}
-
-WifiDisplaySink::~WifiDisplaySink() {
-}
-
-void WifiDisplaySink::start(const char *sourceHost, int32_t sourcePort) {
- sp<AMessage> msg = new AMessage(kWhatStart, id());
- msg->setString("sourceHost", sourceHost);
- msg->setInt32("sourcePort", sourcePort);
- msg->post();
-}
-
-void WifiDisplaySink::start(const char *uri) {
- sp<AMessage> msg = new AMessage(kWhatStart, id());
- msg->setString("setupURI", uri);
- msg->post();
-}
-
-// static
-bool WifiDisplaySink::ParseURL(
- const char *url, AString *host, int32_t *port, AString *path,
- AString *user, AString *pass) {
- host->clear();
- *port = 0;
- path->clear();
- user->clear();
- pass->clear();
-
- if (strncasecmp("rtsp://", url, 7)) {
- return false;
- }
-
- const char *slashPos = strchr(&url[7], '/');
-
- if (slashPos == NULL) {
- host->setTo(&url[7]);
- path->setTo("/");
- } else {
- host->setTo(&url[7], slashPos - &url[7]);
- path->setTo(slashPos);
- }
-
- ssize_t atPos = host->find("@");
-
- if (atPos >= 0) {
- // Split of user:pass@ from hostname.
-
- AString userPass(*host, 0, atPos);
- host->erase(0, atPos + 1);
-
- ssize_t colonPos = userPass.find(":");
-
- if (colonPos < 0) {
- *user = userPass;
- } else {
- user->setTo(userPass, 0, colonPos);
- pass->setTo(userPass, colonPos + 1, userPass.size() - colonPos - 1);
- }
- }
-
- const char *colonPos = strchr(host->c_str(), ':');
-
- if (colonPos != NULL) {
- char *end;
- unsigned long x = strtoul(colonPos + 1, &end, 10);
-
- if (end == colonPos + 1 || *end != '\0' || x >= 65536) {
- return false;
- }
-
- *port = x;
-
- size_t colonOffset = colonPos - host->c_str();
- size_t trailing = host->size() - colonOffset;
- host->erase(colonOffset, trailing);
- } else {
- *port = 554;
- }
-
- return true;
-}
-
-void WifiDisplaySink::onMessageReceived(const sp<AMessage> &msg) {
- switch (msg->what()) {
- case kWhatStart:
- {
- sleep(2); // XXX
-
- int32_t sourcePort;
- CHECK(msg->findString("sourceHost", &mRTSPHost));
- CHECK(msg->findInt32("sourcePort", &sourcePort));
-
- sp<AMessage> notify = new AMessage(kWhatRTSPNotify, id());
-
- status_t err = mNetSession->createRTSPClient(
- mRTSPHost.c_str(), sourcePort, notify, &mSessionID);
- CHECK_EQ(err, (status_t)OK);
-
- mState = CONNECTING;
- break;
- }
-
- case kWhatRTSPNotify:
- {
- int32_t reason;
- CHECK(msg->findInt32("reason", &reason));
-
- switch (reason) {
- case ANetworkSession::kWhatError:
- {
- int32_t sessionID;
- CHECK(msg->findInt32("sessionID", &sessionID));
-
- int32_t err;
- CHECK(msg->findInt32("err", &err));
-
- AString detail;
- CHECK(msg->findString("detail", &detail));
-
- ALOGE("An error occurred in session %d (%d, '%s/%s').",
- sessionID,
- err,
- detail.c_str(),
- strerror(-err));
-
- if (sessionID == mSessionID) {
- ALOGI("Lost control connection.");
-
- // The control connection is dead now.
- mNetSession->destroySession(mSessionID);
- mSessionID = 0;
-
- if (mNotify == NULL) {
- looper()->stop();
- } else {
- sp<AMessage> notify = mNotify->dup();
- notify->setInt32("what", kWhatDisconnected);
- notify->post();
- }
- }
- break;
- }
-
- case ANetworkSession::kWhatConnected:
- {
- ALOGI("We're now connected.");
- mState = CONNECTED;
-
- if (mFlags & FLAG_SPECIAL_MODE) {
- sp<AMessage> notify = new AMessage(
- kWhatTimeSyncerNotify, id());
-
- mTimeSyncer = new TimeSyncer(mNetSession, notify);
- looper()->registerHandler(mTimeSyncer);
-
- mTimeSyncer->startClient(mRTSPHost.c_str(), 8123);
- }
- break;
- }
-
- case ANetworkSession::kWhatData:
- {
- onReceiveClientData(msg);
- break;
- }
-
- default:
- TRESPASS();
- }
- break;
- }
-
- case kWhatStop:
- {
- looper()->stop();
- break;
- }
-
- case kWhatMediaReceiverNotify:
- {
- onMediaReceiverNotify(msg);
- break;
- }
-
- case kWhatTimeSyncerNotify:
- {
- int32_t what;
- CHECK(msg->findInt32("what", &what));
-
- if (what == TimeSyncer::kWhatTimeOffset) {
- CHECK(msg->findInt64("offset", &mTimeOffsetUs));
- mTimeOffsetValid = true;
-
- if (mSetupDeferred) {
- CHECK_EQ((status_t)OK,
- sendSetup(
- mSessionID,
- "rtsp://x.x.x.x:x/wfd1.0/streamid=0"));
-
- mSetupDeferred = false;
- }
- }
- break;
- }
-
- case kWhatReportLateness:
- {
- if (mLatencyCount > 0) {
- int64_t avgLatencyUs = mLatencySumUs / mLatencyCount;
-
- ALOGV("avg. latency = %lld ms (max %lld ms)",
- avgLatencyUs / 1000ll,
- mLatencyMaxUs / 1000ll);
-
- sp<AMessage> params = new AMessage;
- params->setInt64("avgLatencyUs", avgLatencyUs);
- params->setInt64("maxLatencyUs", mLatencyMaxUs);
- mMediaReceiver->informSender(0 /* trackIndex */, params);
- }
-
- mLatencyCount = 0;
- mLatencySumUs = 0ll;
- mLatencyMaxUs = 0ll;
-
- msg->post(kReportLatenessEveryUs);
- break;
- }
-
- default:
- TRESPASS();
- }
-}
-
-void WifiDisplaySink::dumpDelay(size_t trackIndex, int64_t timeUs) {
- int64_t delayMs = (ALooper::GetNowUs() - timeUs) / 1000ll;
-
- if (delayMs > mMaxDelayMs) {
- mMaxDelayMs = delayMs;
- }
-
- static const int64_t kMinDelayMs = 0;
- static const int64_t kMaxDelayMs = 300;
-
- const char *kPattern = "########################################";
- size_t kPatternSize = strlen(kPattern);
-
- int n = (kPatternSize * (delayMs - kMinDelayMs))
- / (kMaxDelayMs - kMinDelayMs);
-
- if (n < 0) {
- n = 0;
- } else if ((size_t)n > kPatternSize) {
- n = kPatternSize;
- }
-
- ALOGI("[%lld]: (%4lld ms / %4lld ms) %s",
- timeUs / 1000,
- delayMs,
- mMaxDelayMs,
- kPattern + kPatternSize - n);
-}
-
-void WifiDisplaySink::onMediaReceiverNotify(const sp<AMessage> &msg) {
- int32_t what;
- CHECK(msg->findInt32("what", &what));
-
- switch (what) {
- case MediaReceiver::kWhatInitDone:
- {
- status_t err;
- CHECK(msg->findInt32("err", &err));
-
- ALOGI("MediaReceiver initialization completed w/ err %d", err);
- break;
- }
-
- case MediaReceiver::kWhatError:
- {
- status_t err;
- CHECK(msg->findInt32("err", &err));
-
- ALOGE("MediaReceiver signaled error %d", err);
- break;
- }
-
- case MediaReceiver::kWhatAccessUnit:
- {
- if (mRenderer == NULL) {
- mRenderer = new DirectRenderer(mSurfaceTex);
- looper()->registerHandler(mRenderer);
- }
-
- sp<ABuffer> accessUnit;
- CHECK(msg->findBuffer("accessUnit", &accessUnit));
-
- int64_t timeUs;
- CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
-
- if (!mTimeOffsetValid && !(mFlags & FLAG_SPECIAL_MODE)) {
- mTimeOffsetUs = timeUs - ALooper::GetNowUs();
- mTimeOffsetValid = true;
- }
-
- CHECK(mTimeOffsetValid);
-
- // We are the timesync _client_,
- // client time = server time - time offset.
- timeUs -= mTimeOffsetUs;
-
- size_t trackIndex;
- CHECK(msg->findSize("trackIndex", &trackIndex));
-
- int64_t nowUs = ALooper::GetNowUs();
- int64_t delayUs = nowUs - timeUs;
-
- mLatencySumUs += delayUs;
- if (mLatencyCount == 0 || delayUs > mLatencyMaxUs) {
- mLatencyMaxUs = delayUs;
- }
- ++mLatencyCount;
-
- // dumpDelay(trackIndex, timeUs);
-
- timeUs += 220000ll; // Assume 220 ms of latency
- accessUnit->meta()->setInt64("timeUs", timeUs);
-
- sp<AMessage> format;
- if (msg->findMessage("format", &format)) {
- mRenderer->setFormat(trackIndex, format);
- }
-
- mRenderer->queueAccessUnit(trackIndex, accessUnit);
- break;
- }
-
- case MediaReceiver::kWhatPacketLost:
- {
-#if 0
- if (!mIDRFrameRequestPending) {
- ALOGI("requesting IDR frame");
-
- sendIDRFrameRequest(mSessionID);
- }
-#endif
- break;
- }
-
- default:
- TRESPASS();
- }
-}
-
-void WifiDisplaySink::registerResponseHandler(
- int32_t sessionID, int32_t cseq, HandleRTSPResponseFunc func) {
- ResponseID id;
- id.mSessionID = sessionID;
- id.mCSeq = cseq;
- mResponseHandlers.add(id, func);
-}
-
-status_t WifiDisplaySink::sendM2(int32_t sessionID) {
- AString request = "OPTIONS * RTSP/1.0\r\n";
- AppendCommonResponse(&request, mNextCSeq);
-
- request.append(
- "Require: org.wfa.wfd1.0\r\n"
- "\r\n");
-
- status_t err =
- mNetSession->sendRequest(sessionID, request.c_str(), request.size());
-
- if (err != OK) {
- return err;
- }
-
- registerResponseHandler(
- sessionID, mNextCSeq, &WifiDisplaySink::onReceiveM2Response);
-
- ++mNextCSeq;
-
- return OK;
-}
-
-status_t WifiDisplaySink::onReceiveM2Response(
- int32_t sessionID, const sp<ParsedMessage> &msg) {
- int32_t statusCode;
- if (!msg->getStatusCode(&statusCode)) {
- return ERROR_MALFORMED;
- }
-
- if (statusCode != 200) {
- return ERROR_UNSUPPORTED;
- }
-
- return OK;
-}
-
-status_t WifiDisplaySink::onReceiveSetupResponse(
- int32_t sessionID, const sp<ParsedMessage> &msg) {
- int32_t statusCode;
- if (!msg->getStatusCode(&statusCode)) {
- return ERROR_MALFORMED;
- }
-
- if (statusCode != 200) {
- return ERROR_UNSUPPORTED;
- }
-
- if (!msg->findString("session", &mPlaybackSessionID)) {
- return ERROR_MALFORMED;
- }
-
- if (!ParsedMessage::GetInt32Attribute(
- mPlaybackSessionID.c_str(),
- "timeout",
- &mPlaybackSessionTimeoutSecs)) {
- mPlaybackSessionTimeoutSecs = -1;
- }
-
- ssize_t colonPos = mPlaybackSessionID.find(";");
- if (colonPos >= 0) {
- // Strip any options from the returned session id.
- mPlaybackSessionID.erase(
- colonPos, mPlaybackSessionID.size() - colonPos);
- }
-
- status_t err = configureTransport(msg);
-
- if (err != OK) {
- return err;
- }
-
- mState = PAUSED;
-
- return sendPlay(
- sessionID,
- "rtsp://x.x.x.x:x/wfd1.0/streamid=0");
-}
-
-status_t WifiDisplaySink::configureTransport(const sp<ParsedMessage> &msg) {
- if (mUsingTCPTransport && !(mFlags & FLAG_SPECIAL_MODE)) {
- // In "special" mode we still use a UDP RTCP back-channel that
- // needs connecting.
- return OK;
- }
-
- AString transport;
- if (!msg->findString("transport", &transport)) {
- ALOGE("Missing 'transport' field in SETUP response.");
- return ERROR_MALFORMED;
- }
-
- AString sourceHost;
- if (!ParsedMessage::GetAttribute(
- transport.c_str(), "source", &sourceHost)) {
- sourceHost = mRTSPHost;
- }
-
- AString serverPortStr;
- if (!ParsedMessage::GetAttribute(
- transport.c_str(), "server_port", &serverPortStr)) {
- ALOGE("Missing 'server_port' in Transport field.");
- return ERROR_MALFORMED;
- }
-
- int rtpPort, rtcpPort;
- if (sscanf(serverPortStr.c_str(), "%d-%d", &rtpPort, &rtcpPort) != 2
- || rtpPort <= 0 || rtpPort > 65535
- || rtcpPort <=0 || rtcpPort > 65535
- || rtcpPort != rtpPort + 1) {
- ALOGE("Invalid server_port description '%s'.",
- serverPortStr.c_str());
-
- return ERROR_MALFORMED;
- }
-
- if (rtpPort & 1) {
- ALOGW("Server picked an odd numbered RTP port.");
- }
-
- return mMediaReceiver->connectTrack(
- 0 /* trackIndex */, sourceHost.c_str(), rtpPort, rtcpPort);
-}
-
-status_t WifiDisplaySink::onReceivePlayResponse(
- int32_t sessionID, const sp<ParsedMessage> &msg) {
- int32_t statusCode;
- if (!msg->getStatusCode(&statusCode)) {
- return ERROR_MALFORMED;
- }
-
- if (statusCode != 200) {
- return ERROR_UNSUPPORTED;
- }
-
- mState = PLAYING;
-
- (new AMessage(kWhatReportLateness, id()))->post(kReportLatenessEveryUs);
-
- return OK;
-}
-
-status_t WifiDisplaySink::onReceiveIDRFrameRequestResponse(
- int32_t sessionID, const sp<ParsedMessage> &msg) {
- CHECK(mIDRFrameRequestPending);
- mIDRFrameRequestPending = false;
-
- return OK;
-}
-
-void WifiDisplaySink::onReceiveClientData(const sp<AMessage> &msg) {
- int32_t sessionID;
- CHECK(msg->findInt32("sessionID", &sessionID));
-
- sp<RefBase> obj;
- CHECK(msg->findObject("data", &obj));
-
- sp<ParsedMessage> data =
- static_cast<ParsedMessage *>(obj.get());
-
- ALOGV("session %d received '%s'",
- sessionID, data->debugString().c_str());
-
- AString method;
- AString uri;
- data->getRequestField(0, &method);
-
- int32_t cseq;
- if (!data->findInt32("cseq", &cseq)) {
- sendErrorResponse(sessionID, "400 Bad Request", -1 /* cseq */);
- return;
- }
-
- if (method.startsWith("RTSP/")) {
- // This is a response.
-
- ResponseID id;
- id.mSessionID = sessionID;
- id.mCSeq = cseq;
-
- ssize_t index = mResponseHandlers.indexOfKey(id);
-
- if (index < 0) {
- ALOGW("Received unsolicited server response, cseq %d", cseq);
- return;
- }
-
- HandleRTSPResponseFunc func = mResponseHandlers.valueAt(index);
- mResponseHandlers.removeItemsAt(index);
-
- status_t err = (this->*func)(sessionID, data);
- CHECK_EQ(err, (status_t)OK);
- } else {
- AString version;
- data->getRequestField(2, &version);
- if (!(version == AString("RTSP/1.0"))) {
- sendErrorResponse(sessionID, "505 RTSP Version not supported", cseq);
- return;
- }
-
- if (method == "OPTIONS") {
- onOptionsRequest(sessionID, cseq, data);
- } else if (method == "GET_PARAMETER") {
- onGetParameterRequest(sessionID, cseq, data);
- } else if (method == "SET_PARAMETER") {
- onSetParameterRequest(sessionID, cseq, data);
- } else {
- sendErrorResponse(sessionID, "405 Method Not Allowed", cseq);
- }
- }
-}
-
-void WifiDisplaySink::onOptionsRequest(
- int32_t sessionID,
- int32_t cseq,
- const sp<ParsedMessage> &data) {
- AString response = "RTSP/1.0 200 OK\r\n";
- AppendCommonResponse(&response, cseq);
- response.append("Public: org.wfa.wfd1.0, GET_PARAMETER, SET_PARAMETER\r\n");
- response.append("\r\n");
-
- status_t err = mNetSession->sendRequest(sessionID, response.c_str());
- CHECK_EQ(err, (status_t)OK);
-
- err = sendM2(sessionID);
- CHECK_EQ(err, (status_t)OK);
-}
-
-void WifiDisplaySink::onGetParameterRequest(
- int32_t sessionID,
- int32_t cseq,
- const sp<ParsedMessage> &data) {
- AString body;
-
- if (mState == CONNECTED) {
- mUsingTCPTransport = false;
- mUsingTCPInterleaving = false;
-
- char val[PROPERTY_VALUE_MAX];
- if (property_get("media.wfd-sink.tcp-mode", val, NULL)) {
- if (!strcasecmp("true", val) || !strcmp("1", val)) {
- ALOGI("Using TCP unicast transport.");
- mUsingTCPTransport = true;
- mUsingTCPInterleaving = false;
- } else if (!strcasecmp("interleaved", val)) {
- ALOGI("Using TCP interleaved transport.");
- mUsingTCPTransport = true;
- mUsingTCPInterleaving = true;
- }
- } else if (mFlags & FLAG_SPECIAL_MODE) {
- mUsingTCPTransport = true;
- }
-
- body = "wfd_video_formats: ";
- body.append(mSinkSupportedVideoFormats.getFormatSpec());
-
- body.append(
- "\r\nwfd_audio_codecs: AAC 0000000F 00\r\n"
- "wfd_client_rtp_ports: RTP/AVP/");
-
- if (mUsingTCPTransport) {
- body.append("TCP;");
- if (mUsingTCPInterleaving) {
- body.append("interleaved");
- } else {
- body.append("unicast 19000 0");
- }
- } else {
- body.append("UDP;unicast 19000 0");
- }
-
- body.append(" mode=play\r\n");
- }
-
- AString response = "RTSP/1.0 200 OK\r\n";
- AppendCommonResponse(&response, cseq);
- response.append("Content-Type: text/parameters\r\n");
- response.append(StringPrintf("Content-Length: %d\r\n", body.size()));
- response.append("\r\n");
- response.append(body);
-
- status_t err = mNetSession->sendRequest(sessionID, response.c_str());
- CHECK_EQ(err, (status_t)OK);
-}
-
-status_t WifiDisplaySink::sendSetup(int32_t sessionID, const char *uri) {
- sp<AMessage> notify = new AMessage(kWhatMediaReceiverNotify, id());
-
- mMediaReceiverLooper = new ALooper;
- mMediaReceiverLooper->setName("media_receiver");
-
- mMediaReceiverLooper->start(
- false /* runOnCallingThread */,
- false /* canCallJava */,
- PRIORITY_AUDIO);
-
- mMediaReceiver = new MediaReceiver(mNetSession, notify);
- mMediaReceiverLooper->registerHandler(mMediaReceiver);
-
- RTPReceiver::TransportMode rtpMode = RTPReceiver::TRANSPORT_UDP;
- if (mUsingTCPTransport) {
- if (mUsingTCPInterleaving) {
- rtpMode = RTPReceiver::TRANSPORT_TCP_INTERLEAVED;
- } else {
- rtpMode = RTPReceiver::TRANSPORT_TCP;
- }
- }
-
- int32_t localRTPPort;
- status_t err = mMediaReceiver->addTrack(
- rtpMode, RTPReceiver::TRANSPORT_UDP /* rtcpMode */, &localRTPPort);
-
- if (err == OK) {
- err = mMediaReceiver->initAsync(MediaReceiver::MODE_TRANSPORT_STREAM);
- }
-
- if (err != OK) {
- mMediaReceiverLooper->unregisterHandler(mMediaReceiver->id());
- mMediaReceiver.clear();
-
- mMediaReceiverLooper->stop();
- mMediaReceiverLooper.clear();
-
- return err;
- }
-
- AString request = StringPrintf("SETUP %s RTSP/1.0\r\n", uri);
-
- AppendCommonResponse(&request, mNextCSeq);
-
- if (rtpMode == RTPReceiver::TRANSPORT_TCP_INTERLEAVED) {
- request.append("Transport: RTP/AVP/TCP;interleaved=0-1\r\n");
- } else if (rtpMode == RTPReceiver::TRANSPORT_TCP) {
- if (mFlags & FLAG_SPECIAL_MODE) {
- // This isn't quite true, since the RTP connection is through TCP
- // and the RTCP connection through UDP...
- request.append(
- StringPrintf(
- "Transport: RTP/AVP/TCP;unicast;client_port=%d-%d\r\n",
- localRTPPort, localRTPPort + 1));
- } else {
- request.append(
- StringPrintf(
- "Transport: RTP/AVP/TCP;unicast;client_port=%d\r\n",
- localRTPPort));
- }
- } else {
- request.append(
- StringPrintf(
- "Transport: RTP/AVP/UDP;unicast;client_port=%d-%d\r\n",
- localRTPPort,
- localRTPPort + 1));
- }
-
- request.append("\r\n");
-
- ALOGV("request = '%s'", request.c_str());
-
- err = mNetSession->sendRequest(sessionID, request.c_str(), request.size());
-
- if (err != OK) {
- return err;
- }
-
- registerResponseHandler(
- sessionID, mNextCSeq, &WifiDisplaySink::onReceiveSetupResponse);
-
- ++mNextCSeq;
-
- return OK;
-}
-
-status_t WifiDisplaySink::sendPlay(int32_t sessionID, const char *uri) {
- AString request = StringPrintf("PLAY %s RTSP/1.0\r\n", uri);
-
- AppendCommonResponse(&request, mNextCSeq);
-
- request.append(StringPrintf("Session: %s\r\n", mPlaybackSessionID.c_str()));
- request.append("\r\n");
-
- status_t err =
- mNetSession->sendRequest(sessionID, request.c_str(), request.size());
-
- if (err != OK) {
- return err;
- }
-
- registerResponseHandler(
- sessionID, mNextCSeq, &WifiDisplaySink::onReceivePlayResponse);
-
- ++mNextCSeq;
-
- return OK;
-}
-
-status_t WifiDisplaySink::sendIDRFrameRequest(int32_t sessionID) {
- CHECK(!mIDRFrameRequestPending);
-
- AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n";
-
- AppendCommonResponse(&request, mNextCSeq);
-
- AString content = "wfd_idr_request\r\n";
-
- request.append(StringPrintf("Session: %s\r\n", mPlaybackSessionID.c_str()));
- request.append(StringPrintf("Content-Length: %d\r\n", content.size()));
- request.append("\r\n");
- request.append(content);
-
- status_t err =
- mNetSession->sendRequest(sessionID, request.c_str(), request.size());
-
- if (err != OK) {
- return err;
- }
-
- registerResponseHandler(
- sessionID,
- mNextCSeq,
- &WifiDisplaySink::onReceiveIDRFrameRequestResponse);
-
- ++mNextCSeq;
-
- mIDRFrameRequestPending = true;
-
- return OK;
-}
-
-void WifiDisplaySink::onSetParameterRequest(
- int32_t sessionID,
- int32_t cseq,
- const sp<ParsedMessage> &data) {
- const char *content = data->getContent();
-
- if (strstr(content, "wfd_trigger_method: SETUP\r\n") != NULL) {
- if ((mFlags & FLAG_SPECIAL_MODE) && !mTimeOffsetValid) {
- mSetupDeferred = true;
- } else {
- status_t err =
- sendSetup(
- sessionID,
- "rtsp://x.x.x.x:x/wfd1.0/streamid=0");
-
- CHECK_EQ(err, (status_t)OK);
- }
- }
-
- AString response = "RTSP/1.0 200 OK\r\n";
- AppendCommonResponse(&response, cseq);
- response.append("\r\n");
-
- status_t err = mNetSession->sendRequest(sessionID, response.c_str());
- CHECK_EQ(err, (status_t)OK);
-}
-
-void WifiDisplaySink::sendErrorResponse(
- int32_t sessionID,
- const char *errorDetail,
- int32_t cseq) {
- AString response;
- response.append("RTSP/1.0 ");
- response.append(errorDetail);
- response.append("\r\n");
-
- AppendCommonResponse(&response, cseq);
-
- response.append("\r\n");
-
- status_t err = mNetSession->sendRequest(sessionID, response.c_str());
- CHECK_EQ(err, (status_t)OK);
-}
-
-// static
-void WifiDisplaySink::AppendCommonResponse(AString *response, int32_t cseq) {
- time_t now = time(NULL);
- struct tm *now2 = gmtime(&now);
- char buf[128];
- strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %z", now2);
-
- response->append("Date: ");
- response->append(buf);
- response->append("\r\n");
-
- response->append(StringPrintf("User-Agent: %s\r\n", sUserAgent.c_str()));
-
- if (cseq >= 0) {
- response->append(StringPrintf("CSeq: %d\r\n", cseq));
- }
-}
-
-} // namespace android
diff --git a/media/libstagefright/wifi-display/sink/WifiDisplaySink.h b/media/libstagefright/wifi-display/sink/WifiDisplaySink.h
deleted file mode 100644
index adb9d89..0000000
--- a/media/libstagefright/wifi-display/sink/WifiDisplaySink.h
+++ /dev/null
@@ -1,196 +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 WIFI_DISPLAY_SINK_H_
-
-#define WIFI_DISPLAY_SINK_H_
-
-#include "ANetworkSession.h"
-
-#include "VideoFormats.h"
-
-#include <gui/Surface.h>
-#include <media/stagefright/foundation/AHandler.h>
-
-namespace android {
-
-struct AMessage;
-struct DirectRenderer;
-struct MediaReceiver;
-struct ParsedMessage;
-struct TimeSyncer;
-
-// Represents the RTSP client acting as a wifi display sink.
-// Connects to a wifi display source and renders the incoming
-// transport stream using a MediaPlayer instance.
-struct WifiDisplaySink : public AHandler {
- enum {
- kWhatDisconnected,
- };
-
- enum Flags {
- FLAG_SPECIAL_MODE = 1,
- };
-
- // If no notification message is specified (notify == NULL)
- // the sink will stop its looper() once the session ends,
- // otherwise it will post an appropriate notification but leave
- // the looper() running.
- WifiDisplaySink(
- uint32_t flags,
- const sp<ANetworkSession> &netSession,
- const sp<IGraphicBufferProducer> &bufferProducer = NULL,
- const sp<AMessage> ¬ify = NULL);
-
- void start(const char *sourceHost, int32_t sourcePort);
- void start(const char *uri);
-
-protected:
- virtual ~WifiDisplaySink();
- virtual void onMessageReceived(const sp<AMessage> &msg);
-
-private:
- enum State {
- UNDEFINED,
- CONNECTING,
- CONNECTED,
- PAUSED,
- PLAYING,
- };
-
- enum {
- kWhatStart,
- kWhatRTSPNotify,
- kWhatStop,
- kWhatMediaReceiverNotify,
- kWhatTimeSyncerNotify,
- kWhatReportLateness,
- };
-
- struct ResponseID {
- int32_t mSessionID;
- int32_t mCSeq;
-
- bool operator<(const ResponseID &other) const {
- return mSessionID < other.mSessionID
- || (mSessionID == other.mSessionID
- && mCSeq < other.mCSeq);
- }
- };
-
- typedef status_t (WifiDisplaySink::*HandleRTSPResponseFunc)(
- int32_t sessionID, const sp<ParsedMessage> &msg);
-
- static const int64_t kReportLatenessEveryUs = 1000000ll;
-
- static const AString sUserAgent;
-
- State mState;
- uint32_t mFlags;
- VideoFormats mSinkSupportedVideoFormats;
- sp<ANetworkSession> mNetSession;
- sp<IGraphicBufferProducer> mSurfaceTex;
- sp<AMessage> mNotify;
- sp<TimeSyncer> mTimeSyncer;
- bool mUsingTCPTransport;
- bool mUsingTCPInterleaving;
- AString mRTSPHost;
- int32_t mSessionID;
-
- int32_t mNextCSeq;
-
- KeyedVector<ResponseID, HandleRTSPResponseFunc> mResponseHandlers;
-
- sp<ALooper> mMediaReceiverLooper;
- sp<MediaReceiver> mMediaReceiver;
- sp<DirectRenderer> mRenderer;
-
- AString mPlaybackSessionID;
- int32_t mPlaybackSessionTimeoutSecs;
-
- bool mIDRFrameRequestPending;
-
- int64_t mTimeOffsetUs;
- bool mTimeOffsetValid;
-
- bool mSetupDeferred;
-
- size_t mLatencyCount;
- int64_t mLatencySumUs;
- int64_t mLatencyMaxUs;
-
- int64_t mMaxDelayMs;
-
- status_t sendM2(int32_t sessionID);
- status_t sendSetup(int32_t sessionID, const char *uri);
- status_t sendPlay(int32_t sessionID, const char *uri);
- status_t sendIDRFrameRequest(int32_t sessionID);
-
- status_t onReceiveM2Response(
- int32_t sessionID, const sp<ParsedMessage> &msg);
-
- status_t onReceiveSetupResponse(
- int32_t sessionID, const sp<ParsedMessage> &msg);
-
- status_t configureTransport(const sp<ParsedMessage> &msg);
-
- status_t onReceivePlayResponse(
- int32_t sessionID, const sp<ParsedMessage> &msg);
-
- status_t onReceiveIDRFrameRequestResponse(
- int32_t sessionID, const sp<ParsedMessage> &msg);
-
- void registerResponseHandler(
- int32_t sessionID, int32_t cseq, HandleRTSPResponseFunc func);
-
- void onReceiveClientData(const sp<AMessage> &msg);
-
- void onOptionsRequest(
- int32_t sessionID,
- int32_t cseq,
- const sp<ParsedMessage> &data);
-
- void onGetParameterRequest(
- int32_t sessionID,
- int32_t cseq,
- const sp<ParsedMessage> &data);
-
- void onSetParameterRequest(
- int32_t sessionID,
- int32_t cseq,
- const sp<ParsedMessage> &data);
-
- void onMediaReceiverNotify(const sp<AMessage> &msg);
-
- void sendErrorResponse(
- int32_t sessionID,
- const char *errorDetail,
- int32_t cseq);
-
- static void AppendCommonResponse(AString *response, int32_t cseq);
-
- bool ParseURL(
- const char *url, AString *host, int32_t *port, AString *path,
- AString *user, AString *pass);
-
- void dumpDelay(size_t trackIndex, int64_t timeUs);
-
- DISALLOW_EVIL_CONSTRUCTORS(WifiDisplaySink);
-};
-
-} // namespace android
-
-#endif // WIFI_DISPLAY_SINK_H_
diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.cpp b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
index cacfcca..3d7b865 100644
--- a/media/libstagefright/wifi-display/source/PlaybackSession.cpp
+++ b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
@@ -559,8 +559,6 @@
converter->dropAFrame();
}
}
- } else if (what == MediaSender::kWhatInformSender) {
- onSinkFeedback(msg);
} else {
TRESPASS();
}
@@ -656,89 +654,6 @@
}
}
-void WifiDisplaySource::PlaybackSession::onSinkFeedback(const sp<AMessage> &msg) {
- int64_t avgLatencyUs;
- CHECK(msg->findInt64("avgLatencyUs", &avgLatencyUs));
-
- int64_t maxLatencyUs;
- CHECK(msg->findInt64("maxLatencyUs", &maxLatencyUs));
-
- ALOGI("sink reports avg. latency of %lld ms (max %lld ms)",
- avgLatencyUs / 1000ll,
- maxLatencyUs / 1000ll);
-
- if (mVideoTrackIndex >= 0) {
- const sp<Track> &videoTrack = mTracks.valueFor(mVideoTrackIndex);
- sp<Converter> converter = videoTrack->converter();
-
- if (converter != NULL) {
- int32_t videoBitrate =
- Converter::GetInt32Property("media.wfd.video-bitrate", -1);
-
- char val[PROPERTY_VALUE_MAX];
- if (videoBitrate < 0
- && property_get("media.wfd.video-bitrate", val, NULL)
- && !strcasecmp("adaptive", val)) {
- videoBitrate = converter->getVideoBitrate();
-
- if (avgLatencyUs > 300000ll) {
- videoBitrate *= 0.6;
- } else if (avgLatencyUs < 100000ll) {
- videoBitrate *= 1.1;
- }
- }
-
- if (videoBitrate > 0) {
- if (videoBitrate < 500000) {
- videoBitrate = 500000;
- } else if (videoBitrate > 10000000) {
- videoBitrate = 10000000;
- }
-
- if (videoBitrate != converter->getVideoBitrate()) {
- ALOGI("setting video bitrate to %d bps", videoBitrate);
-
- converter->setVideoBitrate(videoBitrate);
- }
- }
- }
-
- sp<RepeaterSource> repeaterSource = videoTrack->repeaterSource();
- if (repeaterSource != NULL) {
- double rateHz =
- Converter::GetInt32Property(
- "media.wfd.video-framerate", -1);
-
- char val[PROPERTY_VALUE_MAX];
- if (rateHz < 0.0
- && property_get("media.wfd.video-framerate", val, NULL)
- && !strcasecmp("adaptive", val)) {
- rateHz = repeaterSource->getFrameRate();
-
- if (avgLatencyUs > 300000ll) {
- rateHz *= 0.9;
- } else if (avgLatencyUs < 200000ll) {
- rateHz *= 1.1;
- }
- }
-
- if (rateHz > 0) {
- if (rateHz < 5.0) {
- rateHz = 5.0;
- } else if (rateHz > 30.0) {
- rateHz = 30.0;
- }
-
- if (rateHz != repeaterSource->getFrameRate()) {
- ALOGI("setting frame rate to %.2f Hz", rateHz);
-
- repeaterSource->setFrameRate(rateHz);
- }
- }
- }
- }
-}
-
status_t WifiDisplaySource::PlaybackSession::setupMediaPacketizer(
bool enableAudio, bool enableVideo) {
DataSource::RegisterDefaultSniffers();
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
index 4a49811..2b5bee9 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
@@ -23,7 +23,6 @@
#include "Parameters.h"
#include "ParsedMessage.h"
#include "rtp/RTPSender.h"
-#include "TimeSyncer.h"
#include <binder/IServiceManager.h>
#include <gui/IGraphicBufferProducer.h>
@@ -165,14 +164,6 @@
} else {
err = -EINVAL;
}
- }
-
- if (err == OK) {
- sp<AMessage> notify = new AMessage(kWhatTimeSyncerNotify, id());
- mTimeSyncer = new TimeSyncer(mNetSession, notify);
- looper()->registerHandler(mTimeSyncer);
-
- mTimeSyncer->startServer(8123);
mState = AWAITING_CLIENT_CONNECTION;
}
@@ -548,11 +539,6 @@
break;
}
- case kWhatTimeSyncerNotify:
- {
- break;
- }
-
default:
TRESPASS();
}
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.h b/media/libstagefright/wifi-display/source/WifiDisplaySource.h
index 3efa0b4..44d3e4d 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.h
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.h
@@ -30,7 +30,6 @@
struct IHDCP;
struct IRemoteDisplayClient;
struct ParsedMessage;
-struct TimeSyncer;
// Represents the RTSP server acting as a wifi display source.
// Manages incoming connections, sets up Playback sessions as necessary.
@@ -83,7 +82,6 @@
kWhatHDCPNotify,
kWhatFinishStop2,
kWhatTeardownTriggerTimedOut,
- kWhatTimeSyncerNotify,
};
struct ResponseID {
@@ -120,7 +118,6 @@
sp<ANetworkSession> mNetSession;
sp<IRemoteDisplayClient> mClient;
AString mMediaPath;
- sp<TimeSyncer> mTimeSyncer;
struct in_addr mInterfaceAddr;
int32_t mSessionID;
diff --git a/media/libstagefright/wifi-display/udptest.cpp b/media/libstagefright/wifi-display/udptest.cpp
deleted file mode 100644
index 111846d..0000000
--- a/media/libstagefright/wifi-display/udptest.cpp
+++ /dev/null
@@ -1,116 +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_NEBUG 0
-#define LOG_TAG "udptest"
-#include <utils/Log.h>
-
-#include "ANetworkSession.h"
-#include "TimeSyncer.h"
-
-#include <binder/ProcessState.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-namespace android {
-
-} // namespace android
-
-static void usage(const char *me) {
- fprintf(stderr,
- "usage: %s -c host[:port]\tconnect to test server\n"
- " -l \tcreate a test server\n",
- me);
-}
-
-int main(int argc, char **argv) {
- using namespace android;
-
- ProcessState::self()->startThreadPool();
-
- int32_t localPort = -1;
- int32_t connectToPort = -1;
- AString connectToHost;
-
- int res;
- while ((res = getopt(argc, argv, "hc:l:")) >= 0) {
- switch (res) {
- case 'c':
- {
- const char *colonPos = strrchr(optarg, ':');
-
- if (colonPos == NULL) {
- connectToHost = optarg;
- connectToPort = 49152;
- } else {
- connectToHost.setTo(optarg, colonPos - optarg);
-
- char *end;
- connectToPort = strtol(colonPos + 1, &end, 10);
-
- if (*end != '\0' || end == colonPos + 1
- || connectToPort < 1 || connectToPort > 65535) {
- fprintf(stderr, "Illegal port specified.\n");
- exit(1);
- }
- }
- break;
- }
-
- case 'l':
- {
- char *end;
- localPort = strtol(optarg, &end, 10);
-
- if (*end != '\0' || end == optarg
- || localPort < 1 || localPort > 65535) {
- fprintf(stderr, "Illegal port specified.\n");
- exit(1);
- }
- break;
- }
-
- case '?':
- case 'h':
- usage(argv[0]);
- exit(1);
- }
- }
-
- if (localPort < 0 && connectToPort < 0) {
- fprintf(stderr,
- "You need to select either client or server mode.\n");
- exit(1);
- }
-
- sp<ANetworkSession> netSession = new ANetworkSession;
- netSession->start();
-
- sp<ALooper> looper = new ALooper;
-
- sp<TimeSyncer> handler = new TimeSyncer(netSession, NULL /* notify */);
- looper->registerHandler(handler);
-
- if (localPort >= 0) {
- handler->startServer(localPort);
- } else {
- handler->startClient(connectToHost.c_str(), connectToPort);
- }
-
- looper->start(true /* runOnCallingThread */);
-
- return 0;
-}
-
diff --git a/media/libstagefright/wifi-display/wfd.cpp b/media/libstagefright/wifi-display/wfd.cpp
index 9fee4d0..c947765 100644
--- a/media/libstagefright/wifi-display/wfd.cpp
+++ b/media/libstagefright/wifi-display/wfd.cpp
@@ -18,7 +18,6 @@
#define LOG_TAG "wfd"
#include <utils/Log.h>
-#include "sink/WifiDisplaySink.h"
#include "source/WifiDisplaySource.h"
#include <binder/ProcessState.h>
@@ -39,12 +38,8 @@
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"
- " -l ip[:port] \tlisten on the specified port "
- " -f(ilename) \tstream media "
- "(create a sink)\n"
- " -s(pecial) \trun in 'special' mode\n",
+ " %s -l iface[:port]\tcreate a wifi display source\n"
+ " -f(ilename) \tstream media\n",
me);
}
@@ -214,48 +209,14 @@
DataSource::RegisterDefaultSniffers();
- AString connectToHost;
- int32_t connectToPort = -1;
- AString uri;
-
AString listenOnAddr;
int32_t listenOnPort = -1;
AString path;
- bool specialMode = false;
-
int res;
- while ((res = getopt(argc, argv, "hc:l:u:f:s")) >= 0) {
+ while ((res = getopt(argc, argv, "hl:f:")) >= 0) {
switch (res) {
- case 'c':
- {
- const char *colonPos = strrchr(optarg, ':');
-
- if (colonPos == NULL) {
- connectToHost = optarg;
- connectToPort = WifiDisplaySource::kWifiDisplayDefaultPort;
- } else {
- connectToHost.setTo(optarg, colonPos - optarg);
-
- char *end;
- connectToPort = strtol(colonPos + 1, &end, 10);
-
- if (*end != '\0' || end == colonPos + 1
- || connectToPort < 1 || connectToPort > 65535) {
- fprintf(stderr, "Illegal port specified.\n");
- exit(1);
- }
- }
- break;
- }
-
- case 'u':
- {
- uri = optarg;
- break;
- }
-
case 'f':
{
path = optarg;
@@ -284,12 +245,6 @@
break;
}
- case 's':
- {
- specialMode = true;
- break;
- }
-
case '?':
case 'h':
default:
@@ -298,13 +253,6 @@
}
}
- if (connectToPort >= 0 && listenOnPort >= 0) {
- fprintf(stderr,
- "You can connect to a source or create one, "
- "but not both at the same time.\n");
- exit(1);
- }
-
if (listenOnPort >= 0) {
if (path.empty()) {
createSource(listenOnAddr, listenOnPort);
@@ -315,72 +263,7 @@
exit(0);
}
- if (connectToPort < 0 && uri.empty()) {
- fprintf(stderr,
- "You need to select either source host or uri.\n");
-
- exit(1);
- }
-
- if (connectToPort >= 0 && !uri.empty()) {
- fprintf(stderr,
- "You need to either connect to a wfd host or an rtsp url, "
- "not both.\n");
- exit(1);
- }
-
- sp<SurfaceComposerClient> composerClient = new SurfaceComposerClient;
- CHECK_EQ(composerClient->initCheck(), (status_t)OK);
-
- sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(
- ISurfaceComposer::eDisplayIdMain));
- DisplayInfo info;
- SurfaceComposerClient::getDisplayInfo(display, &info);
- ssize_t displayWidth = info.w;
- ssize_t displayHeight = info.h;
-
- ALOGV("display is %d x %d\n", displayWidth, displayHeight);
-
- sp<SurfaceControl> control =
- composerClient->createSurface(
- String8("A Surface"),
- displayWidth,
- displayHeight,
- PIXEL_FORMAT_RGB_565,
- 0);
-
- CHECK(control != NULL);
- CHECK(control->isValid());
-
- SurfaceComposerClient::openGlobalTransaction();
- CHECK_EQ(control->setLayer(INT_MAX), (status_t)OK);
- CHECK_EQ(control->show(), (status_t)OK);
- SurfaceComposerClient::closeGlobalTransaction();
-
- sp<Surface> surface = control->getSurface();
- CHECK(surface != NULL);
-
- sp<ANetworkSession> session = new ANetworkSession;
- session->start();
-
- sp<ALooper> looper = new ALooper;
-
- sp<WifiDisplaySink> sink = new WifiDisplaySink(
- specialMode ? WifiDisplaySink::FLAG_SPECIAL_MODE : 0 /* flags */,
- session,
- surface->getIGraphicBufferProducer());
-
- looper->registerHandler(sink);
-
- if (connectToPort >= 0) {
- sink->start(connectToHost.c_str(), connectToPort);
- } else {
- sink->start(uri.c_str());
- }
-
- looper->start(true /* runOnCallingThread */);
-
- composerClient->dispose();
+ usage(argv[0]);
return 0;
}
diff --git a/media/libstagefright/yuv/Android.mk b/media/libstagefright/yuv/Android.mk
index a4253f6..b3f7b1b 100644
--- a/media/libstagefright/yuv/Android.mk
+++ b/media/libstagefright/yuv/Android.mk
@@ -6,7 +6,8 @@
YUVCanvas.cpp
LOCAL_SHARED_LIBRARIES := \
- libcutils
+ libcutils \
+ liblog
LOCAL_MODULE:= libstagefright_yuv
diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk
index a485646..1ac647a 100644
--- a/media/mediaserver/Android.mk
+++ b/media/mediaserver/Android.mk
@@ -22,6 +22,7 @@
libmedia \
libmediaplayerservice \
libutils \
+ liblog \
libbinder
LOCAL_STATIC_LIBRARIES := \
diff --git a/media/mtp/Android.mk b/media/mtp/Android.mk
index bee28d4..ac608a1 100644
--- a/media/mtp/Android.mk
+++ b/media/mtp/Android.mk
@@ -42,6 +42,6 @@
# Needed for <bionic_time.h>
LOCAL_C_INCLUDES := bionic/libc/private
-LOCAL_SHARED_LIBRARIES := libutils libcutils libusbhost libbinder
+LOCAL_SHARED_LIBRARIES := libutils libcutils liblog libusbhost libbinder
include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 7806f48..061a079 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -22,7 +22,7 @@
AudioResampler.cpp.arm \
AudioPolicyService.cpp \
ServiceUtilities.cpp \
- AudioResamplerCubic.cpp.arm \
+ AudioResamplerCubic.cpp.arm \
AudioResamplerSinc.cpp.arm
LOCAL_SRC_FILES += StateQueue.cpp
@@ -39,6 +39,7 @@
libcommon_time_client \
libcutils \
libutils \
+ liblog \
libbinder \
libmedia \
libnbaio \
@@ -94,9 +95,10 @@
AudioResamplerSinc.cpp.arm
LOCAL_SHARED_LIBRARIES := \
- libdl \
+ libdl \
libcutils \
- libutils
+ libutils \
+ liblog
LOCAL_MODULE:= test-resample
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index b3de526..87eb6aa 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -143,6 +143,7 @@
mMode(AUDIO_MODE_INVALID),
mBtNrecIsOff(false)
{
+ getpid_cached = getpid();
char value[PROPERTY_VALUE_MAX];
bool doLog = (property_get("ro.test_harness", value, "0") > 0) && (atoi(value) == 1);
if (doLog) {
diff --git a/services/audioflinger/ISchedulingPolicyService.cpp b/services/audioflinger/ISchedulingPolicyService.cpp
index 909b77e..218aa6b 100644
--- a/services/audioflinger/ISchedulingPolicyService.cpp
+++ b/services/audioflinger/ISchedulingPolicyService.cpp
@@ -44,7 +44,7 @@
data.writeInt32(pid);
data.writeInt32(tid);
data.writeInt32(prio);
- remote()->transact(REQUEST_PRIORITY_TRANSACTION, data, &reply);
+ remote()->transact(REQUEST_PRIORITY_TRANSACTION, data, &reply, IBinder::FLAG_ONEWAY);
// fail on exception
if (reply.readExceptionCode() != 0) return -1;
return reply.readInt32();
diff --git a/services/audioflinger/ServiceUtilities.cpp b/services/audioflinger/ServiceUtilities.cpp
index 6a58852..d15bd04 100644
--- a/services/audioflinger/ServiceUtilities.cpp
+++ b/services/audioflinger/ServiceUtilities.cpp
@@ -21,8 +21,9 @@
namespace android {
-// This optimization assumes mediaserver process doesn't fork, which it doesn't
-const pid_t getpid_cached = getpid();
+// Not valid until initialized by AudioFlinger constructor. It would have to be
+// re-initialized if the process containing AudioFlinger service forks (which it doesn't).
+pid_t getpid_cached;
bool recordingAllowed() {
if (getpid_cached == IPCThreadState::self()->getCallingPid()) return true;
diff --git a/services/audioflinger/ServiceUtilities.h b/services/audioflinger/ServiceUtilities.h
index f77ec5b..80cecba 100644
--- a/services/audioflinger/ServiceUtilities.h
+++ b/services/audioflinger/ServiceUtilities.h
@@ -18,7 +18,7 @@
namespace android {
-extern const pid_t getpid_cached;
+extern pid_t getpid_cached;
bool recordingAllowed();
bool settingsAllowed();
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index a6ab4f8..5ac3129 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -1415,6 +1415,9 @@
// since client and server are in the same process,
// the buffer has the same virtual address on both sides
mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize);
+ mClientProxy->setVolumeLR((uint32_t(uint16_t(0x1000)) << 16) | uint16_t(0x1000));
+ mClientProxy->setSendLevel(0.0);
+ mClientProxy->setSampleRate(sampleRate);
} else {
ALOGW("Error creating output track on thread %p", playbackThread);
}
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index 6847bf8..3c84703 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -32,6 +32,7 @@
LOCAL_SHARED_LIBRARIES:= \
libui \
+ liblog \
libutils \
libbinder \
libcutils \
diff --git a/services/camera/libcameraservice/Camera3Device.cpp b/services/camera/libcameraservice/Camera3Device.cpp
index e53dbb5..1433108 100644
--- a/services/camera/libcameraservice/Camera3Device.cpp
+++ b/services/camera/libcameraservice/Camera3Device.cpp
@@ -25,6 +25,18 @@
#define ALOGVV(...) ((void)0)
#endif
+// Convenience macro for transient errors
+#define CLOGE(fmt, ...) ALOGE("Camera %d: %s: " fmt, mId, __FUNCTION__, \
+ ##__VA_ARGS__)
+
+// Convenience macros for transitioning to the error state
+#define SET_ERR(fmt, ...) setErrorState( \
+ "%s: " fmt, __FUNCTION__, \
+ ##__VA_ARGS__)
+#define SET_ERR_L(fmt, ...) setErrorStateLocked( \
+ "%s: " fmt, __FUNCTION__, \
+ ##__VA_ARGS__)
+
#include <utils/Log.h>
#include <utils/Trace.h>
#include <utils/Timers.h>
@@ -39,6 +51,8 @@
mId(id),
mHal3Device(NULL),
mStatus(STATUS_UNINITIALIZED),
+ mNextResultFrameNumber(0),
+ mNextShutterFrameNumber(0),
mListener(NULL)
{
ATRACE_CALL();
@@ -69,7 +83,7 @@
ALOGV("%s: Initializing device for camera %d", __FUNCTION__, mId);
if (mStatus != STATUS_UNINITIALIZED) {
- ALOGE("%s: Already initialized!", __FUNCTION__);
+ CLOGE("Already initialized!");
return INVALID_OPERATION;
}
@@ -84,21 +98,18 @@
reinterpret_cast<hw_device_t**>(&device));
if (res != OK) {
- ALOGE("%s: Could not open camera %d: %s (%d)", __FUNCTION__,
- mId, strerror(-res), res);
- mStatus = STATUS_ERROR;
+ SET_ERR_L("Could not open camera: %s (%d)", strerror(-res), res);
return res;
}
/** Cross-check device version */
if (device->common.version != CAMERA_DEVICE_API_VERSION_3_0) {
- ALOGE("%s: Could not open camera %d: "
+ SET_ERR_L("Could not open camera: "
"Camera device is not version %x, reports %x instead",
- __FUNCTION__, mId, CAMERA_DEVICE_API_VERSION_3_0,
+ CAMERA_DEVICE_API_VERSION_3_0,
device->common.version);
device->common.close(&device->common);
- mStatus = STATUS_ERROR;
return BAD_VALUE;
}
@@ -107,11 +118,10 @@
if (res != OK) return res;
if (info.device_version != device->common.version) {
- ALOGE("%s: HAL reporting mismatched camera_info version (%x)"
- " and device version (%x).", __FUNCTION__,
+ SET_ERR_L("HAL reporting mismatched camera_info version (%x)"
+ " and device version (%x).",
device->common.version, info.device_version);
device->common.close(&device->common);
- mStatus = STATUS_ERROR;
return BAD_VALUE;
}
@@ -119,10 +129,9 @@
res = device->ops->initialize(device, this);
if (res != OK) {
- ALOGE("%s: Camera %d: Unable to initialize HAL device: %s (%d)",
- __FUNCTION__, mId, strerror(-res), res);
+ SET_ERR_L("Unable to initialize HAL device: %s (%d)",
+ strerror(-res), res);
device->common.close(&device->common);
- mStatus = STATUS_ERROR;
return BAD_VALUE;
}
@@ -135,10 +144,9 @@
if (mVendorTagOps.get_camera_vendor_section_name != NULL) {
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);
+ SET_ERR_L("Unable to set tag ops: %s (%d)",
+ strerror(-res), res);
device->common.close(&device->common);
- mStatus = STATUS_ERROR;
return res;
}
}
@@ -148,11 +156,10 @@
mRequestThread = new RequestThread(this, device);
res = mRequestThread->run(String8::format("C3Dev-%d-ReqQueue", mId).string());
if (res != OK) {
- ALOGE("%s: Camera %d: Unable to start request queue thread: %s (%d)",
- __FUNCTION__, mId, strerror(-res), res);
+ SET_ERR_L("Unable to start request queue thread: %s (%d)",
+ strerror(-res), res);
device->common.close(&device->common);
mRequestThread.clear();
- mStatus = STATUS_ERROR;
return res;
}
@@ -179,12 +186,12 @@
(mStatus == STATUS_ERROR && mRequestThread != NULL)) {
res = mRequestThread->clearRepeatingRequests();
if (res != OK) {
- ALOGE("%s: Can't stop streaming", __FUNCTION__);
+ SET_ERR_L("Can't stop streaming");
return res;
}
res = waitUntilDrainedLocked();
if (res != OK) {
- ALOGE("%s: Timeout waiting for HAL to drain", __FUNCTION__);
+ SET_ERR_L("Timeout waiting for HAL to drain");
return res;
}
}
@@ -225,6 +232,9 @@
mStatus == STATUS_ACTIVE ? "ACTIVE" :
"Unknown";
lines.appendFormat(" Device status: %s\n", status);
+ if (mStatus == STATUS_ERROR) {
+ lines.appendFormat(" Error cause: %s\n", mErrorCause.string());
+ }
lines.appendFormat(" Stream configuration:\n");
if (mInputStream != NULL) {
@@ -238,8 +248,22 @@
mOutputStreams[i]->dump(fd,args);
}
+ lines = String8(" In-flight requests:\n");
+ if (mInFlightMap.size() == 0) {
+ lines.append(" None\n");
+ } else {
+ for (size_t i = 0; i < mInFlightMap.size(); i++) {
+ InFlightRequest r = mInFlightMap.valueAt(i);
+ lines.appendFormat(" Frame %d | Timestamp: %lld, metadata"
+ " arrived: %s, buffers left: %d\n", mInFlightMap.keyAt(i),
+ r.captureTimestamp, r.haveResultMetadata ? "true" : "false",
+ r.numBuffersLeft);
+ }
+ }
+ write(fd, lines.string(), lines.size());
+
if (mHal3Device != NULL) {
- lines = String8(" HAL device dump:\n");
+ lines = String8(" HAL device dump:\n");
write(fd, lines.string(), lines.size());
mHal3Device->ops->dump(mHal3Device, fd);
}
@@ -251,7 +275,7 @@
ALOGVV("%s: E", __FUNCTION__);
if (CC_UNLIKELY(mStatus == STATUS_UNINITIALIZED ||
mStatus == STATUS_ERROR)) {
- ALOGE("%s: Access to static info %s!", __FUNCTION__,
+ ALOGW("%s: Access to static info %s!", __FUNCTION__,
mStatus == STATUS_ERROR ?
"when in error state" : "before init");
}
@@ -266,23 +290,23 @@
switch (mStatus) {
case STATUS_ERROR:
- ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
+ CLOGE("Device has encountered a serious error");
return INVALID_OPERATION;
case STATUS_UNINITIALIZED:
- ALOGE("%s: Device not initialized", __FUNCTION__);
+ CLOGE("Device not initialized");
return INVALID_OPERATION;
case STATUS_IDLE:
case STATUS_ACTIVE:
// OK
break;
default:
- ALOGE("%s: Unexpected status: %d", __FUNCTION__, mStatus);
+ SET_ERR_L("Unexpected status: %d", mStatus);
return INVALID_OPERATION;
}
sp<CaptureRequest> newRequest = setUpRequestLocked(request);
if (newRequest == NULL) {
- ALOGE("%s: Can't create capture request", __FUNCTION__);
+ CLOGE("Can't create capture request");
return BAD_VALUE;
}
@@ -296,23 +320,23 @@
switch (mStatus) {
case STATUS_ERROR:
- ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
+ CLOGE("Device has encountered a serious error");
return INVALID_OPERATION;
case STATUS_UNINITIALIZED:
- ALOGE("%s: Device not initialized", __FUNCTION__);
+ CLOGE("Device not initialized");
return INVALID_OPERATION;
case STATUS_IDLE:
case STATUS_ACTIVE:
// OK
break;
default:
- ALOGE("%s: Unexpected status: %d", __FUNCTION__, mStatus);
+ SET_ERR_L("Unexpected status: %d", mStatus);
return INVALID_OPERATION;
}
sp<CaptureRequest> newRepeatingRequest = setUpRequestLocked(request);
if (newRepeatingRequest == NULL) {
- ALOGE("%s: Can't create repeating request", __FUNCTION__);
+ CLOGE("Can't create repeating request");
return BAD_VALUE;
}
@@ -330,8 +354,7 @@
if (mStatus == STATUS_IDLE) {
res = configureStreamsLocked();
if (res != OK) {
- ALOGE("%s: Can't set up streams: %s (%d)",
- __FUNCTION__, strerror(-res), res);
+ SET_ERR_L("Can't set up streams: %s (%d)", strerror(-res), res);
return NULL;
}
}
@@ -346,17 +369,17 @@
switch (mStatus) {
case STATUS_ERROR:
- ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
+ CLOGE("Device has encountered a serious error");
return INVALID_OPERATION;
case STATUS_UNINITIALIZED:
- ALOGE("%s: Device not initialized", __FUNCTION__);
+ CLOGE("Device not initialized");
return INVALID_OPERATION;
case STATUS_IDLE:
case STATUS_ACTIVE:
// OK
break;
default:
- ALOGE("%s: Unexpected status: %d", __FUNCTION__, mStatus);
+ SET_ERR_L("Unexpected status: %d", mStatus);
return INVALID_OPERATION;
}
@@ -379,10 +402,10 @@
switch (mStatus) {
case STATUS_ERROR:
- ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
+ CLOGE("Device has encountered a serious error");
return INVALID_OPERATION;
case STATUS_UNINITIALIZED:
- ALOGE("%s: Device not initialized", __FUNCTION__);
+ CLOGE("Device not initialized");
return INVALID_OPERATION;
case STATUS_IDLE:
// OK
@@ -394,13 +417,12 @@
if (res != OK) {
ALOGE("%s: Can't pause captures to reconfigure streams!",
__FUNCTION__);
- mStatus = STATUS_ERROR;
return res;
}
wasActive = true;
break;
default:
- ALOGE("%s: Unexpected status: %d", __FUNCTION__, mStatus);
+ SET_ERR_L("Unexpected status: %d", mStatus);
return INVALID_OPERATION;
}
assert(mStatus == STATUS_IDLE);
@@ -416,8 +438,7 @@
res = mOutputStreams.add(mNextStreamId, newStream);
if (res < 0) {
- ALOGE("%s: Can't add new stream to set: %s (%d)",
- __FUNCTION__, strerror(-res), res);
+ SET_ERR_L("Can't add new stream to set: %s (%d)", strerror(-res), res);
return res;
}
@@ -428,8 +449,8 @@
ALOGV("%s: Restarting activity to reconfigure streams", __FUNCTION__);
res = configureStreamsLocked();
if (res != OK) {
- ALOGE("%s: Can't reconfigure device for new stream %d: %s (%d)",
- __FUNCTION__, mNextStreamId, strerror(-res), res);
+ CLOGE("Can't reconfigure device for new stream %d: %s (%d)",
+ mNextStreamId, strerror(-res), res);
return res;
}
mRequestThread->setPaused(false);
@@ -442,7 +463,7 @@
ATRACE_CALL();
(void)outputId; (void)id;
- ALOGE("%s: Unimplemented", __FUNCTION__);
+ CLOGE("Unimplemented");
return INVALID_OPERATION;
}
@@ -454,23 +475,23 @@
switch (mStatus) {
case STATUS_ERROR:
- ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
+ CLOGE("Device has encountered a serious error");
return INVALID_OPERATION;
case STATUS_UNINITIALIZED:
- ALOGE("%s: Device not initialized!", __FUNCTION__);
+ CLOGE("Device not initialized!");
return INVALID_OPERATION;
case STATUS_IDLE:
case STATUS_ACTIVE:
// OK
break;
default:
- ALOGE("%s: Unexpected status: %d", __FUNCTION__, mStatus);
+ SET_ERR_L("Unexpected status: %d", mStatus);
return INVALID_OPERATION;
}
ssize_t idx = mOutputStreams.indexOfKey(id);
if (idx == NAME_NOT_FOUND) {
- ALOGE("%s: Stream %d is unknown", __FUNCTION__, id);
+ CLOGE("Stream %d is unknown", id);
return idx;
}
@@ -488,24 +509,24 @@
switch (mStatus) {
case STATUS_ERROR:
- ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
+ CLOGE("Device has encountered a serious error");
return INVALID_OPERATION;
case STATUS_UNINITIALIZED:
- ALOGE("%s: Device not initialized", __FUNCTION__);
+ CLOGE("Device not initialized");
return INVALID_OPERATION;
case STATUS_IDLE:
case STATUS_ACTIVE:
// OK
break;
default:
- ALOGE("%s: Unexpected status: %d", __FUNCTION__, mStatus);
+ SET_ERR_L("Unexpected status: %d", mStatus);
return INVALID_OPERATION;
}
ssize_t idx = mOutputStreams.indexOfKey(id);
if (idx == NAME_NOT_FOUND) {
- ALOGE("%s: Stream %d does not exist",
- __FUNCTION__, id);
+ CLOGE("Stream %d does not exist",
+ id);
return BAD_VALUE;
}
@@ -520,7 +541,7 @@
// CameraDevice semantics require device to already be idle before
// deleteStream is called, unlike for createStream.
if (mStatus != STATUS_IDLE) {
- ALOGE("%s: Device not idle", __FUNCTION__);
+ CLOGE("Device not idle");
return INVALID_OPERATION;
}
@@ -531,8 +552,7 @@
} else {
ssize_t idx = mOutputStreams.indexOfKey(id);
if (idx == NAME_NOT_FOUND) {
- ALOGE("%s: Stream %d does not exist",
- __FUNCTION__, id);
+ CLOGE("Stream %d does not exist", id);
return BAD_VALUE;
}
deletedStream = mOutputStreams.editValueAt(idx);
@@ -542,7 +562,7 @@
// Free up the stream endpoint so that it can be used by some other stream
res = deletedStream->disconnect();
if (res != OK) {
- ALOGE("%s: Can't disconnect deleted stream", __FUNCTION__);
+ SET_ERR_L("Can't disconnect deleted stream %d", id);
// fall through since we want to still list the stream as deleted.
}
mDeletedStreams.add(deletedStream);
@@ -554,7 +574,7 @@
ATRACE_CALL();
(void)id;
- ALOGE("%s: Unimplemented", __FUNCTION__);
+ CLOGE("Unimplemented");
return INVALID_OPERATION;
}
@@ -567,24 +587,28 @@
switch (mStatus) {
case STATUS_ERROR:
- ALOGE("%s: Device has encountered a serious error", __FUNCTION__);
+ CLOGE("Device has encountered a serious error");
return INVALID_OPERATION;
case STATUS_UNINITIALIZED:
- ALOGE("%s: Device is not initialized!", __FUNCTION__);
+ CLOGE("Device is not initialized!");
return INVALID_OPERATION;
case STATUS_IDLE:
case STATUS_ACTIVE:
// OK
break;
default:
- ALOGE("%s: Unexpected status: %d", __FUNCTION__, mStatus);
+ SET_ERR_L("Unexpected status: %d", mStatus);
return INVALID_OPERATION;
}
const camera_metadata_t *rawRequest;
rawRequest = mHal3Device->ops->construct_default_request_settings(
mHal3Device, templateId);
- if (rawRequest == NULL) return DEAD_OBJECT;
+ if (rawRequest == NULL) {
+ SET_ERR_L("HAL is unable to construct default settings for template %d",
+ templateId);
+ return DEAD_OBJECT;
+ }
*request = rawRequest;
return OK;
@@ -611,35 +635,31 @@
// Need to shut down
break;
default:
- ALOGE("%s: Unexpected status: %d", __FUNCTION__, mStatus);
+ SET_ERR_L("Unexpected status: %d",mStatus);
return INVALID_OPERATION;
}
if (mRequestThread != NULL) {
res = mRequestThread->waitUntilPaused(kShutdownTimeout);
if (res != OK) {
- ALOGE("%s: Can't stop request thread in %f seconds!",
- __FUNCTION__, kShutdownTimeout/1e9);
- mStatus = STATUS_ERROR;
+ SET_ERR_L("Can't stop request thread in %f seconds!",
+ kShutdownTimeout/1e9);
return res;
}
}
if (mInputStream != NULL) {
res = mInputStream->waitUntilIdle(kShutdownTimeout);
if (res != OK) {
- ALOGE("%s: Can't idle input stream %d in %f seconds!",
- __FUNCTION__, mInputStream->getId(), kShutdownTimeout/1e9);
- mStatus = STATUS_ERROR;
+ SET_ERR_L("Can't idle input stream %d in %f seconds!",
+ mInputStream->getId(), kShutdownTimeout/1e9);
return res;
}
}
for (size_t i = 0; i < mOutputStreams.size(); i++) {
res = mOutputStreams.editValueAt(i)->waitUntilIdle(kShutdownTimeout);
if (res != OK) {
- ALOGE("%s: Can't idle output stream %d in %f seconds!",
- __FUNCTION__, mOutputStreams.keyAt(i),
- kShutdownTimeout/1e9);
- mStatus = STATUS_ERROR;
+ SET_ERR_L("Can't idle output stream %d in %f seconds!",
+ mOutputStreams.keyAt(i), kShutdownTimeout/1e9);
return res;
}
}
@@ -673,8 +693,8 @@
if (res == TIMED_OUT) {
return res;
} else if (res != OK) {
- ALOGE("%s: Camera %d: Error waiting for frame: %s (%d)",
- __FUNCTION__, mId, strerror(-res), res);
+ ALOGW("%s: Camera %d: No frame in %lld ns: %s (%d)",
+ __FUNCTION__, mId, timeout, strerror(-res), res);
return res;
}
}
@@ -761,7 +781,7 @@
ATRACE_CALL();
(void)reprocessStreamId; (void)buffer; (void)listener;
- ALOGE("%s: Unimplemented", __FUNCTION__);
+ CLOGE("Unimplemented");
return INVALID_OPERATION;
}
@@ -782,8 +802,8 @@
if (inputStreams.count > 0) {
if (mInputStream == NULL ||
mInputStream->getId() != inputStreams.data.u8[0]) {
- ALOGE("%s: Request references unknown input stream %d",
- __FUNCTION__, inputStreams.data.u8[0]);
+ CLOGE("Request references unknown input stream %d",
+ inputStreams.data.u8[0]);
return NULL;
}
// Lazy completion of stream configuration (allocation/registration)
@@ -791,10 +811,9 @@
if (mInputStream->isConfiguring()) {
res = mInputStream->finishConfiguration(mHal3Device);
if (res != OK) {
- ALOGE("%s: Unable to finish configuring input stream %d:"
+ SET_ERR_L("Unable to finish configuring input stream %d:"
" %s (%d)",
- __FUNCTION__, mInputStream->getId(),
- strerror(-res), res);
+ mInputStream->getId(), strerror(-res), res);
return NULL;
}
}
@@ -806,15 +825,15 @@
camera_metadata_entry_t streams =
newRequest->mSettings.find(ANDROID_REQUEST_OUTPUT_STREAMS);
if (streams.count == 0) {
- ALOGE("%s: Zero output streams specified!", __FUNCTION__);
+ CLOGE("Zero output streams specified!");
return NULL;
}
for (size_t i = 0; i < streams.count; i++) {
int idx = mOutputStreams.indexOfKey(streams.data.u8[i]);
if (idx == NAME_NOT_FOUND) {
- ALOGE("%s: Request references unknown stream %d",
- __FUNCTION__, streams.data.u8[i]);
+ CLOGE("Request references unknown stream %d",
+ streams.data.u8[i]);
return NULL;
}
sp<Camera3OutputStream> stream = mOutputStreams.editValueAt(idx);
@@ -824,8 +843,8 @@
if (stream->isConfiguring()) {
res = stream->finishConfiguration(mHal3Device);
if (res != OK) {
- ALOGE("%s: Unable to finish configuring stream %d: %s (%d)",
- __FUNCTION__, stream->getId(), strerror(-res), res);
+ SET_ERR_L("Unable to finish configuring stream %d: %s (%d)",
+ stream->getId(), strerror(-res), res);
return NULL;
}
}
@@ -842,7 +861,7 @@
status_t res;
if (mStatus != STATUS_IDLE) {
- ALOGE("%s: Not idle", __FUNCTION__);
+ CLOGE("Not idle");
return INVALID_OPERATION;
}
@@ -859,9 +878,7 @@
camera3_stream_t *inputStream;
inputStream = mInputStream->startConfiguration();
if (inputStream == NULL) {
- ALOGE("%s: Can't start input stream configuration",
- __FUNCTION__);
- // TODO: Make sure the error flow here is correct
+ SET_ERR_L("Can't start input stream configuration");
return INVALID_OPERATION;
}
streams.add(inputStream);
@@ -871,9 +888,7 @@
camera3_stream_t *outputStream;
outputStream = mOutputStreams.editValueAt(i)->startConfiguration();
if (outputStream == NULL) {
- ALOGE("%s: Can't start output stream configuration",
- __FUNCTION__);
- // TODO: Make sure the error flow here is correct
+ SET_ERR_L("Can't start output stream configuration");
return INVALID_OPERATION;
}
streams.add(outputStream);
@@ -887,11 +902,33 @@
res = mHal3Device->ops->configure_streams(mHal3Device, &config);
if (res != OK) {
- ALOGE("%s: Unable to configure streams with HAL: %s (%d)",
- __FUNCTION__, strerror(-res), res);
+ SET_ERR_L("Unable to configure streams with HAL: %s (%d)",
+ strerror(-res), res);
return res;
}
+ // Finish all stream configuration immediately.
+ // TODO: Try to relax this later back to lazy completion, which should be
+ // faster
+
+ if (mInputStream != NULL) {
+ res = mInputStream->finishConfiguration(mHal3Device);
+ if (res != OK) {
+ SET_ERR_L("Can't finish configuring input stream %d: %s (%d)",
+ mInputStream->getId(), strerror(-res), res);
+ return res;
+ }
+ }
+
+ for (size_t i = 0; i < mOutputStreams.size(); i++) {
+ res = mOutputStreams.editValueAt(i)->finishConfiguration(mHal3Device);
+ if (res != OK) {
+ SET_ERR_L("Can't finish configuring output stream %d: %s (%d)",
+ mOutputStreams[i]->getId(), strerror(-res), res);
+ return res;
+ }
+ }
+
// Request thread needs to know to avoid using repeat-last-settings protocol
// across configure_streams() calls
mRequestThread->configurationComplete();
@@ -903,6 +940,59 @@
return OK;
}
+void Camera3Device::setErrorState(const char *fmt, ...) {
+ Mutex::Autolock l(mLock);
+ va_list args;
+ va_start(args, fmt);
+
+ setErrorStateLockedV(fmt, args);
+
+ va_end(args);
+}
+
+void Camera3Device::setErrorStateV(const char *fmt, va_list args) {
+ Mutex::Autolock l(mLock);
+ setErrorStateLockedV(fmt, args);
+}
+
+void Camera3Device::setErrorStateLocked(const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+
+ setErrorStateLockedV(fmt, args);
+
+ va_end(args);
+}
+
+void Camera3Device::setErrorStateLockedV(const char *fmt, va_list args) {
+ // Print out all error messages to log
+ String8 errorCause = String8::formatV(fmt, args);
+ ALOGE("Camera %d: %s", mId, errorCause.string());
+
+ // But only do error state transition steps for the first error
+ if (mStatus == STATUS_ERROR) return;
+
+ mErrorCause = errorCause;
+
+ mRequestThread->setPaused(true);
+ mStatus = STATUS_ERROR;
+}
+
+/**
+ * In-flight request management
+ */
+
+status_t Camera3Device::registerInFlight(int32_t frameNumber,
+ int32_t numBuffers) {
+ ATRACE_CALL();
+ Mutex::Autolock l(mInFlightLock);
+
+ ssize_t res;
+ res = mInFlightMap.add(frameNumber, InFlightRequest(numBuffers));
+ if (res < 0) return res;
+
+ return OK;
+}
/**
* Camera HAL device callback methods
@@ -913,58 +1003,115 @@
status_t res;
- if (result->result == NULL) {
- // TODO: Report error upstream
- ALOGW("%s: No metadata for frame %d", __FUNCTION__,
- result->frame_number);
+ uint32_t frameNumber = result->frame_number;
+ if (result->result == NULL && result->num_output_buffers == 0) {
+ SET_ERR("No result data provided by HAL for frame %d",
+ frameNumber);
return;
}
+ // Get capture timestamp from list of in-flight requests, where it was added
+ // by the shutter notification for this frame. Then update the in-flight
+ // status and remove the in-flight entry if all result data has been
+ // received.
nsecs_t timestamp = 0;
+ {
+ Mutex::Autolock l(mInFlightLock);
+ ssize_t idx = mInFlightMap.indexOfKey(frameNumber);
+ if (idx == NAME_NOT_FOUND) {
+ SET_ERR("Unknown frame number for capture result: %d",
+ frameNumber);
+ return;
+ }
+ InFlightRequest &request = mInFlightMap.editValueAt(idx);
+ timestamp = request.captureTimestamp;
+ if (timestamp == 0) {
+ SET_ERR("Called before shutter notify for frame %d",
+ frameNumber);
+ return;
+ }
+
+ if (result->result != NULL) {
+ if (request.haveResultMetadata) {
+ SET_ERR("Called multiple times with metadata for frame %d",
+ frameNumber);
+ return;
+ }
+ request.haveResultMetadata = true;
+ }
+
+ request.numBuffersLeft -= result->num_output_buffers;
+
+ if (request.numBuffersLeft < 0) {
+ SET_ERR("Too many buffers returned for frame %d",
+ frameNumber);
+ return;
+ }
+
+ if (request.haveResultMetadata && request.numBuffersLeft == 0) {
+ mInFlightMap.removeItemsAt(idx, 1);
+ }
+
+ // Sanity check - if we have too many in-flight frames, something has
+ // likely gone wrong
+ if (mInFlightMap.size() > kInFlightWarnLimit) {
+ CLOGE("In-flight list too large: %d", mInFlightMap.size());
+ }
+
+ }
+
AlgState cur3aState;
AlgState new3aState;
int32_t aeTriggerId = 0;
int32_t afTriggerId = 0;
- NotificationListener *listener;
+ NotificationListener *listener = NULL;
- {
+ // Process the result metadata, if provided
+ if (result->result != NULL) {
Mutex::Autolock l(mOutputLock);
- // Push result metadata into queue
- mResultQueue.push_back(CameraMetadata());
- // Lets avoid copies! Too bad there's not a #back method
- CameraMetadata &captureResult = *(--mResultQueue.end());
+ if (frameNumber != mNextResultFrameNumber) {
+ SET_ERR("Out-of-order capture result metadata submitted! "
+ "(got frame number %d, expecting %d)",
+ frameNumber, mNextResultFrameNumber);
+ return;
+ }
+ mNextResultFrameNumber++;
+
+ CameraMetadata &captureResult =
+ *mResultQueue.insert(mResultQueue.end(), CameraMetadata());
captureResult = result->result;
if (captureResult.update(ANDROID_REQUEST_FRAME_COUNT,
- (int32_t*)&result->frame_number, 1) != OK) {
- ALOGE("%s: Camera %d: Failed to set frame# in metadata (%d)",
- __FUNCTION__, mId, result->frame_number);
- // TODO: Report error upstream
+ (int32_t*)&frameNumber, 1) != OK) {
+ SET_ERR("Failed to set frame# in metadata (%d)",
+ frameNumber);
} else {
ALOGVV("%s: Camera %d: Set frame# in metadata (%d)",
- __FUNCTION__, mId, result->frame_number);
+ __FUNCTION__, mId, frameNumber);
}
- // Get timestamp from result metadata
+ // Check that there's a timestamp in the result metadata
camera_metadata_entry entry =
captureResult.find(ANDROID_SENSOR_TIMESTAMP);
if (entry.count == 0) {
- ALOGE("%s: Camera %d: No timestamp provided by HAL for frame %d!",
- __FUNCTION__, mId, result->frame_number);
- // TODO: Report error upstream
- } else {
- timestamp = entry.data.i64[0];
+ SET_ERR("No timestamp provided by HAL for frame %d!",
+ frameNumber);
+ }
+ if (timestamp != entry.data.i64[0]) {
+ SET_ERR("Timestamp mismatch between shutter notify and result"
+ " metadata for frame %d (%lld vs %lld respectively)",
+ frameNumber, timestamp, entry.data.i64[0]);
}
// Get 3A states from result metadata
entry = captureResult.find(ANDROID_CONTROL_AE_STATE);
if (entry.count == 0) {
- ALOGE("%s: Camera %d: No AE state provided by HAL for frame %d!",
- __FUNCTION__, mId, result->frame_number);
+ CLOGE("No AE state provided by HAL for frame %d!",
+ frameNumber);
} else {
new3aState.aeState =
static_cast<camera_metadata_enum_android_control_ae_state>(
@@ -973,8 +1120,8 @@
entry = captureResult.find(ANDROID_CONTROL_AF_STATE);
if (entry.count == 0) {
- ALOGE("%s: Camera %d: No AF state provided by HAL for frame %d!",
- __FUNCTION__, mId, result->frame_number);
+ CLOGE("No AF state provided by HAL for frame %d!",
+ frameNumber);
} else {
new3aState.afState =
static_cast<camera_metadata_enum_android_control_af_state>(
@@ -983,8 +1130,8 @@
entry = captureResult.find(ANDROID_CONTROL_AWB_STATE);
if (entry.count == 0) {
- ALOGE("%s: Camera %d: No AWB state provided by HAL for frame %d!",
- __FUNCTION__, mId, result->frame_number);
+ CLOGE("No AWB state provided by HAL for frame %d!",
+ frameNumber);
} else {
new3aState.awbState =
static_cast<camera_metadata_enum_android_control_awb_state>(
@@ -993,16 +1140,16 @@
entry = captureResult.find(ANDROID_CONTROL_AF_TRIGGER_ID);
if (entry.count == 0) {
- ALOGE("%s: Camera %d: No AF trigger ID provided by HAL for frame %d!",
- __FUNCTION__, mId, result->frame_number);
+ CLOGE("No AF trigger ID provided by HAL for frame %d!",
+ frameNumber);
} else {
afTriggerId = entry.data.i32[0];
}
entry = captureResult.find(ANDROID_CONTROL_AE_PRECAPTURE_ID);
if (entry.count == 0) {
- ALOGE("%s: Camera %d: No AE precapture trigger ID provided by HAL"
- " for frame %d!", __FUNCTION__, mId, result->frame_number);
+ CLOGE("No AE precapture trigger ID provided by HAL"
+ " for frame %d!", frameNumber);
} else {
aeTriggerId = entry.data.i32[0];
}
@@ -1013,7 +1160,8 @@
m3AState = new3aState;
} // scope for mOutputLock
- // Return completed buffers to their streams
+ // Return completed buffers to their streams with the timestamp
+
for (size_t i = 0; i < result->num_output_buffers; i++) {
Camera3Stream *stream =
Camera3Stream::cast(result->output_buffers[i].stream);
@@ -1021,23 +1169,22 @@
// Note: stream may be deallocated at this point, if this buffer was the
// last reference to it.
if (res != OK) {
- ALOGE("%s: Camera %d: Can't return buffer %d for frame %d to its"
- " stream:%s (%d)", __FUNCTION__, mId, i,
- result->frame_number, strerror(-res), res);
- // TODO: Report error upstream
+ SET_ERR("Can't return buffer %d for frame %d to its stream: "
+ " %s (%d)", i, frameNumber, strerror(-res), res);
}
}
- // Dispatch any 3A change events to listeners
- if (listener != NULL) {
+ // Finally, dispatch any 3A change events to listeners if we got metadata
+
+ if (result->result != NULL && listener != NULL) {
if (new3aState.aeState != cur3aState.aeState) {
ALOGVV("%s: AE state changed from 0x%x to 0x%x",
- __FUNCTION__, cur3aState.aeState, new3aState.aeState);
+ __FUNCTION__, cur3aState.aeState, new3aState.aeState);
listener->notifyAutoExposure(new3aState.aeState, aeTriggerId);
}
if (new3aState.afState != cur3aState.afState) {
ALOGVV("%s: AF state changed from 0x%x to 0x%x",
- __FUNCTION__, cur3aState.afState, new3aState.afState);
+ __FUNCTION__, cur3aState.afState, new3aState.afState);
listener->notifyAutoFocus(new3aState.afState, afTriggerId);
}
if (new3aState.awbState != cur3aState.awbState) {
@@ -1051,13 +1198,11 @@
NotificationListener *listener;
{
Mutex::Autolock l(mOutputLock);
- if (mListener == NULL) return;
listener = mListener;
}
if (msg == NULL) {
- ALOGE("%s: Camera %d: HAL sent NULL notify message!",
- __FUNCTION__, mId);
+ SET_ERR("HAL sent NULL notify message!");
return;
}
@@ -1070,18 +1215,51 @@
msg->message.error.error_stream);
streamId = stream->getId();
}
- listener->notifyError(msg->message.error.error_code,
- msg->message.error.frame_number, streamId);
+ if (listener != NULL) {
+ listener->notifyError(msg->message.error.error_code,
+ msg->message.error.frame_number, streamId);
+ }
break;
}
case CAMERA3_MSG_SHUTTER: {
- listener->notifyShutter(msg->message.shutter.frame_number,
- msg->message.shutter.timestamp);
+ ssize_t idx;
+ uint32_t frameNumber = msg->message.shutter.frame_number;
+ nsecs_t timestamp = msg->message.shutter.timestamp;
+ // Verify ordering of shutter notifications
+ {
+ Mutex::Autolock l(mOutputLock);
+ if (frameNumber != mNextShutterFrameNumber) {
+ SET_ERR("Shutter notification out-of-order. Expected "
+ "notification for frame %d, got frame %d",
+ mNextShutterFrameNumber, frameNumber);
+ break;
+ }
+ mNextShutterFrameNumber++;
+ }
+
+ // Set timestamp for the request in the in-flight tracking
+ {
+ Mutex::Autolock l(mInFlightLock);
+ idx = mInFlightMap.indexOfKey(frameNumber);
+ if (idx >= 0) {
+ mInFlightMap.editValueAt(idx).captureTimestamp = timestamp;
+ }
+ }
+ if (idx < 0) {
+ SET_ERR("Shutter notification for non-existent frame number %d",
+ frameNumber);
+ break;
+ }
+
+ // Call listener, if any
+ if (listener != NULL) {
+ listener->notifyShutter(frameNumber, timestamp);
+ }
break;
}
default:
- ALOGE("%s: Camera %d: Unknown notify message from HAL: %d",
- __FUNCTION__, mId, msg->type);
+ SET_ERR("Unknown notify message from HAL: %d",
+ msg->type);
}
}
@@ -1094,6 +1272,7 @@
Thread(false),
mParent(parent),
mHal3Device(hal3Device),
+ mId(getId(parent)),
mReconfigured(false),
mDoPause(false),
mPaused(true),
@@ -1133,6 +1312,12 @@
return OK;
}
+int Camera3Device::RequestThread::getId(const wp<Camera3Device> &device) {
+ sp<Camera3Device> d = device.promote();
+ if (d != NULL) return d->mId;
+ return 0;
+}
+
status_t Camera3Device::RequestThread::queueTriggerLocked(
RequestTrigger trigger) {
@@ -1145,9 +1330,8 @@
case TYPE_INT32:
break;
default:
- ALOGE("%s: Type not supported: 0x%x",
- __FUNCTION__,
- trigger.getTagType());
+ ALOGE("%s: Type not supported: 0x%x", __FUNCTION__,
+ trigger.getTagType());
return INVALID_OPERATION;
}
@@ -1240,9 +1424,9 @@
int32_t triggerCount;
res = insertTriggers(nextRequest);
if (res < 0) {
- ALOGE("RequestThread: Unable to insert triggers "
- "(capture request %d, HAL device: %s (%d)",
- (mFrameNumber+1), strerror(-res), res);
+ SET_ERR("RequestThread: Unable to insert triggers "
+ "(capture request %d, HAL device: %s (%d)",
+ (mFrameNumber+1), strerror(-res), res);
cleanUpFailedRequest(request, nextRequest, outputBuffers);
return false;
}
@@ -1289,7 +1473,7 @@
request.input_buffer = &inputBuffer;
res = nextRequest->mInputStream->getBuffer(&inputBuffer);
if (res != OK) {
- ALOGE("RequestThread: Can't get input buffer, skipping request:"
+ SET_ERR("RequestThread: Can't get input buffer, skipping request:"
" %s (%d)", strerror(-res), res);
cleanUpFailedRequest(request, nextRequest, outputBuffers);
return true;
@@ -1305,7 +1489,7 @@
res = nextRequest->mOutputStreams.editItemAt(i)->
getBuffer(&outputBuffers.editItemAt(i));
if (res != OK) {
- ALOGE("RequestThread: Can't get output buffer, skipping request:"
+ SET_ERR("RequestThread: Can't get output buffer, skipping request:"
"%s (%d)", strerror(-res), res);
cleanUpFailedRequest(request, nextRequest, outputBuffers);
return true;
@@ -1315,12 +1499,28 @@
request.frame_number = mFrameNumber++;
+ // Log request in the in-flight queue
+ sp<Camera3Device> parent = mParent.promote();
+ if (parent == NULL) {
+ CLOGE("RequestThread: Parent is gone");
+ cleanUpFailedRequest(request, nextRequest, outputBuffers);
+ return false;
+ }
+
+ res = parent->registerInFlight(request.frame_number,
+ request.num_output_buffers);
+ if (res != OK) {
+ SET_ERR("RequestThread: Unable to register new in-flight request:"
+ " %s (%d)", strerror(-res), res);
+ cleanUpFailedRequest(request, nextRequest, outputBuffers);
+ return false;
+ }
// Submit request and block until ready for next one
res = mHal3Device->ops->process_capture_request(mHal3Device, &request);
if (res != OK) {
- ALOGE("RequestThread: Unable to submit capture request %d to HAL"
+ SET_ERR("RequestThread: Unable to submit capture request %d to HAL"
" device: %s (%d)", request.frame_number, strerror(-res), res);
cleanUpFailedRequest(request, nextRequest, outputBuffers);
return false;
@@ -1333,7 +1533,7 @@
// Remove any previously queued triggers (after unlock)
res = removeTriggers(mPrevRequest);
if (res != OK) {
- ALOGE("RequestThread: Unable to remove triggers "
+ SET_ERR("RequestThread: Unable to remove triggers "
"(capture request %d, HAL device: %s (%d)",
request.frame_number, strerror(-res), res);
return false;
@@ -1378,7 +1578,6 @@
nextRequest->mOutputStreams.editItemAt(i)->returnBuffer(
outputBuffers[i], 0);
}
- // TODO: Report error upstream
}
sp<Camera3Device::CaptureRequest>
@@ -1462,6 +1661,18 @@
return false;
}
+void Camera3Device::RequestThread::setErrorState(const char *fmt, ...) {
+ sp<Camera3Device> parent = mParent.promote();
+ if (parent != NULL) {
+ va_list args;
+ va_start(args, fmt);
+
+ parent->setErrorStateV(fmt, args);
+
+ va_end(args);
+ }
+}
+
status_t Camera3Device::RequestThread::insertTriggers(
const sp<CaptureRequest> &request) {
diff --git a/services/camera/libcameraservice/Camera3Device.h b/services/camera/libcameraservice/Camera3Device.h
index 7f294e6..6cad08e 100644
--- a/services/camera/libcameraservice/Camera3Device.h
+++ b/services/camera/libcameraservice/Camera3Device.h
@@ -108,7 +108,8 @@
buffer_handle_t *buffer, wp<BufferReleasedListener> listener);
private:
- static const nsecs_t kShutdownTimeout = 5000000000; // 5 sec
+ static const size_t kInFlightWarnLimit = 20;
+ static const nsecs_t kShutdownTimeout = 5000000000; // 5 sec
struct RequestTrigger;
Mutex mLock;
@@ -128,6 +129,9 @@
STATUS_ACTIVE
} mStatus;
+ // Tracking cause of fatal errors when in STATUS_ERROR
+ String8 mErrorCause;
+
// Mapping of stream IDs to stream instances
typedef KeyedVector<int, sp<camera3::Camera3OutputStream> > StreamSet;
@@ -172,6 +176,16 @@
*/
status_t configureStreamsLocked();
+ /**
+ * Set device into an error state due to some fatal failure, and set an
+ * error message to indicate why. Only the first call's message will be
+ * used. The message is also sent to the log.
+ */
+ void setErrorState(const char *fmt, ...);
+ void setErrorStateV(const char *fmt, va_list args);
+ void setErrorStateLocked(const char *fmt, ...);
+ void setErrorStateLockedV(const char *fmt, va_list args);
+
struct RequestTrigger {
// Metadata tag number, e.g. android.control.aePrecaptureTrigger
uint32_t metadataTag;
@@ -249,6 +263,8 @@
virtual bool threadLoop();
private:
+ static int getId(const wp<Camera3Device> &device);
+
status_t queueTriggerLocked(RequestTrigger trigger);
// Mix-in queued triggers into this request
int32_t insertTriggers(const sp<CaptureRequest> &request);
@@ -272,9 +288,14 @@
// Pause handling
bool waitIfPaused();
+ // Relay error to parent device object setErrorState
+ void setErrorState(const char *fmt, ...);
+
wp<Camera3Device> mParent;
camera3_device_t *mHal3Device;
+ const int mId;
+
Mutex mRequestLock;
Condition mRequestSignal;
RequestList mRequestQueue;
@@ -292,7 +313,7 @@
sp<CaptureRequest> mPrevRequest;
int32_t mPrevTriggers;
- int32_t mFrameNumber;
+ uint32_t mFrameNumber;
Mutex mLatestRequestMutex;
Condition mLatestRequestSignal;
@@ -308,6 +329,39 @@
sp<RequestThread> mRequestThread;
/**
+ * In-flight queue for tracking completion of capture requests.
+ */
+
+ struct InFlightRequest {
+ // Set by notify() SHUTTER call.
+ nsecs_t captureTimestamp;
+ // Set by process_capture_result call with valid metadata
+ bool haveResultMetadata;
+ // Decremented by calls to process_capture_result with valid output
+ // buffers
+ int numBuffersLeft;
+
+ InFlightRequest() :
+ captureTimestamp(0),
+ haveResultMetadata(false),
+ numBuffersLeft(0) {
+ }
+
+ explicit InFlightRequest(int numBuffers) :
+ captureTimestamp(0),
+ haveResultMetadata(false),
+ numBuffersLeft(numBuffers) {
+ }
+ };
+ // Map from frame number to the in-flight request state
+ typedef KeyedVector<uint32_t, InFlightRequest> InFlightMap;
+
+ Mutex mInFlightLock; // Protects mInFlightMap
+ InFlightMap mInFlightMap;
+
+ status_t registerInFlight(int32_t frameNumber, int32_t numBuffers);
+
+ /**
* Output result queue and current HAL device 3A state
*/
@@ -316,6 +370,8 @@
/**** Scope for mOutputLock ****/
+ uint32_t mNextResultFrameNumber;
+ uint32_t mNextShutterFrameNumber;
List<CameraMetadata> mResultQueue;
Condition mResultSignal;
NotificationListener *mListener;
diff --git a/services/medialog/Android.mk b/services/medialog/Android.mk
index 559b1ed..08006c8 100644
--- a/services/medialog/Android.mk
+++ b/services/medialog/Android.mk
@@ -4,7 +4,7 @@
LOCAL_SRC_FILES := MediaLogService.cpp
-LOCAL_SHARED_LIBRARIES := libmedia libbinder libutils libnbaio
+LOCAL_SHARED_LIBRARIES := libmedia libbinder libutils liblog libnbaio
LOCAL_MODULE:= libmedialogservice
diff --git a/services/medialog/MediaLogService.cpp b/services/medialog/MediaLogService.cpp
index f60749d..683fdf3 100644
--- a/services/medialog/MediaLogService.cpp
+++ b/services/medialog/MediaLogService.cpp
@@ -60,7 +60,9 @@
static const String16 sDump("android.permission.DUMP");
if (!(IPCThreadState::self()->getCallingUid() == AID_MEDIA ||
PermissionCache::checkCallingPermission(sDump))) {
- fdprintf(fd, "Permission denied.\n");
+ fdprintf(fd, "Permission Denial: can't dump media.log from pid=%d, uid=%d\n",
+ IPCThreadState::self()->getCallingPid(),
+ IPCThreadState::self()->getCallingUid());
return NO_ERROR;
}